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 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 Test
Recommendations for Data Source implementers. Testing
products and services are available from independent
labs to test.

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.3. CLICK
HERE
|