### Simulate Jam with Multiple Checks Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/simulator.htm This example demonstrates simulating a jam with two images in the buffer, using multiple @check.ReadHeader commands. The first check condition is all zeros, which the simulator ignores. The checks are placed at the top, as their position does not matter for specific command targeting. ```text @init @check.ReadHeader 00 00 00 00 00 00 00 00 00 00 00 00 00 00 @check.ReadHeader F0 00 04 00 00 00 00 0A 00 00 00 09 3B 05 @image @image @stop ``` -------------------------------- ### Simulate Jam with Specific Check Condition Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/simulator.htm This example shows how to simulate a jam with one image in the buffer, using a specific @check condition (F0 00 04 00 00 00 00 0A 00 00 00 09 3B 05) before the second image is processed. ```text @init @image @check F0 00 04 00 00 00 00 0A 00 00 00 09 3B 05 @image @stop ``` -------------------------------- ### TWAIN ExtImageInfo Sample Code Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/TWAIN_ExtImageInfo.htm This C++ code demonstrates how to collect various Extended Image Information fields using the DAT_EXTIMAGEINFO structure. It includes helper macros for type conversion and finding indices, and a function to gather a comprehensive set of data. The example emphasizes collecting only necessary fields to optimize performance, especially on faster scanners. ```cpp #define cvtf(x) (((float)(x.Whole))+(((float)x.Frac)/65536.0)) #define FI(x) FindIndex(eii,x) int FindIndex ( TW_EXTIMAGEINFO *eii, ``` -------------------------------- ### Set Pixel Type Capability Source: https://github.com/soukoku/ntwain/blob/v3/README.md Use the DataSource's Capabilities property to interact with TWAIN capabilities. This example demonstrates setting the PixelType to BlackWhite after checking support and availability. ```csharp // The wrapper has many methods that corresponds to the TWAIN capability triplet msgs like // GetValues(), GetCurrent(), GetDefault(), SetValue(), etc. // (see TWAIN spec for reference) // This example sets pixel type of scanned image to BW and // IPixelType is the wrapper property on the data source. // The name of the wrapper property is the same as the CapabilityId enum. PixelType myValue = PixelType.BlackWhite; if (myDS.Capabilities.ICapPixelType.CanSet && myDS.Capabilities.ICapPixelType.GetValues().Contains(myValue)) { myDS.Capabilities.ICapPixelType.SetValue(myValue); } ``` -------------------------------- ### Accessing TWAIN Triplets Source: https://github.com/soukoku/ntwain/blob/v3/src/NTwain/Triplets/WhatsThis.txt Demonstrates how to access a TWAIN triplet for getting the status of a Data Source (DS). This follows the pattern DGControl.Status.Get(...). ```csharp DGControl.Status.Get(...) ``` -------------------------------- ### Initialize Simulator Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/simulator.htm This command must be the first in any sequence of @-commands. It serves as a reset point for the simulator, allowing multiple scanning sessions without exiting the application. ```text @init ``` -------------------------------- ### ICAP_COMPRESSION and ICAP_XFERMECH Dependencies Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/faq.htm Illustrates the valid combinations of ICAP_COMPRESSION and ICAP_XFERMECH. Note specific limitations for i800 and default behavior resets. ```text ICAP_XFERMECH ICAP_COMPRESSION TWSX_NATIVE TWCP_NONE** TWSX_FILE TWCP_NONE, TWCP_GROUP31D*, TWCP_GROUP32D*, TWCP_GROUP4, TWCP_JPEG TWSX_MEMORY TWCP_NONE, TWCP_GROUP31D*, TWCP_GROUP32D*, TWCP_GROUP4, TWCP_JPEG * - i800 only ** - accepts other valid values but resets to TWCP_NONE automatically ``` -------------------------------- ### Create and Initialize TwainSession Source: https://github.com/soukoku/ntwain/blob/v3/README.md Create a TwainSession instance using a TWIdentity and subscribe to essential events. The session must be opened before use. ```csharp // can use the utility method to create appId or make one yourself var appId = TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetExecutingAssembly()); // new it up and handle events var session = new TwainSession(appId); session.TransferReady += ... session.DataTransferred += ... // finally open it session.Open(); ``` -------------------------------- ### Simulate Jam with One Image Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/simulator.htm This snippet demonstrates a basic simulation scenario involving one image in the scanner buffer, including initialization, image generation, jamming, and stopping. ```text @init @image @jam @image @stop ``` -------------------------------- ### RAMSCAN.TXT @-Commands for Simulator Behavior Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/simulator.htm Use @-commands at the end of ramscan.txt to control simulator behavior, such as initializing, capturing images, and stopping the session. Each '@image' command corresponds to one side of a sheet of paper. ```text @init @image @image @stop ``` -------------------------------- ### Specify DualStream Images from Files Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/simulator.htm This @image command form combines bitonal and color images from files, suitable for dualstream scanning. The order of images does not matter; the simulator selects the appropriate one based on the CAP_CAMERAORDER capability. ```text @image 1280 1692 1 0 250 c:\twain\bitonal.tif 640 848 24 6 0 c:\twain\color.jpg ``` -------------------------------- ### Negotiating Rear Cameras Separately Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/readme.htm This C/C++ code snippet demonstrates how to negotiate rear cameras separately from front cameras, typically for simultaneous bitonal/color or bitonal/grayscale scanning using CAP_CAMERAENABLE. ```c // Example code snippet for negotiating rear cameras separately // This code assumes the existence of TWAIN DSM and driver entry points. // It focuses on the logic for enabling/disabling cameras using a custom capability. #include #include // Assume KODAK_CUSTOM_CAP_CAMERAENABLE and related structures are defined elsewhere // (e.g., in kdscust.h or a similar header file). // Placeholder for TWAIN driver entry point function extern TW_UINT16 DSM_Entry(TW_UINT32ッション, TW_UINT16 msg, TW_IDENTITY *pOrigin, TW_IDENTITY *pDest, TW_UINT32 data, TW_UINT16 *pXferMech); // Function to configure camera scanning TW_UINT16 ConfigureCameraScanning(TW_IDENTITY *pAppID, TW_IDENTITY *pDsID) { TW_UINT16 rc = TWRC_SUCCESS; TW_CAPABILITY cap; KODAK_CAMERA_ENABLE_SET cameraEnable; // Initialize TW_CAPABILITY structure for setting camera enable state ZeroMemory(&cap, sizeof(TW_CAPABILITY)); cap.Cap = CUSTOM_CAP_CAMERAENABLE; // Use the custom capability code cap.ConType = TWON_ONEVALUE; cap.Data.pContainer = &cameraEnable; cap.hContainer = 0; // Not used for TWON_ONEVALUE with pointer // Set desired camera states // Example: Enable front camera for color, rear camera for bitonal cameraEnable.enableFrontCamera = TRUE; cameraEnable.enableRearCamera = TRUE; // Call the TWAIN DSM to set the custom capability rc = DSM_Entry(DG_CONTROL, DAT_CAPABILITY, pAppID, pDsID, (TW_UINT32)&cap, NULL); if (rc != TWRC_SUCCESS) { // Handle error: Failed to set camera capability // Log error, display message, etc. return rc; } // Optionally, retrieve the current camera status to verify KODAK_CAMERA_STATUS cameraStatus; ZeroMemory(&cap, sizeof(TW_CAPABILITY)); cap.Cap = CUSTOM_CAP_CAMERAENABLE; cap.ConType = TWON_ONEVALUE; cap.Data.pContainer = &cameraStatus; cap.hContainer = 0; // To get status, we might need to use a different message or data structure // depending on the driver's implementation. Assuming a GET operation. // This part is highly dependent on the specific driver implementation. // For demonstration, let's assume a GET operation is possible. // rc = DSM_Entry(DG_CONTROL, DAT_CAPABILITY, pAppID, pDsID, (TW_UINT32)&cap, NULL); // if (rc == TWRC_SUCCESS) { // // Process cameraStatus.frontCameraEnabled, cameraStatus.rearCameraEnabled // } return TWRC_SUCCESS; } // Note: This is a conceptual example. Actual TWAIN communication and custom // capability handling require a deep understanding of the TWAIN specification // and the specific driver's implementation details. ``` -------------------------------- ### Simulate ADF Scanner with Flatbed Accessory (Version 9.x+) Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/simulator.htm Enable simulation by setting 'simulation' to true in the [Simulation] section of const.ini. Specify the ADF scanner model with 'simmodel' and the flatbed accessory with 'simflatbed'. ```ini [Simulation] simulation=true simmodel=i3000 simflatbed=i2000legal ``` -------------------------------- ### Specify Image from File (Bitonal) Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/simulator.htm This form of the @image command uses a local file for image data. The arguments specify the image dimensions, bit depth (1 for bitonal), compression type (e.g., 0 for none), byte offset to raw image data, and the filename. ```text @image 1280 1692 1 0 250 c:\twain\bitonal.tif ``` -------------------------------- ### Simulate Jam with ReadHeader Check Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/simulator.htm This snippet simulates a jam with two images in the buffer, using the @check.ReadHeader command with specific parameters. The jam message appears before any images are read. ```text @init @image @check.ReadHeader F0 00 04 00 00 00 00 0A 00 00 00 09 3B 05 @image @stop ``` -------------------------------- ### Discover and Select Cameras with TWAIN FileSystem Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/TWAIN_FileSystem.htm This code iterates through available TWAIN devices to identify and store names for combined, front, and rear cameras. It then demonstrates how to change the active camera using MSG_CHANGEDIRECTORY. ```c TW_FILESYSTEM fs; TW_STR255 cameraname[3]; // For loop used to discover available cameras... memset(cameraname,0,sizeof(cameraname)); for (rc = (*pDSM_Entry) (&AppId,&SourceId, �DG_CONTROL, �DAT_FILESYSTEM, �MSG_GETFIRSTFILE,(TW_MEMREF)&fs); rc == TWRC_SUCCESS; rc = (*pDSM_Entry) (&AppId,&SourceId, �DG_CONTROL, �DAT_FILESYSTEM, �MSG_GETNEXTFILE,(TW_MEMREF)&fs)) { // This is the combined front / rear camera... // In each case, just take the first one we find... if (fs.FileType == TWFY_CAMERA) { if (!cameraname[0][0]) strcpy(cameraname[0],fs.OutputName); // This is the front camera... } else if (fs.FileType == TWFY_CAMERA_TOP) { if (!cameraname[1][0]) strcpy(cameraname[1],fs.OutputName); // This is the rear camera... } else if (fs.FileType == TWFY_CAMERA_BOTTOM) { if (!cameraname[2][0]) strcpy(cameraname[2],fs.OutputName); } } // Change to the front camera... strcpy(fs.InputName,cameraname[1]); rc = (*pDSM_Entry) (&AppId,&SourceId, �DG_CONTROL, �DAT_FILESYSTEM, �MSG_CHANGEDIRECTORY,(TW_MEMREF)&fs); // Set some front capabilities, like ICAP_CONTRAST ... // Change to the rear camera... strcpy(fs.InputName,cameraname[2]); rc = (*pDSM_Entry) (&AppId,&SourceId, �DG_CONTROL, �DAT_FILESYSTEM, �MSG_CHANGEDIRECTORY,(TW_MEMREF)&fs); // Set some rear capabilities, like ICAP_CONTRAST ... // Change back to the combined camera (have to do // this before scanning starts, but can also do // this to simultaneously change front and rear // values).� Note that this is the default camera // when the Source is first started... strcpy(fs.InputName,cameraname[0]); rc = (*pDSM_Entry) (&AppId,&SourceId, �DG_CONTROL, �DAT_FILESYSTEM, �MSG_CHANGEDIRECTORY,(TW_MEMREF)&fs); ... ``` -------------------------------- ### Adjust Platen Autocrop/Deskew Sensitivity Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/faq.htm Tune the ForceBaffleBlackPlatenAdjustment value in CONST.INI to optimize autocrop and deskew performance on the platen. Higher values reduce false image data from dust and light scatter, while lower values better handle dark backgrounds. Experiment with values between 0-255, allowing lamps to warm up for at least a minute. ```ini ForceBaffleBlackPlatenAdjustment=60 ``` -------------------------------- ### Show Extended Image Information Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/TWAIN_ExtImageInfo.htm Allocates memory, builds the extended image information structure, issues a GETSPECIAL command to the TWAIN driver, and formats the retrieved information into strings. ```c 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) { ``` -------------------------------- ### Enable TWAIN Data Source for Transfer Source: https://github.com/soukoku/ntwain/blob/v3/README.md Call the Enable() method on the DataSource object to initiate the data transfer process. This prepares the TWAIN source for scanning. ```csharp myDS.Enable(...); ``` -------------------------------- ### Generate Blank Simulated Image Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/simulator.htm This is the simplest form of the @image command. The simulator generates a blank image with characteristics matching the negotiated session, including cropping, compression, polarity, and pixel type. ```text @image ``` -------------------------------- ### Select and Open a TWAIN Data Source Source: https://github.com/soukoku/ntwain/blob/v3/README.md Select the first available TWAIN data source and open it for use. This allows interaction with the data source's TWAIN triplet API. ```csharp // choose and open the first source found // note that TwainSession implements IEnumerable so we can use this extension method. DataSource myDS = session.FirstOrDefault(); myDS.Open(); ``` -------------------------------- ### Specify Image from File (Color) Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/simulator.htm This form of the @image command uses a local file for image data. The arguments specify the image dimensions, bit depth (24 for color), compression type (e.g., 6 for JPEG), byte offset to raw image data, and the filename. ```text @image 640 848 24 6 0 c:\twain\color.jpg ``` -------------------------------- ### Simulator Command Format Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/simulator.htm Commands in ramscan.txt follow the format '@command.platform arguments'. The '.platform' specifier is optional and can be Gemini, Viper, Prism, or Alien. ```text @image ``` ```text @jam.Prism ``` ```text @stop ``` -------------------------------- ### Simulate ReadHeader Error on Viper Platform Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/simulator.htm Use the '@check.ReadHeader.Viper' command with specific hexadecimal values to generate a ReadHeader error on the Viper platform. The underlined values are relevant for the simulator. ```text @check.ReadHeader.Viper F0 00 04 00 00 00 00 0A 00 00 00 09 3B 05 ``` -------------------------------- ### Simulate ReadHeader Error on Prism Platform Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/simulator.htm Use the '@check.ReadHeader.Prism' command with specific hexadecimal values to generate a ReadHeader error on the Prism platform. The underlined values are relevant for the simulator. ```text @check.ReadHeader.Prism F0 00 04 00 00 00 00 0A 00 00 00 09 3B 05 ``` -------------------------------- ### Toggle Bitonal/Grayscale Output Source: https://github.com/soukoku/ntwain/blob/v3/Spec/Kodak/simulator.htm Tells the simulator to toggle between bitonal and grayscale/color output for supported scanner models. This is useful for testing applications that handle different image formats. ```text @init @image @patch toggle @image @stop ```