/// <summary> /// Start a scan session... /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void m_buttonScan_Click(object sender, EventArgs e) { m_iUseBitmap = 0; string szTwmemref; TWAIN.STS sts; // Silently start scanning if we detect that customdsdata is supported, // otherwise bring up the driver GUI so the user can change settings... if (m_formsetup.IsCustomDsDataSupported()) { szTwmemref = "FALSE,FALSE," + this.Handle; } else { szTwmemref = "TRUE,FALSE," + this.Handle; } // Send the command... ClearEvents(); TWAIN.TW_USERINTERFACE twuserinterface = default(TWAIN.TW_USERINTERFACE); m_twain.CsvToUserinterface(ref twuserinterface, szTwmemref); sts = m_twain.DatUserinterface(TWAIN.DG.CONTROL, TWAIN.MSG.ENABLEDS, ref twuserinterface); if (sts == TWAIN.STS.SUCCESS) { SetButtons(EBUTTONSTATE.SCANNING); } }
/// <summary> /// Bring up the driver's non-scanning UI... /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void m_buttonSetup_Click(object sender, EventArgs e) { m_formscan.ClearEvents(); TWAIN.TW_USERINTERFACE twuserinterface = default(TWAIN.TW_USERINTERFACE); m_twain.CsvToUserinterface(ref twuserinterface, "TRUE,FALSE," + Handle); m_twain.DatUserinterface(TWAIN.DG.CONTROL, TWAIN.MSG.ENABLEDSUIONLY, ref twuserinterface); }
/// <summary> /// Rollback the TWAIN state to whatever is requested... /// </summary> /// <param name="a_state"></param> public void Rollback(TWAIN.STATE a_state) { TWAIN.TW_PENDINGXFERS twpendingxfers = default(TWAIN.TW_PENDINGXFERS); TWAIN.TW_USERINTERFACE twuserinterface = default(TWAIN.TW_USERINTERFACE); TWAIN.TW_IDENTITY twidentity = default(TWAIN.TW_IDENTITY); // Make sure we have something to work with... if (m_twain == null) { return; } // Walk the states, we don't care about the status returns. Basically, // these need to work, or we're guaranteed to hang... // 7 --> 6 if ((m_twain.GetState() == TWAIN.STATE.S7) && (a_state < TWAIN.STATE.S7)) { m_twain.DatPendingxfers(TWAIN.DG.CONTROL, TWAIN.MSG.ENDXFER, ref twpendingxfers); } // 6 --> 5 if ((m_twain.GetState() == TWAIN.STATE.S6) && (a_state < TWAIN.STATE.S6)) { m_twain.DatPendingxfers(TWAIN.DG.CONTROL, TWAIN.MSG.RESET, ref twpendingxfers); } // 5 --> 4 if ((m_twain.GetState() == TWAIN.STATE.S5) && (a_state < TWAIN.STATE.S5)) { m_twain.DatUserinterface(TWAIN.DG.CONTROL, TWAIN.MSG.DISABLEDS, ref twuserinterface); } // 4 --> 3 if ((m_twain.GetState() == TWAIN.STATE.S4) && (a_state < TWAIN.STATE.S4)) { m_twain.CsvToIdentity(ref twidentity, m_twain.GetDsIdentity()); m_twain.DatIdentity(TWAIN.DG.CONTROL, TWAIN.MSG.CLOSEDS, ref twidentity); } // 3 --> 2 if ((m_twain.GetState() == TWAIN.STATE.S3) && (a_state < TWAIN.STATE.S3)) { m_twain.DatParent(TWAIN.DG.CONTROL, TWAIN.MSG.CLOSEDSM, ref m_intptrHwnd); } }
/// <summary> /// Go through the sequence needed to capture images... /// </summary> private void CaptureImages() { TWAIN.STS sts; TWAIN.TW_IMAGEINFO twimageinfo = default(TWAIN.TW_IMAGEINFO); TWAIN.TW_IMAGEMEMXFER twimagememxfer = default(TWAIN.TW_IMAGEMEMXFER); TWAIN.TW_PENDINGXFERS twpendingxfers = default(TWAIN.TW_PENDINGXFERS); TWAIN.TW_USERINTERFACE twuserinterface = default(TWAIN.TW_USERINTERFACE); // Dispatch on the state... switch (m_twain.GetState()) { // Not a good state, just scoot... default: return; // We're on our way out... case TWAIN.STATE.S5: m_blDisableDsSent = true; m_twain.DatUserinterface(TWAIN.DG.CONTROL, TWAIN.MSG.DISABLEDS, ref twuserinterface); SetButtons(EBUTTONSTATE.OPEN); return; // Memory transfers... case TWAIN.STATE.S6: case TWAIN.STATE.S7: m_twain.CsvToImagememxfer(ref twimagememxfer, "0,0,0,0,0,0,0," + ((int)TWAIN.TWMF.APPOWNS | (int)TWAIN.TWMF.POINTER) + "," + m_twsetupmemxfer.Preferred + "," + m_intptrXfer); sts = m_twain.DatImagememxfer(TWAIN.DG.IMAGE, TWAIN.MSG.GET, ref twimagememxfer); break; } // Handle problems... if ((sts != TWAIN.STS.SUCCESS) && (sts != TWAIN.STS.XFERDONE)) { m_blDisableDsSent = true; Rollback(TWAIN.STATE.S4); SetButtons(EBUTTONSTATE.OPEN); return; } // Allocate or grow the image memory... if (m_intptrImage == IntPtr.Zero) { m_intptrImage = Marshal.AllocHGlobal((int)twimagememxfer.BytesWritten); } else { m_intptrImage = Marshal.ReAllocHGlobal(m_intptrImage, (IntPtr)(m_iImageBytes + twimagememxfer.BytesWritten)); } // Ruh-roh... if (m_intptrImage == IntPtr.Zero) { m_blDisableDsSent = true; Rollback(TWAIN.STATE.S4); SetButtons(EBUTTONSTATE.OPEN); return; } // Copy into the buffer, and bump up our byte tally... TWAIN.MemCpy(m_intptrImage + m_iImageBytes, m_intptrXfer, (int)twimagememxfer.BytesWritten); m_iImageBytes += (int)twimagememxfer.BytesWritten; // If we saw XFERDONE we can save the image, display it, // end the transfer, and see if we have more images... if (sts == TWAIN.STS.XFERDONE) { // Bump up our image counter, this always grows for the // life of the entire session... m_iImageCount += 1; // Get the image info... sts = m_twain.DatImageinfo(TWAIN.DG.IMAGE, TWAIN.MSG.GET, ref twimageinfo); // Add the appropriate header... // Bitonal uncompressed... if (((TWAIN.TWPT)twimageinfo.PixelType == TWAIN.TWPT.BW) && ((TWAIN.TWCP)twimageinfo.Compression == TWAIN.TWCP.NONE)) { TWAIN.TiffBitonalUncompressed tiffbitonaluncompressed; tiffbitonaluncompressed = new TWAIN.TiffBitonalUncompressed((uint)twimageinfo.ImageWidth, (uint)twimageinfo.ImageLength, (uint)twimageinfo.XResolution.Whole, (uint)m_iImageBytes); m_intptrImage = Marshal.ReAllocHGlobal(m_intptrImage, (IntPtr)(Marshal.SizeOf(tiffbitonaluncompressed) + m_iImageBytes)); TWAIN.MemMove((IntPtr)((UInt64)m_intptrImage + (UInt64)Marshal.SizeOf(tiffbitonaluncompressed)), m_intptrImage, m_iImageBytes); Marshal.StructureToPtr(tiffbitonaluncompressed, m_intptrImage, true); m_iImageBytes += (int)Marshal.SizeOf(tiffbitonaluncompressed); } // Bitonal GROUP4... else if (((TWAIN.TWPT)twimageinfo.PixelType == TWAIN.TWPT.BW) && ((TWAIN.TWCP)twimageinfo.Compression == TWAIN.TWCP.GROUP4)) { TWAIN.TiffBitonalG4 tiffbitonalg4; tiffbitonalg4 = new TWAIN.TiffBitonalG4((uint)twimageinfo.ImageWidth, (uint)twimageinfo.ImageLength, (uint)twimageinfo.XResolution.Whole, (uint)m_iImageBytes); m_intptrImage = Marshal.ReAllocHGlobal(m_intptrImage, (IntPtr)(Marshal.SizeOf(tiffbitonalg4) + m_iImageBytes)); TWAIN.MemMove((IntPtr)((UInt64)m_intptrImage + (UInt64)Marshal.SizeOf(tiffbitonalg4)), m_intptrImage, m_iImageBytes); Marshal.StructureToPtr(tiffbitonalg4, m_intptrImage, true); m_iImageBytes += (int)Marshal.SizeOf(tiffbitonalg4); } // Gray uncompressed... else if (((TWAIN.TWPT)twimageinfo.PixelType == TWAIN.TWPT.GRAY) && ((TWAIN.TWCP)twimageinfo.Compression == TWAIN.TWCP.NONE)) { TWAIN.TiffGrayscaleUncompressed tiffgrayscaleuncompressed; tiffgrayscaleuncompressed = new TWAIN.TiffGrayscaleUncompressed((uint)twimageinfo.ImageWidth, (uint)twimageinfo.ImageLength, (uint)twimageinfo.XResolution.Whole, (uint)m_iImageBytes); m_intptrImage = Marshal.ReAllocHGlobal(m_intptrImage, (IntPtr)(Marshal.SizeOf(tiffgrayscaleuncompressed) + m_iImageBytes)); TWAIN.MemMove((IntPtr)((UInt64)m_intptrImage + (UInt64)Marshal.SizeOf(tiffgrayscaleuncompressed)), m_intptrImage, m_iImageBytes); Marshal.StructureToPtr(tiffgrayscaleuncompressed, m_intptrImage, true); m_iImageBytes += (int)Marshal.SizeOf(tiffgrayscaleuncompressed); } // Gray JPEG... else if (((TWAIN.TWPT)twimageinfo.PixelType == TWAIN.TWPT.GRAY) && ((TWAIN.TWCP)twimageinfo.Compression == TWAIN.TWCP.JPEG)) { // No work to be done, we'll output JPEG... } // RGB uncompressed... else if (((TWAIN.TWPT)twimageinfo.PixelType == TWAIN.TWPT.RGB) && ((TWAIN.TWCP)twimageinfo.Compression == TWAIN.TWCP.NONE)) { TWAIN.TiffColorUncompressed tiffcoloruncompressed; tiffcoloruncompressed = new TWAIN.TiffColorUncompressed((uint)twimageinfo.ImageWidth, (uint)twimageinfo.ImageLength, (uint)twimageinfo.XResolution.Whole, (uint)m_iImageBytes); m_intptrImage = Marshal.ReAllocHGlobal(m_intptrImage, (IntPtr)(Marshal.SizeOf(tiffcoloruncompressed) + m_iImageBytes)); TWAIN.MemMove((IntPtr)((UInt64)m_intptrImage + (UInt64)Marshal.SizeOf(tiffcoloruncompressed)), m_intptrImage, m_iImageBytes); Marshal.StructureToPtr(tiffcoloruncompressed, m_intptrImage, true); m_iImageBytes += (int)Marshal.SizeOf(tiffcoloruncompressed); } // RGB JPEG... else if (((TWAIN.TWPT)twimageinfo.PixelType == TWAIN.TWPT.RGB) && ((TWAIN.TWCP)twimageinfo.Compression == TWAIN.TWCP.JPEG)) { // No work to be done, we'll output JPEG... } // Oh well... else { TWAINWorkingGroup.Log.Error("unsupported format <" + twimageinfo.PixelType + "," + twimageinfo.Compression + ">"); m_blDisableDsSent = true; Rollback(TWAIN.STATE.S4); SetButtons(EBUTTONSTATE.OPEN); return; } // Save the image to disk, if we're doing that... if (!string.IsNullOrEmpty(m_formsetup.GetImageFolder())) { // Create the directory, if needed... if (!Directory.Exists(m_formsetup.GetImageFolder())) { try { Directory.CreateDirectory(m_formsetup.GetImageFolder()); } catch (Exception exception) { TWAINWorkingGroup.Log.Error("CreateDirectory failed - " + exception.Message); } } // Write it out... string szFilename = Path.Combine(m_formsetup.GetImageFolder(), "img" + string.Format("{0:D6}", m_iImageCount)); TWAIN.WriteImageFile(szFilename, m_intptrImage, m_iImageBytes, out szFilename); } // Turn the image into a byte array, and free the original memory... byte[] abImage = new byte[m_iImageBytes]; Marshal.Copy(m_intptrImage, abImage, 0, m_iImageBytes); Marshal.FreeHGlobal(m_intptrImage); m_intptrImage = IntPtr.Zero; m_iImageBytes = 0; // Turn the byte array into a stream... MemoryStream memorystream = new MemoryStream(abImage); Bitmap bitmap = (Bitmap)Image.FromStream(memorystream); // Display the image... if (m_iUseBitmap == 0) { m_iUseBitmap = 1; LoadImage(ref m_pictureboxImage1, ref m_graphics1, ref m_bitmapGraphic1, bitmap); } else { m_iUseBitmap = 0; LoadImage(ref m_pictureboxImage2, ref m_graphics2, ref m_bitmapGraphic2, bitmap); } // Cleanup... bitmap.Dispose(); memorystream = null; // disposed by the bitmap abImage = null; // End the transfer... m_twain.DatPendingxfers(TWAIN.DG.CONTROL, TWAIN.MSG.ENDXFER, ref twpendingxfers); // Looks like we're done! if (twpendingxfers.Count == 0) { m_blDisableDsSent = true; m_twain.DatUserinterface(TWAIN.DG.CONTROL, TWAIN.MSG.DISABLEDS, ref twuserinterface); SetButtons(EBUTTONSTATE.OPEN); return; } } }