Kodak KDS TWAIN Driver

Extended Image Info (DAT_EXTIMAGEINFO)

17-January-2013

 

 

Contents

1.     Overview...................................................................................................................... 2

2.     CAP_EXTIMAGEINFO.............................................................................................. 3

3.     MSG_GETSPECIAL................................................................................................... 4

4.     Supported Information................................................................................................... 5

5.     Sample Code................................................................................................................ 7

 

 

 

1.   Overview

One of TWAIN’s strengths is its ability to decouple the negotiation phase (state 4/5) from the image capture phase (state 6/7).  For this to work the application need image meta-data to describe each image so that it doesn’t have to rely on the negotiated values to understand what it is getting.  Take for example the image width and height, if ICAP_AUTOMATICBORDERDETECTION is TRUE then these values will vary from image to image.  Now in this case DAT_IMAGEINFO is sufficient to collect the needed information, but the TW_IMAGEINFO structure is fixed, and only contains a fraction of the possible meta-data values that can be associated with an image.

 

Extended Image Info (DAT_EXTIMAGEINFO) was introduced in 1.7 of the TWAIN specification as a way to collect a tagged list of meta-data for every captured image.  The Kodak Document Scanners significantly extend this list with custom data.  The purpose of this document is to detail what information is present and how to get it.

 

The term “All of the Kodak Document Scanners” refers to the following models or families:

 

            3000/4000

            5000/7000/9000

            i30/i40

            i200

            i600

            i700

            i800

            i900

            i1100

            i1200

            i1300

            i1400

            i1800

            i2000

            i2900

            i3000

            i4000

            i5000

            PS50/PS80

 

2.   CAP_EXTIMAGEINFO

All of the Kodak Document Scanners support DAT_EXTIMAGEINFO, however a well designed TWAIN application should confirm this by testing that the capability CAP_EXTIMAGEINFO is TRUE.

 

 

3.   MSG_GETSPECIAL

The TWAIN specification (currently at 2.1) indicates that DG_IMAGE / DAT_EXTIMAGEINFO / MSG_GET is only supported in state 7, after the image has been fully transferred (that is after the receipt of TWRC_XFERDONE).  All of the Kodak Document Scanners are able to report everything there is to know about an image in state 6, prior to transferring the image (this applies to DAT_IMAGEINFO, as well).

 

In order to support this behavior without violating the TWAIN specification we have added a new custom message MSG_GETSPECIAL.  DG_IMAGE / DAT_EXTIMAGEINFO / MSG_GETSPECIAL can be used in state 6 or 7, and will report identical information for an image in either state.

 

 

4.   Supported Information

The following Extended Image Information values are supported by the TWAIN driver.  Those fields followed by a TWAIN name (such as ICAP_COMPRESSION) indicate that the values for that field come from that capability (ex: TWCP_GROUP4).

 

Not all fields are supported for all scanners.  The following codes can be used to figure out which scanner family/models support a given item.

 

            g - 5000/7000/9000 series support

      v - 3000/4000 series support

p - i800 series support

a - i200 series support

m - i30/i40/i55/i65 series support

f - i1100 series support

o - i600/i700/i1800 series support

h - i1200/i1300/i1400 series support

d - i2000/i2900/i3000/i4000/i5000/PS50/PS80 series support

r - i900 series support

 

* - Reference Gemini Integrator’s Guide for further information

 

If a field is unsupported, TWRC_INFONOTSUPPORTED (8) will be returned as the condition code.

 

TWAIN Standard

Type

Description

Supported Models

TWEI_BOOKNAME

TWTY_STR255

- Image Address fixed field

g,p,i1800

TWEI_CAMERA

TWTY_STR255

- DAT_FILESYSTEM camera

all

TWEI_CHAPTERNUMBER

TWTY_UINT32

- Image Address level 3

p,i1800

TWEI_DESKEWSTATUS

TWTY_UINT32

- Disabled (3), Pass(0), Fail(2)

all

TWEI_DOCUMENTNUMBER

TWTY_UINT32

- Document count

all

TWEI_FILESYSTEMSOURCE

TW_STR255

- The camera that captured the image data

d,r

TWEI_FRAME

TWTY_FRAME

- Similar to ICAP_FRAME

all

TWEI_FRAMENUMBER

TWTY_UINT32

- Always 1 (only 1 cropping region per image)

all

TWEI_IMAGEMERGED

TW_BOOL

- Indicates that the current image is merged between the front and rear images

d,r

TWEI_PAGENUMBER

TWTY_UINT32

- Page count

all

TWEI_PAGESIDE

TWTY_UINT16

- Page side TWCS_TOP/TWCS_BOTTOM

d,r

TWEI_PIXELFLAVOR

TWTY_UINT16

- Similar to ICAP_PIXELFLAVOR

all

TWEI_SKEWORIGINALANGLE

TWTY_UINT32

- The amount of skew in the original image

all

 

 

 

 

Custom Data

 

 

 

TWEI_HDR_AUTOCOLORAMOUNT

TWTY_UINT32

- Auto color amount

all (except g,v,p,a,m,f)

TWEI_HDR_AUTOCOLORDETECTED

TWTY_UINT32

- Auto color detected

all (except g,v,p,a,m,f)

TWEI_HDR_AUTOCOLORTHRESHOLD

TWTY_UINT32

- Auto color threshold

all (except g,v,p,a,m,f)

TWEI_HDR_BARCODE

TWTY_STR255

- KDIS formatted barcodes*

g

TWEI_HDR_BINARIZATIONQUALITY

TWTY_UINT32

- Conveys the quality level of the binarized image

d,r

TWEI_HDR_BITONALCONTRAST

TWTY_UINT32

- Bitonal contrast (0-FFFh)

o

TWEI_HDR_BITONALCONTRASTPERCENTAGE

TWTY_UINT32

- Bitonal contrast percentage (0-100d)

o

TWEI_HDR_BITONALTHRESHOLD

TWTY_UINT32

- Bitonal threshold (0-255d)

o

TWEI_HDR_BITORDER

TWTY_UINT32

- Similar to ICAP_BITORDER (MSB->LSB)

all

TWEI_HDR_BOOKNAME_A

TWTY_STR255

- Fixed field A (unsupported unless field A is fixed)

g,p,i1800

TWEI_HDR_BOOKNAME_B

TWTY_STR255

- Fixed field B (unsupported unless field B is fixed)

p,i1800

TWEI_HDR_BOOKNAME_C

TWTY_STR255

- Fixed field C (unsupported unless field C is fixed)

p,i1800

TWEI_HDR_BOOKNAME_D

TWTY_STR255

- Fixed field D (unsupported unless field D is fixed)

p,i1800

TWEI_HDR_COMPRESSION

TWTY_UINT32

- Similar to ICAP_COMPRESSION

all

TWEI_HDR_DATE

TWTY_UINT32

- Date (YYMMDD)

all

TWEI_HDR_DESKEW

TWTY_UINT32

- Image Manager deskew flag: Yes(1), No(0), Disabled(-1).  If -1 check TWEI_DESKEWSTATUS.

all

TWEI_HDR_DESKEWANGLE

TWTY_UINT32

- Angle in 1/10000 degrees - Example: 4.7 degress is represented as 47000

h,d,r

TWEI_HDR_DESKEWANGLEACTUAL

TWTY_INT32

- Angle (-450 to 450 degrees, -450,450 = Fail, signed 10ths of a degree)

o

TWEI_HDR_DESKEWCONFIDENCEFACTOR

TWTY_UINT32

- Deskew confidence (1-99d, 1%=Fail, 99%=Success)

o

TWEI_HDR_DIFFERENCEHISTOGRAM

TWTY_UINT8

- Difference histogram (256 bytes)

o

TWEI_HDR_DITHER

TWTY_STR255

- Similar to ICAP_HALFTONES

g,v,p,a,m,f,o,h

TWEI_HDR_DOCUMENTCOUNT

TWTY_UINT32

- Doc counter (CAP_PRINTERINDEX for gp, for va only if printer installed))

all

TWEI_HDR_DROPOUTSTATUS

TWTY_INT32

- ECDO Algorithm Status (0 = Success, >0 Algorithm Specific Error)

h,d 

TWEI_HDR_DUALSTACKINGSTACK

TWTY_UINT32

- When dual stacking is enabled, contains output tray a document was dropped into (1,2)

d-i5000 only

TWEI_HDR_FEATUREPATCH

TWTY_UINT32

- Feature patch value (1,4,6)

p,a,o,i1400,i3000,i4000,i5000

TWEI_HDR_FOLDEDCORNERPERCENTAGE

TWTY_UINT32

- Folded corner percentage (0-100d) 0->Not folded, 100->Folded along the diagonal

o

TWEI_HDR_GAMMATABLE

TWTY_UINT8

- Gamma table (256 bytes)

o

TWEI_HDR_IMAGEADDRESSDEFS

TWTY_STR255

- IA definitions (ex: FFF.333.222.111) (where each field is and how they are formatted)

p,i1800

TWEI_HDR_IMAGEADDRESSSTRING

TWTY_STR255

- Formatted image address string

p,i1800

TWEI_HDR_IMAGENUMBER

TWTY_UINT32

- Count of images in this session (since starting the application)

all

TWEI_HDR_IMAGESTATUS

TWTY_UINT32

- Image status

none

TWEI_HDR_LATCHEDFLAG

TWTY_UINT32

- Latch switch flag*

g

TWEI_HDR_LENGTH

TWTY_UINT32

- Size of image data from scanner (bytes)

all

TWEI_HDR_LEVEL

TWTY_UINT32

- Image Address Level  (0,1,2,3)

g,p,i1800

TWEI_HDR_LINELENGTH

TWTY_UINT32

- Image width (pixels)

all

TWEI_HDR_LONGPAPERLASTSEGMENT

TWTY_UINT32

- Image last segment

a

TWEI_HDR_LONGPAPERSEGMENTNUMBER

TWTY_UINT32

- Image segment number

a

TWEI_HDR_MODE

TWTY_UINT32

- Mode*

g

TWEI_HDR_MULTIFEED

TWTY_UINT32

- Multifeed detected: Yes(1), No(0))

all (except g,v,p)

TWEI_HDR_MOMENTARYFLAG

TWTY_UINT32

- Momentary flag*

g

TWEI_HDR_PAGEIMAGENUMBER

TWTY_UINT32

- Image count on sheet (1 – 4)

all

TWEI_HDR_PAGELENGTH

TWTY_UINT32

- Image height (pixels)

all

TWEI_HDR_PAGENUMBER

TWTY_UINT32

- Count of sheets in this session

all

TWEI_HDR_PAGESIDE

TWTY_UINT32

- Page side: Front(0), Rear(1)

all

TWEI_HDR_PATCHDETECTED

TWTY_UINT32

- Patch code detected on this sheet

p,a,o,i1400,i3000,i4000,i5000

TWEI_HDR_PCARD_HEADER

TWTY_STR255

- Personality-Card Header

none

TWEI_HDR_PCARD_FOOTER

TWTY_STR255

- Personality-Card Footer

none

TWEI_HDR_POLARITY

TWTY_UINT32

- SCSI RIF value: 0 is White(0), 1 is White(1)

gvpam

TWEI_HDR_PRINTERINDEX

TWTY_UINT32

- String Doc counter (CAP_PRINTERINDEX)

all

TWEI_HDR_PRINTERSTRING

TWTY_STR255

- String printed on document

v,p,a,d,i1400

TWEI_HDR_PROCESSINGSTATUS

TWTY_UINT32

- Processing Status (0 = Disabled, 1 = Success, 2 = Skipped, 4 = Fail)

none

TWEI_HDR_RAWIMAGEHEADER

TWTY_STR255

- Raw image header from scanner

p,o

TWEI_HDR_REGENERATION

TWTY_UINT32

- Retry count

none

TWEI_HDR_RESOLUTION

TWTY_UINT32

- ICAP_RESOLUTION

all

TWEI_HDR_ROLL

TWTY_UINT32

- Roll number*

g-990 only

TWEI_HDR_SKEW

TWTY_UINT32

- Skew flag detect: Yes(1), No(0)*

g-5000/7000 only

TWEI_HDR_SUMHISTOGRAM

TWTY_UINT8

- Sum histogram (256 bytes)

none

TWEI_HDR_TIME

TWTY_UINT32

- Time (HHMMSS)

all

TWEI_HDR_TOKEN_COUNT

TWTY_UINT32

- Token flag

none

TWEI_HDR_XOFFSET

TWTY_UINT32

- X-offset of image (pixels)

all

TWEI_HDR_XML

TWTY_HANDLE

- Everything in XML format (<reportimage> data)

d,r

TWEI_HDR_YOFFSET

TWTY_UINT32

- Y-offset of image (pixels)

all

 

 

5.   Sample Code

This section shows all the fields being collected in a single DAT_EXTIMAGEINFO call.  Hopefully this is enough information to get the information needed by your application.  We strongly recommend against getting fields you don’t need, especially ones that require memory allocations, as this can impact the performance of the system (especially on the faster scanners).

 

 

// This function creates a huge string that has ExtImageData in

// it along with some text headers.  The main purpose of the

// function is to show how to collect different kinds of data.

// Real applications should whittle this function down to exactly

// what they need.

#define cvtf(x) (((float)(x.Whole))+(((float)x.Frac)/65536.0))

#define FI(x) FindIndex(eii,x)

int FindIndex

(

       TW_EXTIMAGEINFO      *eii,

       int                  InfoID

)

{

       for (int ii=0; eii->Info[ii].InfoID; ii++)

       {

              if (eii->Info[ii].InfoID == InfoID) return(ii);

       }

       return(0);

}

 

void ShowExtImageInfo

(

void

)

{

       int                  ii;

       int                  sts;

       int                  len;

       int                  tmpint;

       char                 *str;

       TW_EXTIMAGEINFO      *eii;

       TW_FRAME             *f;

char hdr_titles[8192];

char hdr_data[8192];

 

       // Allocate the string...

       str = (char*)GlobalAlloc(GPTR,65536);

if (!str)

{

       // GlobalAlloc failed...

return;

}

 

       // Allocate the table...

       eii = (TW_EXTIMAGEINFO*)GlobalAlloc

(

GPTR,

sizeof(TW_EXTIMAGEINFO)+(sizeof(TW_INFO)*64)

);

if (!eii)

{

       // GlobalAlloc failed...

return;

}

 

       // Build the table...

       ii = 0;

       eii->Info[ii++].InfoID  = TWEI_BOOKNAME;

       eii->Info[ii++].InfoID  = TWEI_CAMERA;

       eii->Info[ii++].InfoID  = TWEI_CHAPTERNUMBER;

       eii->Info[ii++].InfoID  = TWEI_DESKEWSTATUS;

       eii->Info[ii++].InfoID  = TWEI_DOCUMENTNUMBER;

       eii->Info[ii++].InfoID  = TWEI_FRAME;

       eii->Info[ii++].InfoID  = TWEI_FRAMENUMBER;

       eii->Info[ii++].InfoID  = TWEI_PAGENUMBER;

       eii->Info[ii++].InfoID  = TWEI_PIXELFLAVOR;

       eii->Info[ii++].InfoID  = TWEI_SKEWORIGINALANGLE;

       eii->Info[ii++].InfoID  = TWEI_HDR_BARCODE;

       eii->Info[ii++].InfoID  = TWEI_HDR_BITORDER;

       eii->Info[ii++].InfoID  = TWEI_HDR_COMPRESSION;

       eii->Info[ii++].InfoID  = TWEI_HDR_DATE;

       eii->Info[ii++].InfoID  = TWEI_HDR_DESKEW;

       eii->Info[ii++].InfoID  = TWEI_HDR_DESKEWANGLE;

       eii->Info[ii++].InfoID  = TWEI_HDR_DESKEWANGLEACTUAL;

       eii->Info[ii++].InfoID  = TWEI_HDR_DOCUMENTCOUNT;

       eii->Info[ii++].InfoID  = TWEI_HDR_DUALSTACKINGSTACK;

       eii->Info[ii++].InfoID  = TWEI_HDR_FEATUREPATCH;

       eii->Info[ii++].InfoID  = TWEI_HDR_IMAGEADDRESSSTRING;

       eii->Info[ii++].InfoID  = TWEI_HDR_IMAGEADDRESSDEFS;

       eii->Info[ii++].InfoID  = TWEI_HDR_IMAGENUMBER;

       eii->Info[ii++].InfoID  = TWEI_HDR_LATCHEDFLAG;

       eii->Info[ii++].InfoID  = TWEI_HDR_LENGTH;

       eii->Info[ii++].InfoID  = TWEI_HDR_LEVEL;

       eii->Info[ii++].InfoID  = TWEI_HDR_LINELENGTH;

       eii->Info[ii++].InfoID  = TWEI_HDR_LONGPAPERLASTSEGMENT;

       eii->Info[ii++].InfoID  = TWEI_HDR_LONGPAPERSEGMENTNUMBER;

       eii->Info[ii++].InfoID  = TWEI_HDR_MODE;

       eii->Info[ii++].InfoID  = TWEI_HDR_MOMENTARYFLAG;

       eii->Info[ii++].InfoID  = TWEI_HDR_PAGEIMAGENUMBER;

       eii->Info[ii++].InfoID  = TWEI_HDR_PAGELENGTH;

       eii->Info[ii++].InfoID  = TWEI_HDR_PAGENUMBER;

       eii->Info[ii++].InfoID  = TWEI_HDR_PAGESIDE;

       eii->Info[ii++].InfoID  = TWEI_HDR_POLARITY;

       eii->Info[ii++].InfoID  = TWEI_HDR_PRINTERSTRING;

       eii->Info[ii++].InfoID  = TWEI_HDR_RESOLUTION;

       eii->Info[ii++].InfoID  = TWEI_HDR_ROLL;

       eii->Info[ii++].InfoID  = TWEI_HDR_SKEW;

       eii->Info[ii++].InfoID  = TWEI_HDR_TIME;

       eii->Info[ii++].InfoID  = TWEI_HDR_XOFFSET;

       eii->Info[ii++].InfoID  = TWEI_HDR_YOFFSET;

       eii->Info[ii++].InfoID  = TWEI_HDR_XML;

       eii->NumInfos = ii;

 

       // Issue the command to the driver...

       sts = (*pDSM_Entry)

(

&AppId,

&SourceId,

DG_IMAGE,

DAT_EXTIMAGEINFO,

MSG_GETSPECIAL,

(TW_MEMREF)eii

);

if (sts != TWRC_SUCCESS)

{

       // DAT_EXTIMAGEINFO failed…

       return;

}

 

// Grab the barcode length (if there is one)…

if (eii->Info[FI(TWEI_HDR_BARCODE)].CondCode == TWRC_SUCCESS)

{

       len = strlen((char*)eii->Info[FI(TWEI_HDR_BARCODE)].Item);

}

else

{

       len = 0;

}

 

       // Format the headers...

       str[0] = 0;

       sprintf(&str[strlen(str)],"Standard Extensions\n");

       sprintf(&str[strlen(str)],"TWEI_CAMERA:\n");

       sprintf(&str[strlen(str)],"TWEI_FRAME:\n");

       sprintf(&str[strlen(str)],"TWEI_PIXELFLAVOR:\n");

       sprintf(&str[strlen(str)],"TWEI_DESKEWSTATUS:\n");

       sprintf(&str[strlen(str)],"TWEI_SKEWORIGINALANGLE:\n");

       sprintf(&str[strlen(str)],"\nImage Address\n");

       sprintf(&str[strlen(str)],"TWEI_BOOKNAME:\n");

       sprintf(&str[strlen(str)],"TWEI_CHAPTERNUMBER:\n");

       sprintf(&str[strlen(str)],"TWEI_DOCUMENTNUMBER:\n");

       sprintf(&str[strlen(str)],"TWEI_PAGENUMBER:\n");

       sprintf(&str[strlen(str)],"TWEI_FRAMENUMBER:\n");

       sprintf(&str[strlen(str)],"\nCustom Extensions\n");

       if (len < 40) {

              sprintf(&str[strlen(str)],"TWEI_HDR_BARCODE:\n");

       } else if (len < 80) {

              sprintf(&str[strlen(str)],"TWEI_HDR_BARCODE:\n\n");

       } else {

              sprintf(&str[strlen(str)],"TWEI_HDR_BARCODE:\n\n\n");

       }

       sprintf(&str[strlen(str)],"TWEI_HDR_BITORDER:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_COMPRESSION:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_DATE:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_DESKEW:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_DESKEWANGLE:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_DESKEWANGLEACTUAL:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_DOCUMENTCOUNT:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_DUALSTACKINGSTACK:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_FEATUREPATCH:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_IMAGEADDRESDEFS:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_IMAGEADDRESSTRING:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_IMAGENUMBER:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_LATCHEDFLAG:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_LENGTH:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_LEVEL:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_LINELENGTH:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_LONGPAPERLASTSEGMENT:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_LONGPAPERSEGMENTNUMBER:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_MODE:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_MOMENTARYFLAG:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_PAGEIMAGENUMBER:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_PAGELENGTH:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_PAGENUMBER:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_PAGESIDE:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_POLARITY:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_PRINTERSTRING:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_RESOLUTION:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_ROLL:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_SKEW:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_TIME:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_XOFFSET:\n");

       sprintf(&str[strlen(str)],"TWEI_HDR_YOFFSET:\n");

       strcpy(hdr_titles,str);

 

       // Blank lines...

       str[0] = 0;

       sprintf(&str[strlen(str)],"\n");

 

       // Camera...

       if (eii->Info[ii=FI(TWEI_CAMERA)].CondCode != TWRC_SUCCESS)

{

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       }

else

{

              sprintf(&str[strlen(str)],"<%s>\n",eii->Info[ii].Item);

              GlobalFree((void*)eii->Info[ii].Item);

       }

 

       // Frame...

       if (eii->Info[ii=FI(TWEI_FRAME)].CondCode != TWRC_SUCCESS)

{

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       }

else

{

              f = (TW_FRAME*)eii->Info[ii].Item;

              sprintf

(

&str[strlen(str)],

"L%.2f  R%.2f  T%.2f  B%.2f\n",

cvtf(f->Left),

cvtf(f->Top),

cvtf(f->Right),

cvtf(f->Bottom)

);

              GlobalFree((void*)eii->Info[ii].Item);

       }

 

       // PixelFlavor...

       if (eii->Info[ii=FI(TWEI_PIXELFLAVOR)].CondCode != TWRC_SUCCESS)

{

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       }

else

{

              switch (eii->Info[ii].Item)

{

                     default:

                           sprintf(&str[strlen(str)],"*** ERROR ***\n");

                           break;

                     case TWPF_CHOCOLATE:

                           sprintf(&str[strlen(str)],"TWPF_CHOCOLATE\n");

                           break;

                     case TWPF_VANILLA:

                           sprintf(&str[strlen(str)],"TWPF_VANILLA\n");

                           break;

              }

       }

 

       // DeskewStatus...

       if (eii->Info[ii=FI(TWEI_DESKEWSTATUS)].CondCode != TWRC_SUCCESS)

{

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       }

else

{

              switch (eii->Info[ii].Item)

{

                     default:

                           sprintf(&str[strlen(str)],"*** ERROR ***\n");

                           break;

                     case TWDSK_SUCCESS:

                           sprintf(&str[strlen(str)],"TWDSK_SUCCESS\n");

                           break;

                     case TWDSK_REPORTONLY:

                           sprintf(&str[strlen(str)],"TWDSK_REPORTONLY\n");

                           break;

                     case TWDSK_FAIL:

                           sprintf(&str[strlen(str)],"TWDSK_FAIL\n");

                           break;

                     case TWDSK_DISABLED:

                           sprintf(&str[strlen(str)],"TWDSK_DISABLED\n");

                           break;

              }

       }

 

       // SkewOriginalAngle...

       if (eii->Info[ii=FI(TWEI_SKEWORIGINALANGLE)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // Blank lines...

       sprintf(&str[strlen(str)],"\n\n");

 

       // BookName...

       if (eii->Info[ii=FI(TWEI_BOOKNAME)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"<%s>\n",eii->Info[ii].Item);

              GlobalFree((void*)eii->Info[ii].Item);

       }

 

       // ChapterNumber...

       if (eii->Info[ii=FI(TWEI_CHAPTERNUMBER)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // DocumentNumber...

       if (eii->Info[ii=FI(TWEI_DOCUMENTNUMBER)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // PageNumber...

       if (eii->Info[ii=FI(TWEI_PAGENUMBER)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // FrameNumber...

       if (eii->Info[ii=FI(TWEI_FRAMENUMBER)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // Blank lines...

       sprintf(&str[strlen(str)],"\n\n");

 

       // Barcode...

       if (eii->Info[ii=FI(TWEI_HDR_BARCODE)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              if (len <= 0) {

                     sprintf(&str[strlen(str)],"<>\n");

              } else if (len < 40) {

                     sprintf(&str[strlen(str)],"<%s>\n",eii->Info[ii].Item);

                     str[strlen(str)-3] = '$';

              } else if (len < 80) {

                     char xxx[512];

                     strcpy(xxx,(char*)eii->Info[ii].Item);

                     xxx[40] = 0;

                     sprintf(&str[strlen(str)],"<%s\n",xxx);

                     strcpy(xxx,&((char*)eii->Info[ii].Item)[40]);

                     sprintf(&str[strlen(str)],"%s>\n",xxx);

                     str[strlen(str)-3] = '$';

              } else {

                     char xxx[512];

                     strcpy(xxx,(char*)eii->Info[ii].Item);

                     xxx[40] = 0;

                     sprintf(&str[strlen(str)],"<%s\n",xxx);

                     strcpy(xxx,&((char*)eii->Info[ii].Item)[40]);

                     xxx[40] = 0;

                     sprintf(&str[strlen(str)],"%s\n",xxx);

                     strcpy(xxx,&((char*)eii->Info[ii].Item)[80]);

                     sprintf(&str[strlen(str)],"%s>\n",xxx);

                     str[strlen(str)-3] = '$';

              }

              GlobalFree((void*)eii->Info[ii].Item);

       }

 

       // BitOrder...

       if (eii->Info[ii=FI(TWEI_HDR_BITORDER)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // Compression...

       if (eii->Info[ii=FI(TWEI_HDR_COMPRESSION)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // Date...

       if (eii->Info[ii=FI(TWEI_HDR_DATE)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              tmpint = eii->Info[ii].Item;

              sprintf

(

&str[strlen(str)],

"%02d/%02d/%02d\n",

tmpint/10000,

(tmpint/100)-((tmpint/10000)*100),

tmpint-((tmpint/100)*100)

);

       }

 

       // Deskew...

       if (eii->Info[ii=FI(TWEI_HDR_DESKEW)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // DeskewAngle...

       if (eii->Info[ii=FI(TWEI_HDR_DESKEWANGLE)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

// DeskewAngleActual...

if (eii->Info[ii=FI(TWEI_HDR_DESKEWANGLEACTUAL)].CondCode != TWRC_SUCCESS) {

       sprintf(&str[strlen(str)],"*** unsupported ***\n");

} else {

       sprintf(&str[strlen(str)],"%d.%d\n",((TW_INT32)eii->Info[ii].Item)/10,abs(((TW_INT32)eii->Info[ii].Item)) % 10);

}

 

       // DocumentCount...

       if (eii->Info[ii=FI(TWEI_HDR_DOCUMENTCOUNT)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       } 

 

       // Dropout Status...

       if (eii->Info[ii=FI(TWEI_HDR_DROPOUTSTATUS)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // Dualstackingstack...

       if (eii->Info[ii=FI(TWEI_HDR_DUALSTACKINGSTACK)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // FeaturePatch...

       if (eii->Info[ii=FI(TWEI_HDR_FEATUREPATCH)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

  

       // ImageAddressDefs...

       if (eii->Info[ii=FI(TWEI_HDR_IMAGEADDRESSDEFS)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"<%s>\n",eii->Info[ii].Item);

              GlobalFree((void*)eii->Info[ii].Item);

       }

 

       // ImageAddressString...

       if (eii->Info[ii=FI(TWEI_HDR_IMAGEADDRESSSTRING)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"<%s>\n",eii->Info[ii].Item);

              GlobalFree((void*)eii->Info[ii].Item);

       }

 

       // ImageNumber...

       if (eii->Info[ii=FI(TWEI_HDR_IMAGENUMBER)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // LatchedFlag...

       if (eii->Info[ii=FI(TWEI_HDR_LATCHEDFLAG)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // Length...

       if (eii->Info[ii=FI(TWEI_HDR_LENGTH)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // Level...

       if (eii->Info[ii=FI(TWEI_HDR_LEVEL)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // LineLength...

       if (eii->Info[ii=FI(TWEI_HDR_LINELENGTH)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

      

       // LongPaperLastSegment...

       if (eii->Info[ii=FI(TWEI_HDR_LONGPAPERLASTSEGMENT)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // LongPaperSegmentNumber...

       if (eii->Info[ii=FI(TWEI_HDR_LONGPAPERSEGMENTNUMBER].CondCode != TWRC_SUCCESS){

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // Mode...

       if (eii->Info[ii=FI(TWEI_HDR_MODE)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // MomentaryFlag...

       if (eii->Info[ii=FI(TWEI_HDR_MOMENTARYFLAG)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // PageImageNumber...

       if (eii->Info[ii=FI(TWEI_HDR_PAGEIMAGENUMBER)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // PageLength...

       if (eii->Info[ii=FI(TWEI_HDR_PAGELENGTH)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // PageNumber...

       if (eii->Info[ii=FI(TWEI_HDR_PAGENUMBER)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // PageSide...

       if (eii->Info[ii=FI(TWEI_HDR_PAGESIDE)].CondCode != TWRC_SUCCESS) {

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       } else {

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // Polarity...

       if (eii->Info[ii=FI(TWEI_HDR_POLARITY)].CondCode != TWRC_SUCCESS)

{

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       }

else

{

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // PrinterString...

       if (eii->Info[ii=FI(TWEI_HDR_PRINTERSTRING)].CondCode != TWRC_SUCCESS)

{

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       }

else

{

              sprintf(&str[strlen(str)],"<%s>\n",eii->Info[ii].Item);

              GlobalFree((void*)eii->Info[ii].Item);

       }

 

       // Resolution...

       if (eii->Info[ii=FI(TWEI_HDR_RESOLUTION)].CondCode != TWRC_SUCCESS)

{

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       }

else

{

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // Roll...

       if (eii->Info[ii=FI(TWEI_HDR_ROLL)].CondCode != TWRC_SUCCESS)

{

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       }

else

{

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // Skew...

       if (eii->Info[ii=FI(TWEI_HDR_SKEW)].CondCode != TWRC_SUCCESS)

{

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       }

else

{

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // Time...

       if (eii->Info[ii=FI(TWEI_HDR_TIME)].CondCode != TWRC_SUCCESS)

{

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       }

else

{

              tmpint = eii->Info[ii].Item;

              sprintf

(

&str[strlen(str)],

"%02d:%02d:%02d\n",

tmpint/10000,

(tmpint/100)-((tmpint/10000)*100),

tmpint-((tmpint/100)*100)

);

       }

 

       // Xoffset...

       if (eii->Info[ii=FI(TWEI_HDR_XOFFSET)].CondCode != TWRC_SUCCESS)

{

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       }

else

{

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // Yoffset...

       if (eii->Info[ii=FI(TWEI_HDR_YOFFSET)].CondCode != TWRC_SUCCESS)

{

              sprintf(&str[strlen(str)],"*** unsupported ***\n");

       }

else

{

              sprintf(&str[strlen(str)],"%d\n",eii->Info[ii].Item);

       }

 

       // XML...

       if (eii->Info[ii=FI(TWEI_HDR_XML)].CondCode != TWRC_SUCCESS)

       {

              sprintf (&str[strlen(str)],"*** unsupported ***\n");

       }

       else

       {

              sprintf (&str[strlen(str)],"<%s>\n",eii->Info[ii].Item);

              GlobalFree((void*)eii->Info[ii].Item);

       }

 

strcpy(hdr_data,str);

 

       // At this point hdr_titles is an array of the TWEI* names, and hdr_data is the array of the data for the TWEI*’s

       // Final cleanup

GlobalFree(eii);

}