TWAIN-- Standard for image acquisition devices.

Technical Support

If you have a question or technical issue that isn’t answered on this page, ask the entire TWAIN community at http://www.twainforum.org.

You may also search the TWAIN Mailing List Archives at: http://services2k.jflinc.com/twain/?

FAQ

The following questions are the result of sorting through questions posted on the TWAIN Developers mailing list and discussions with TWAIN Working Group members. The intention is to clear-up any implementation issues before the TWAIN Working Group imposes TWAIN Compliance guidelines.

= represents Microsoft Windows only

 

Question: What is a GUID?

Answer: A globally unique identifier or GUID is a special type of identifier used in software applications in order to provide a reference number which is unique in any context (hence, "globally"). For example, in defining the internal reference for a type of access point in a software application, or for creating unique keys in a database. While each generated GUID is not guaranteed to be unique, the total number of unique keys (2128 or 3.4×1038) is so large that the probability of the same number being generated twice is infinitesimally small.

 

Question: How do I create a GUID?

Answer: To create a GUID you should Google “create a GUID” and follow the directions given.

 

Question: What is TWAIN an acronym for?

Answer: An image capture API for Microsoft Windows and Apple Macintosh operating systems. The standard was first released in 1992, and is currently ratified at version 1.9 as of January 2000. TWAIN is typically used as an interface between image processing software and a scanner or digital camera.

The word TWAIN is from Kipling's "The Ballad of East and West" - "...and never the twain shall meet...", reflecting the difficulty, at the time, of connecting scanners and personal computers. It was up-cased to TWAIN to make it more distinctive. This led people to believe it was an acronym, and then to a contest to come up with an expansion. None were selected, but the entry "Technology Without An Interesting Name" continues to haunt the standard. "

(Borrowed with permission from The Free On-Line Dictionary of Computing).

 

Question: Where do I get updated scanner drivers for Windows 95, 98, NT, 2000, Me, and XP, as well as MacIntosh drivers?

Answer: You need to get the driver for your device from the scanner or digital camera vendor.  The TWAIN Working Group does not maintain any scanner or digital camera drivers. Normally vendors make the drivers available at no charge from their Web sites. There are some vendors and other inclusive Web sites that make many different drivers available listed on our drivers page.

 

Question: Is there a royality/license fee to implement TWAIN?

Answer: TWAIN is free to use in your application or data source. The TWAIN Working Group asks that you make your applications and drivers adhere to the TWAIN Specification.  You may read the TWAIN License online.

 

Question: I lost the driver diskette or CD that came with my scanner or digital camera. Where can I get the TWAIN Driver for my device?

Answer: You need to get the driver for your device from the scanner or digital camera vendor.  The TWAIN Working Group does not maintain any scanner or digital camera drivers. Normally vendors make the drivers available at no charge from their Web sites. There are some vendors and other inclusive Web sites that make many different drivers available listed on our drivers page.

 

Question: My digital camera or scanner is not listed when I try to download an image from the device.

Answer: Your computer is not seeing the device, probably because the driver is not properly installed. Re-install the driver for your device following the manufacturer's instructions and then reboot your computer. (See our Drivers page for more information on where to find your driver.) If you still cannot acquire the image, then call the manufacturer of the device and ask them to guide you through the process of configuring your computer to work with their device.

 

Question: Who dictates container type during MSG_GET/MSG_GETCURRENT/MSG_GETDEFAULT?

Answer: Container types are dictated by the Data Source in all cases where a value is queried.

 

Question: What containers are allowed for each capability?

Answer: The allowable container types of each capability are clearly defined in Chapter 9 of the TWAIN Specification.

 

Question: Can the application ever specify a container type?

Answer: The only time it is appropriate for the calling Application to specify a container type is during the MSG_SET operation. At that time, the Application must also consider the allowable containers and types for the particular capability.

 

Question: What are TWAIN Types hold Strings?

Answer: There are 4 types of TWAIN strings defined for developer use:

TW_STR32

TW_STR64

TW_STR128

TW_STR256

 

Question: What types of TWAIN Containers can hold Strings?

Answer: The only containers that can possibly hold a string are the following:

TW_ENUMERATION

TW_ARRAY

TW_ONEVALUE

It is not possible or useful to use this type in a TW_RANGE, in fact there is no case where a capability has been defined in Chapter 9 of the TWAIN Specification where a TW_RANGE is allowed for a TW_STRXXX type of value.

 

Question: What TWAIN Capabilities use String Values?

Answer: As of version 1.9, only the following capabilities accept strings:

CAP_AUTHOR, TW_ONEVALUE, TW_STR128<

CAP_CAPTION, TW_ONEVALUE, TW_STR255

CAP_TIMEDATE, TW_ONEVALUE, TW_STR32

CAP_DEVICETIMEDATE, TW_ONEVALUE, TW_STR32

CAP_PRINTERSTRING, TW_ONEVALUE/TW_ENUMERATION, TW_STR255

CAP_PRINTERSUFFIX, TW_ONEVALUE, TW_STR255

CAP_SERIALNUMBER, TW_ONEVALUE, TW_STR255

ICAP_HALFTONES, TW_ONEVALUE/TW_ENUMERATION/TW_ARRAY, TW_STR32

 

Question: What would a TW_ONEVALUE holding a string look like?

Answer: If you were to redefine the TW_ONEVALUE container to hold a string, it would look like this structurally.

/* TWON_ONEVALUESTR32. Container for one value holding TW_STR32. */
typedef struct {
    TW_UINT16 ItemType;
    TW_STR32 Item;
} TW_ONEVALUESTR32, FAR * pTW_ONEVALUESTR32;

(Note: pay attention to 2 byte structure packing when defining custom container structures)

 

Question: How would I allocate a container with strings without redefining the structure?

Answer: The following function demonstrates how you would allocate and fill a string container using the TWAIN Structures already defined by TWAIN.

HGLOBAL AllocateAndFillOneValueStr32( const pTW_STR32 pInString )
{
                DWORD dwContainerSize = 0l;
                HGLOBAL hContainer = NULL;
                pTW_ONEVALUE pOneValue = NULL;
                pTW_STR32 pString = NULL;

                assert(pInString);

                // note: this calculation will yield a size approximately one pointer

               // larger than that required for this container (sizeof(TW_UINT32)). For

               // simplicity the size difference is negligible. The first TW_STR32 item shall

                // be located immediately after the pEnum->DefaultIndex member.

                dwContainerSize = sizeof(TW_ONEVALUE) + sizeof(TW_STR32);
                hContainer = GlobalAlloc( GPTR, dwContainerSize );
                if(hContainer)
                {
                                pOneValue = (pTW_ONEVALUE)GlobalLock(hContainer);
                                if(pOneValue)
                                {
                                                pOneValue->ItemType = TWTY_STR32;
                                                pString = (pTW_STR32)&pOneValue->Item;

                                                memcpy(pString, pInString, sizeof(TW_STR32));

                                                GlobalUnlock(hContainer);
                                                pOneValue = NULL;
                                                pString = NULL;
                                }
                }
                return hContainer;
}

 

Question: How could I put strings in a TW_ENUMERATION Container?

Answer: The following example demonstrates the creation of an enumeration to hold a certain number of TW_STR32 type strings.

HGLOBAL AllocateEnumerationStr32( TW_UINT32 unNumItems )
{
                DWORD dwContainerSize = 0l;
                HGLOBAL hContainer = NULL;
                pTW_ENUMERATION pEnum = NULL;

                // note: this calculation will yield a size approximately one pointer
                // larger than that required for this container (sizeof(pTW_UINT8)). For
                // simplicity the size difference is negligible. The first TW_STR32 item shall
                // be located immediately after the pEnum->DefaultIndex member.
                dwContainerSize = sizeof(TW_ENUMERATION) + ( sizeof(TW_STR32) * unNumItems);

                hContainer = GlobalAlloc( GPTR, dwContainerSize );
                if(hContainer)
                {
                                pEnum = (pTW_ENUMERATION) GlobalLock(hContainer);
                                if(pEnum)
                                {
                                                pEnum->ItemType = TWTY_STR32;
                                                pEnum->NumItems = unNumItems;

                                                GlobalUnlock(hContainer);
                                                pEnum = NULL;
                                }
                 }
                return hContainer;
}

 

Question: How do I index strings found in an TW_ENUMERATION?

Answer: The following function demonstrates the indexing of a string found in an enumeration container.

pTW_STR128 IndexStr128FromEnumeration( pTW_ENUMERATION pEnum, TW_UINT32 unIndex)
{
                BYTE *pBegin = (BYTE *)&pEnum->ItemList[0];
                assert(pEnum->NumItems > unIndex);
                assert(pEnum->ItemType == TWTY_STR128);

                pBegin += (unIndex * sizeof(TW_STR128));
                return (pTW_STR128)pBegin;
}

Question: How do I deal with "Current" and "Default" and "Preferred" Capability Values?

Answer: Often it is assumed that the "Current" and "Default" capabilities are going to be the same when a Data Source is opened. This assumption is not correct. This assumption would make it impossible for a Data Source to store and restore settings between sessions as a convenience for the user.

A better way to look at it, would be that "Default" Capability values indicate what value will be used if you issue a MSG_RESET operation.

The "Current" value may be set to a "Preferred" or to a previously stored value.

 

Question: How can I store Scan Parameters from one session and restore them in another?

Answer:

1. User configures the Data Source User Interface with the following Parameters: 4x6 inch image in 24bit at 200 DPI X and Y Resolution

2. User selects "Scan" and Data Source Signals Application to transfer

3. Application Acquires the image successfully

4. Application Disables the Data Source

5. Application inquires during State 4 the Current values of Frame, Pixel Type, Bit Depth, and Resolution

6. Data Source reports to each inquiry the current values that were set by the user: 4x6 inch image in 24bit at 200 DPI X and Y resolution

7. Application Closes the Data Source

8. During Close procedure, the Data Source stores the current Frame, Pixel Type, Bit Depth and Resolution

9. Application Opens Data Source

10. During Open procedure, the Data Source restores current Frame, Pixel Type, Bit Depth and Resolution

11. Application inquires during State 4 the Current values of Frame, Pixel Type, Bit Depth, and Resolution

12. Data Source reports to each inquiry the current values that were restored from previous session: 4x6 inch image in 24bit at 200 DPI X and Y resolution in one session

 

Question: How can the Data Source represent the preferred Pixel Flavor without compromising TWAIN Defined Default value?

Answer:

1. Application opens Data Source for the first time

2. Application inquires during State 4 about the Default Pixel Flavor

3. Data Source reports that the Default Pixel Flavor is TWPF_CHOCOLATE (spec chapter 9)

4. tabApplication inquires during State 4 about the Current Pixel Flavor

5. tabData Source reports that the Current Pixel Flavor is TWPF_VANILLA (because this device returns data in that gender natively)

6. tabApplication issues Reset to Current Pixel Flavor

7. tabDuring reset operation, Data Source changes current value to TWPF_CHOCOLATE and prepares to invert data during transfer to accommodate the calling Application request

 

Question: Does this work in all conditions?

Answer: No. If a capability is constrained and the "Default" value is not in the constrained list, and the Data Source is supposed to respond to MSG_GET with a TW_ENUMERATION, then it cannot possibly report a valid Default Index. In this case it is safer for the Data Source to provide some valid index. When MSG_RESET is issued, the constraints will be lifted and the Default Index can once again be reported correctly.

 

Question: How does a Data Source respond to MSG_RESET?

Answer: It is known that this call resets the current value of the requested Capability to the default. It must also be stated that this call will also reset any Application imposed constraints upon the requested Capability.

Question: How does a Data Source respond to MSG_GETCURRENT, and MSG_GETDEFAULT?

Answer: It is intuitive to assume that this message should not be supported by Capabilities that have no Current or Default value. However the spec says otherwise in chapter 9 (a good example is ICAP_SUPPORTEDCAPS). In this case, it makes sense to simply respond to these messages in the same manner as MSG_GET.

It can also be assumed, that it is more intuitive for a Data Source to respond to this capability with a TW_ONEVALUE container in all cases that a TW_ONEVALUE container is allowed.

 

Question: How does a Data Source respond to a MSG_GET?

Answer: If an Application has constrained the current capability, then the Data Source response to this message should reflect those constraints. Otherwise, this should respond with all the values that the Data Source supports. Of course, the number of values that can be placed in the response are restricted by the allowed containers for the particular current capability outlined in chapter 9.

 

Question: Why does my application deadlock with some Data Sources?

Answer: It is possible that during execution of any triplet that the Data Source will fail unexpectedly. It is very important that Applications pay attention to the TWAIN State of the Data Source at the time of failure. A hanging or deadlock condition will occur if the Application fails to recover from error conditions with the proper state transitions. Most error handling is fairly obvious, however the following items have been mishandled in the past.

 

Question: How do I know if transition to State 5 has really happened?

Answer: A Data Source may fail a call to DG_CONTROL / DAT_USERINTERFACE / MSG_ENABLEDS unexpectedly. It is important to note that if an Application requests the User Interface be suppressed, and the Data Source returns a code of TWRC_CHECKSTATUS, this means only that User Interface suppression was not possible. The transition to State 5 still occurred. If the Application does not like this condition, then it may call MSG_DISABLEDS to close the Data Source without further user interaction. A return code of TWRC_FAILURE indicates that the transition to State 5 has not occurred.

 

Question: If there’s an error during image transfer, how do I get back to State 5?

Answer: It is important to be aware that when an error occurs during image transfer, a state transition to State 5 is not implicit. A call to DG_CONTROL / DAT_PENDINGXFERS / MSG_RESET or MSG_ENDXFER is required for a state transition back to State 5. If an Application calls MSG_DISABLEDS immediately after such a failure without first making the required calls to DAT_PENDINGXFERS, the resulting behavior of the Data Source will not be predictable. The Data Source should fail any call to MSG_DISABLEDS outside of State 5.

 

Question: How do I resolve conflict between changing ICAP_FRAMES, ICAP_SUPPORTEDSIZES, DAT_IMAGELAYOUT?

Answer: Since there are several ways to negotiate the scan area, it becomes confusing when deciding what should take precedence. It is logical to assume that the last method used to set the frame will dictate the current frame. However, it may still be confusing to decide how that is represented during a MSG_GET operation for any of the three methods. The following behavior is suggested.

Note: Frame Extents are only limited by ICAP_PHYSICALWIDTH and ICAP_PHYSICALHEIGHT. Setting ICAP_SUPPORTEDSIZES does NOT imply a new extent limitation. TWSS_XXXX sizes are simply predefined fixed Frame sizes.

  • If the frame is set in DAT_IMAGELAYOUT

- ICAP_FRAMES shall respond to MSG_GETCURRENT with the dimensions of the frame set in the DAT_IMAGELAYOUT call.

- ICAP_SUPPORTEDSIZES shall respond to MSG_GETCURRENT with TWSS_NONE

  • If the current frame is set from ICAP_FRAMES

- DAT_IMAGELAYOUT shall respond with the dimensions of the current frame set in ICAP_FRAMES

- ICAP_SUPPORTEDSIZES shall respond to MSG_GETCURRENT with TWSS_NONE

  • If the current fixed frame is set from ICAP_SUPPORTEDSIZES

- DAT_IMAGELAYOUT shall respond to MSG_GET with the dimensions of the fixed frame specified in ICAP_SUPPORTEDSIZES

- ICAP_FRAMES shall respond to MSG_GETCURRENT with the dimensions of the fixed frame specified in ICAP_SUPPORTEDSIZES

 

Question: What effect does ICAP_ROTATION, ICAP_ORIENTATION have on ICAP_FRAMES, DAT_IMAGELAYOUT, DAT_IMAGEINFO?

Answer: There is considerable confusion when trying to resolve the affect of Rotation and Orientation on the current Frames and Image Layout. After careful consideration of the specification it has been concluded that ICAP_ROTATION and ICAP_ORIENTATION shall be applied after considering ICAP_FRAMES and DAT_IMAGELAYOUT.

Obviously a change in orientation will have an effect on the output image dimensions, so these must be reflected in DAT_IMAGEINFO during state 6. The resulting image dimensions shall be reported by the Data Source after considering the affect of the rotation on the current frame.

For the sake of simplicity, the use of ICAP_ROTATION and ICAP_ORIENTATION should be mutually exclusive. However, it is really up to the Application to try and use one or the other. If an Application attempts to set both, then the reaction of the Data Source would be unpredictable. It may prioritize these items, or it might try to compound them.

 

Question: What are the actual allowed values for ICAP_CONTRAST, ICAP_BRIGHTNESS, and ICAP_SHADOW?

Answer: There is considerable confusion about what is the appropriate way to present these actual features for a particular device. Anyone that has attempted to support these capabilities knows that the recommended ranges do not accurately reflect the capabilities of real world devices. Data Source developers have tried many different methods of getting the correct response for their Data Source, and not all are consistent.

By providing a meaningful step size, or by providing a different container, a Data Source can provide the Application with enough information to accurately model the actual ability of the device. For an Application that wishes to present a custom User Interface for this type of capability, it is not really useful to the user if it provides 2000 steps from -1000 to +1000, especially if the device really only supports a small number of levels.

Since both Data Source Developers and Application Developers read the same specification, it can be assumed that it is not acceptable to provide values that do not fit within the documented ranges for these types of capabilities.

The following suggestion is an example of how to follow the spec, and provide the most accurate values for the particular Data Source.

 

Question: My scanner only supports 3 levels of brightness. How do I implement ICAP_BRIGHTNESS?

Answer: Specification requirement stated in Chapter 9:

"Source should normalize the values into the range. Make sure that a ‘0' value is available as the Current Value when the Source starts up. If the Source’s ± range is asymmetric about the ‘0’ value, set range maxima to ±1000 and scale homogeneously from the ‘0’ value in each direction. This will yield a positive range whose step size differs from the negative range’s step size."

(Note: it should be expanded in this statement that for a step size that differs in the negative and positive range, a TW_ENUMERATION container must be used. A TW_RANGE container is not suitable for representing a non-linear step size)

Actual device simply supports the options, normal, lighten, and darken.

These can fit into the constraints by mapping actual values to required values:

Normal = 0

lighten = -1000

darken = 1000

These values can be placed in a TW_RANGE container with a step size of 1000, or into a TW_ENUMERATION containing only the 3 values.

{ -1000, 0, 1000 }, the current and default values are 0.

 

Question: What do the TWAIN Defined Paper sizes refer to?

Answer: Please see the appropriate section in the TWAIN Specification.

Question: How do I handle ICAP_XRESOLUTION and ICAP_YRESOLUTION when ICAP_UNITS is set to TWUN_PIXELS?

Answer: In chapter 9 the TWAIN Specification states the following about the contents of ICAP_XRESOLUTION, and ICAP_YRESOLUTION:

"Measured in units of pixels per unit as defined by ICAP_UNITS (pixels per TWUN_PIXELS yields dimensionless data)."

The term "dimensionless" does nothing to indicate exactly how the Data Source shall respond in this condition. This behavior can be clarified by further stating that ICAP_XRESOLUTION shall report 1pixel/pixel when the units are TWUN_PIXELS. ICAP_YRESOLUTION shall report 1 pixel/pixel when the units are TWUN_PIXELS. Some Data Sources like to report the actual number of pixels that the device supports, but that response is more appropriate in ICAP_PHYSICALHEIGHT and ICAP_PHYSICALWIDTH.

 

Question: How does CAP_TIMEDATE know when and what to negotiate?

Answer: On page 9-14 of the TWAIN Specification the contents of CAP_TIMEDATE are described as follows:

"The date and time the image was acquired."

"The time and date when the image was originally acquired (when the Source entered State 7)"

The first problem with this definition is when to negotiate it. Since the Data Source can enter State 4 without ever having entered State 7, it should be stated that this capability must be negotiated during a State 7, before the call to the DG_CONTROL / DAT_PENDINGXFERS / MSG_ENDXFER triplet. (Note: That behavior requires the capability to be listed in the CAP_EXTENDEDCAPS capability by the Data Source.)

The strict definition in the TWAIN Specification, concerning the content of this capability, dedicates the use to tracking when an image was transferred from the Data Source to the Application. That is not really a useful value to provide, since the Application could generate that by itself with no assistance from the Data Source. In the current form, it also forbids the use of truly useful information that can be inquired from specialized scanners such as digital cameras. The expected content of this capability can be clarified with the following statement:

"CAP_TIMEDATE should return the closest available approximation of the time the physical phenomena represented by the image was recorded."

This statement opens the definition up to several possibilities, and makes it more ambiguous. In this case, ambiguity is good since specialized Data Sources can then provide truly useful information when it is available. Applications must also be aware of the specialized nature of this capability. If an Application truly wants the exact time of acquisition, it should generate that value itself during the image acquisition procedure.

 

Question: Will ICAP_PHYSICALWIDTH, and ICAP_PHYSICALHEIGHT change when the scanning area has changed?

Answer: Probably. On page 7-59 the specification states:

"Source: Reset all the fields of the structure pointed at by pImageLayout to the device’s power-on origin and extents. There is an implied resetting of ICAP_ORIENTATION, ICAP_PHYSICALWIDTH, and ICAP_PHYSICALHEIGHT to the device’s power-on default values."

This statement should be disregarded, since ICAP_PHYSICALHEIGHT and ICAP_PHYSICALWIDTH cannot be set or reset. These values are dependant on the maximum width and height that can possibly be set using the scanning area. These values are read only. It is reasonable to assume that these values will change when the scanning area has changed. Such a change could be triggered by enabling or disabling a document feeder.

 

Question: What happens when the Data Source has different ICAP_PHYSCALHEIGHT for Document Feeder and Flat Bed?

Answer:

  • Application negotiates CAP_FEEDERENABLED/MSG_GET, Data Source Response: FALSE>
  • Application negotiates ICAP_PHYSICALHEIGHT, Data Source Response: 11 inches
  • Application negotiates CAP_FEEDERENABLED/MSG_SET, Value: TRUE, Data Source changes internal feeder enabled state to TRUE
  • Application negotiates ICAP_PHYSICALHEIGHT, Data Source Response: 14 inches

 

Question: I enable a Data Source and I cannot use TAB or Keyboard Shortcuts to Navigate TWAIN Dialog.

Answer: The cause of this can be one of two things. Either the application is not forwarding all messages to TWAIN through the DAT_EVENT mechanism, or the Data Source is not properly processing the DAT_EVENT messages. (Windows: calling IsDialogMessage for each forwarded message with TWAIN Dialog handle)

Question: I enable the Data Source and the TWAIN Dialog Box Combo Boxes cannot be opened and Edit boxes produce multiple characters per keystroke.

Answer: his case is caused by processing TWAIN Dialog Messages twice. Either the Data Source has not returned the proper return code in response to DAT_EVENT calls (Windows: TWRC_DSEVENT when IsDialogMessage returns TRUE), or the Application is ignoring the return code.

 

Question: This is not a problem when Data Source operates through TWAIN Thunker?

Answer: Problems with the application handling of these messages are not often detected if the Data Source is operating through the TWAIN Thunking mechanism. This is because the Thunker process has a separate Window and Message pump that properly dispatch DAT_EVENT messages to the Data Source. Any mistake in application handling will pass without notice since all DAT_EVENT calls will return TWRC_NOTDSEVENT. (with the exception of important messages such as MSG_XFERREADY.)

 

Question: I do not think the problem is mine, it seems erratic, keyboard shortcuts and Tab key work for Message Boxes, but not TWAIN Dialog?

Answer: This is because Windows architecture is getting in the way. In Windows, a standard Message box is Modal, and operates from a local message pump until the user closes it. All messages are properly dispatched to the message box since it does not rely on the application message pump. The TWAIN Dialog is slightly different since it is implemented Modeless. There is no easy way to duplicate Modal behavior for the TWAIN Dialog.

 

Question: FloatToFix32 does not round negative numbers correctly.

Answer: The following changes are a possible fix to the problem:

/**********************************************************
* FloatToFix32
* Convert a floating point value into a FIX32
**********************************************************/

TW_FIX32 FloatToFix32( float floater )
{
                TW_FIX32 Fix32_value;
                TW_BOOL sign = (floater < 0)?TRUE:FALSE;
                TW_INT32 value = (TW_INT32) (floater * 65536.0 + (sign?(-0.5):0.5));
                Fix32_value.Whole = value >> 16;
                Fix32_value.Frac = value & 0x0000ffffL;
                return (Fix32_value);
}

 

Question: How can I get a copy of the EZTWAIN toolkit?

Answer: The EZTWAIN toolkit is available for download from the following location on the Web: http://www.dosadi.com/download.htm

 

Question: What certification program is available to certify my TWAIN implementation is compliant?

Answer: The TWAIN Working Group (TWG) has available the TWAIN Self-Certification Program.

Question: How can I configure from my Application and Data Source to scan duplex and what special considerations would apply to transfer these duplex images?

Answer: From the TWAIN application's point of view the duplex scanning, once enabled, is the same as multi page scanning. Duplex can be enabled (for devices and Data Sources supporting it) either programmatically using CAP_DUPLEXENABLED or from the Data Source GUI.

The application can check the CAP_DUPLEX value to know if duplex is supported and what duplex mode is supported by the device (one pass or two pass duplex).

Before setting CAP_DUPLEXEMABLED to True the application may need to enable the document feeder setting CAP_FEEDERENABLED (and CAP_AUTOFEED for automatic document feeding) to True and set CAP_XFERCOUNT to either -1 or a multiple of 2 value.

During a multi page duplex transfer sequence the application can keep record of which paper side (front or back) is being transferred by counting the images transferred so far (and assuming the first one was front side). Some Data Sources do implement custom capabilities or extended image information support to let the application know which side is about to be transferred next, is transferred currently or was just transferred (in the extended image information case).

Some Data Sources supporting duplex may also support different File System camera devices (which can be selected by the application through DG_CONTROL/ DAT_FILESYSTEM/ MSG_CHENGEDIRECTORY) so certain capabilities can be negotiated separately for each scan side (front and back) (e.g. there are duplex scanners that support different scaling, resolution, even pixel type for the front and back side). By default all these capabilities are negotiated for the "default camera", that is the scanner (i.e. for both front and back sides). Usually when such functionality is supported, it is available also from the Data Source GUI (to allow the user to select different scan parameters for the front and back sides). The application shall use DG_IMAGE/ DAT_IMAGEINFO/ MSG_GET in state 6 before a new image transfer to know the image attributes (such as image dimensions, bit depth, pixel type, compression).

 

Question: I want to develop a TWAIN Data Source for a duplex scanner but I don't know if I need a special TWAIN application to scan duplex using my Data Source? Which TWAIN applications support duplex scanning?

Answer: Not necessarily unless you need to test the programmatic duplex configuration for your Data Source. Any TWAIN application that supports multiple transfers per TWAIN session and enables the selected TWAIN Data Source with its GUI on (such as Adobe Photoshop, Kodak/Wang Imaging, Adobe Acrobat and many others) should be able to scan duplex from a Data Source (that supports duplex) if the user enables the duplex functionality from the Data Source GUI (for example when configuring the scan source the user can select between flatbed - if the scanner is equipped with one -, ADF single side - simplex scanning, ADF double side - duplex scanning - if supported; some Sources may even allow configuring scanning just the back side of each page).

 

Question: I am currently trying to add TWAIN support to an application but I am running into problems trying to select a Data Source. I have successfully opened the Source Manager but when I call MSG_USERSELECT the Select Source dialog appears but the list is empty.

Answer: You have to configure your development environment and/or compiler to align data structures on a word (16 bits) boundary (as opposed to byte /8 bits and double word /32 bits boundaries).

 

Question: Is it possible from a TWAIN application to know if a scanner is a flatbed scanner or not?

Answer: Yes, it is. If CAP_FEEDERENABLED is not supported or it is but it cannot be set to true then it is safe to assume the scanner is a flatbed-only device (at least, this is the functionality that can be accessed from its TWAIN Data Source). If CAP_FEEDERENABLED is supported and can be set to true then the scanner is equipped with a feeder. If CAP_AUTOFEED is supported and can be set to true then the feeder is an automatic document feeder (ADF). If CAP_FEEDERENABLED is supported but the only supported value is true then the device would be a feeder-only scanner (or a similar device supporting only feeder-like operations).

 

<Question: How does CAP_JOBCONTROL work? What is a patch code?

Answer: A scanner may be able to detect a special paper to scan as a "job separator" (this may be a paper with a special shape for example). When inserting such separators between stacks of papers to be scanned the user may want to have the TWAIN driver instruct the scanner what to do when recognizes a separator: scan or not the separator, stop the transfer sequence (return TW_PENDINGXFERS.Count 0 to the first MSG_ENDXFER) or continue the transfers (scan the next page). The purpose of CAP_JOBCONTROL is to enable programmatic control of such a scanner feature.

 

Question: How do you transfer multiple images with different dimensions in the same TWAIN transfer sequence?

Answer: In order to transfer images of multiple dimensions in a single sequence (for a single MSG_XFERREADY) using the TWAIN buffered memory transfer mode, the application must execute DG_IMAGE/ DAT_IMAGEINFO/ MSG_GET for every new image to be transferred in state 6 (when ICAP_UNDEFINEDIMAGESIZE is not supported or set to false) or after every new image transfer (after TWRC_XFERDONE) if ICAP_UNDEFINEDIMAGESIZE is set to true.

For Native transfers and most of File transfers the image dimensions are described in the header of each image transferred so it is not necessary to execute this command for each individual image transfer.

 

Question: What is the exact role of the 16-bit TWUNK_16.EXE for 32-bit Windows TWAIN scanning? Is it possible to disable it?

Answer: Under MS Windows there are two TWAIN Data Source Manager modules, the 16-bit TWAIN.DLL and the 32-bit TWAIN_32.DLL. Each one when loaded will attempt to start the other one through one of the TWAIN Thunker modules (TWUNK_16.EXE or TWUNK_32.EXE) so it could enumerate all the TWAIN Data Sources installed on the system, both 16 and 32-bit. Without TWUNK_16.EXE TWAIN_32.DLL (and the application that loaded TWAIN_32.DLL) would be unable to see any 16-bit Data Sources. And without TWUNK_32.EXE TWAIN.DLL would be not able to see 32-bit Data Sources.

One problem usually reported about TWUNK_16.EXE is seeing it being loaded in memory when a 32-bit TWAIN Application loads TWAIN_32.DLL, even tough there are absolutely no 16-bit TWAIN Data Sources installed.

The TWAIN Thunker could be disabled manually under Windows 9x or NT by removing TWUNK_16.EXE and TWUNK_32.EXE from the %System% directory (e.g. the "Windows" or "WinNT" directory, the directory where Windows is installed). Without TWUNK_16.EXE 32-bit TWAIN Applications could still load TWAIN_32.DLL and use 32-bit Data Sources. Same thing is true for TWUNK_32.EXE and 16-bit TWAIN Applications and 16-bit Data Sources.

Under newer versions of Windows such as Windows 2000 and XP the TWUNK_16.EXE and TWUNK_32.EXE files (along with TWAIN_32.DLL and TWAIN.DLL) are considered system protected files and if they are removed Windows will attempt to restore them immediately from the original installation files.

A second problem often reported about TWUNK_16.EXE is have it remaining loaded in memory after a 32-bit TWAIN application is closed or crashes. The explanation for this would be that a 32-bit TWAIN Application (such as Imaging under Windows 2000) would always cause the 16-bit TWAIN thunker to be loaded (even if no 16-bit Data Sources are installed the 32-bit TWAIN Data Source Manager - TWAIN_32.DLL - needs to search for 16-bit sources; again, TWUNK_16.EXE is a 16-bit program that communicates with the TWAIN_32.DLL over DDEML and allows a 32-bit TWAIN Application to access transparently 16-bit Data Sources together with 32-bit ones). If the application crashes, TWUNK_16.EXE could be left running in background (the system won't shut it down automatically) along with any 16-bit Data Source DLLs that could be loaded with it. The solution would be to manually shut down TWUNK_16.EXE after an application crash, before to restart the application. From Windows 2000 or NT go to the Task Manager (Ctrl + Alt + Del), see the list of running processes and kill the TWUNK_16.EXE one (also WOWEXEC.EXE if you there are not other 16-bit applications running at that time).

 

Question: Is it possible to write a Windows TWAIN Application using Visual Basic or other high level programming language that doesn't allow modifying the main application's message loop?

Answer: Yes, it is possible, but it will be much easier if you use one of the TWAIN ActiveX/COM controls/libraries available on the market today. The use of memory pointers, handles, TWAIN capability containers and the need to alter the main application's message loop make it difficult to use a high level language such as Visual Basic.

The recommended solution to develop a Visual Basic (or other high level language) TWAIN Application is to use one of the TWAIN ActiveX/COM controls/libraries available on the market today. Some of these ActiveX controls are very well developed and would let the application use the full TWAIN programmatic functionality that TWAIN Data Sources might support - in most cases using a very simple set of ActiveX control properties, methods and events, saving the transferred images to disk files in formats easily recognized by the image/picture controls in Visual Basic and other similar languages.

To develop very basic, simple, limited usage TWAIN application support, a Visual Basic application could do the following:

  • Open the Data Source
  • Set MSG_XFERCOUNT to 1
  • Enable the Data Source modally (TW_USERINTERFACE.ModalUI set to TRUE)
  • Start a local message loop (using PeekMessage/GetMessage and TranslateMessage Win32 APIs) to wait for the first message to come from the Source.
  • If MSG_XFERREADY is received, transfer one image then end the transfer.
  • Discard any pending transfers if there are any and disable the Data Source.

This means no complex capability negotiation, just one image transfer per MSG_ENABLEDS/MSG_DISABLEDS sequence. If MSG_CLOSEDSREQ is received instead of MSG_XFERREADY, consider the session canceled and disable the Data Source. Such an application would need to load TWAIN_32.DLL and connect to its exported DSM_Entry.

 

Question: How can a TWAIN Application know whether a Data Source is a Scanner or a Digital Camera?

Answer: Currently TWAIN does not define a standard method to get from a TWAIN Data Source the type/class of the image acquisition device it drives.

From a TWAIN Application these would be some suggestions to help deciding whether the device is a scanner or digital camera:

  • Check CAP_FEEDERENABLED to tell if there is a "feeder" (TRUE supported) or "flatbed" (FALSE supported) device; if CAP_FEEDERENABLED is unsupported the device might not be a scanner;
  • Check the ICAP_UNITS available values: usually a digital camera won't support anything than TWUN_PIXELS.. at TWUN_PIXELS all resolutions values should be 1 - still note that some Sources incorrectly report the maximum image size in pixels as "x/y resolution" (happens especially for DC sources and is incorrect);
  • Check if ICAP_IMAGEDATASET and ICAP_THUMBNAILSENABLED are supported; these are capability designed specifically for Digital Cameras - a scanner shouldn't usually have a reason to use it (an image database however could take advantage of them);
  • Check if CAP_BATTERYMINUTES and CAP_BATTERYPERCENTAGE are supported - again, if supported, the device might be a digital camera and not a scanner (unless there is a battery operated scanner);
  • CAP_CAMERAPREVIEWUI is also a capability highly recommended by TWAIN for digital camera Sources; if it is supported (with a TRUE value) then it is a chance that the device is a digital camera;
  • Finally, using the TW_IDENTITY ProductName and other information an application could recognize a certain device/Data Source it knows about.

Question: What does Apple say about how to implement a TWAIN Data Source (DS) for Mac OS X"?

Answer: Read the technote on the Apple Web site that describes how to implement a TWAIN Data Source (DS) for Mac OS X.  CLICK HERE

 

Question: Does Apple make the Image Capture SDK for Mac OS X v10.3 available?

Answer: Yes. Go to the Apple Web site and click on Image Capture SDK for Mac OS X v10.3CLICK HERE

 

 

TWAIN-- Standard for image acquisition devices.

Home | Events | About TWAIN | FAQs | Certification | Resources | Downloads | Contact Us | TWAIN Forum | Membership
Search | Sitemap

TWAIN license information
 
For questions or comments about TWAIN, contact the TWAIN Working Group
For comments about the site, contact the Webmaster

Copyright © 1992 - 2011 TWAIN Working Group. All rights reserved.