protected void TransferPicturesIncremental() { // see http://www.twain.org/wp-content/uploads/2017/03/TWAIN-2.4-Specification.pdf // page 4-20 Console.WriteLine("TransferPicturesIncremental..."); Logger.WriteLog(LOG_LEVEL.LL_NORMAL_LOG, "TransferPicturesIncremental..."); if (DataSource.SourceId.Id == 0) { return; } PendingXfers pendingTransfer = new PendingXfers(); TwainResult result; try { int recievedBlockCount = 1; do { pendingTransfer.Count = 0; // the Twain source will fill this in during DsPendingTransfer Console.WriteLine("Get the image info..."); // Get the image info ImageInfo imageInfo = new ImageInfo(); result = Twain32Native.DsImageInfo( ApplicationId, DataSource.SourceId, DataGroup.Image, DataArgumentType.ImageInfo, Message.Get, imageInfo); if (result != TwainResult.Success) { DataSource.Close(); break; } /*Console.WriteLine("Get the image layout..."); * ImageLayout imageLayout = new ImageLayout(); * result = Twain32Native.DsImageLayout( * ApplicationId, * DataSource.SourceId, * DataGroup.Image, * DataArgumentType.ImageLayout, * Message.GetCurrent, * imageLayout); * * if (result != TwainResult.Success) * { * DataSource.Close(); * break; * }*/ // Setup Destination Bitmap Bitmap bitmap = BitmapRenderer.NewBitmapForImageInfo(imageInfo); Console.WriteLine("Setup incremental Memory XFer..."); // Setup incremental Memory XFer SetupMemXfer setupMemXfer = new SetupMemXfer(); result = Twain32Native.DsSetupMemXfer( ApplicationId, DataSource.SourceId, DataGroup.Control, DataArgumentType.SetupMemXfer, Message.Get, setupMemXfer ); if (result != TwainResult.Success) { DataSource.Close(); break; } Console.WriteLine("allocate the preferred buffer size..."); // allocate the preferred buffer size // see twain spec pdf, page 4-21 ImageMemXfer imageMemXfer = new ImageMemXfer(); try { imageMemXfer.Memory.Flags = MemoryFlags.AppOwns | MemoryFlags.Pointer; imageMemXfer.Memory.Length = setupMemXfer.MinBufSize; // 對於A8 scanner,Preferred = MaxBufSize,太大了,所以我們選小一點的 imageMemXfer.Memory.TheMem = Kernel32Native.GlobalAlloc(GlobalAllocFlags.MemFixed, (int)setupMemXfer.MinBufSize * 2); // 不知道為什麼原本她size寫要*2倍 imageMemXfer.Compression = Compression.None; if (imageMemXfer.Memory.TheMem == IntPtr.Zero) { Logger.WriteLog(LOG_LEVEL.LL_SERIOUS_ERROR, "error allocating buffer for memory transfer"); throw new TwainException("error allocating buffer for memory transfer"); } long pixels_written = 0; long total_pixels = imageInfo.ImageWidth * imageInfo.ImageLength; do { // perform a transfer result = Twain32Native.DsImageMemXfer( ApplicationId, DataSource.SourceId, DataGroup.Image, DataArgumentType.ImageMemXfer, Message.Get, imageMemXfer ); //string savePath = @"C:\Users\Tenny\Pictures\TwainTest\tempBitmap_"; //savePath += i.ToString() + @".bmp"; if (result == TwainResult.Success || result == TwainResult.XferDone) { // dibArray是這次Buffer的RGB陣列 byte[] dibArray = ShiftPixels(ref imageMemXfer, imageInfo.BitsPerPixel / 8); BitmapRenderer.TransferPixels(bitmap, imageInfo, imageMemXfer); pixels_written += (imageMemXfer.BytesWritten * 8) / imageInfo.BitsPerPixel; double percent_complete = (double)pixels_written / (double)total_pixels; if (result == TwainResult.XferDone) { percent_complete = 1.0; // 算出空白區域的高度,裁切尾端部分 int blankHeight = GetCropHeight(bitmap); if (blankHeight > 0 && blankHeight < imageInfo.ImageLength) { bitmap = cropImage(bitmap, blankHeight); } } // fire the transfer event TransferImageEventArgs args = new TransferImageEventArgs(bitmap, result != TwainResult.XferDone, (float)percent_complete); TransferImage(this, args); if (!args.ContinueScanning) { result = TwainResult.XferDone; } } recievedBlockCount++; } while (result == TwainResult.Success); } finally { if (imageMemXfer.Memory.TheMem != IntPtr.Zero) { Kernel32Native.GlobalFree(imageMemXfer.Memory.TheMem); imageMemXfer.Memory.TheMem = IntPtr.Zero; } } // End pending transfers result = Twain32Native.DsPendingTransfer( ApplicationId, DataSource.SourceId, DataGroup.Control, DataArgumentType.PendingXfers, Message.EndXfer, pendingTransfer); if (result != TwainResult.Success) { DataSource.Close(); break; } }while (pendingTransfer.Count != 0); } finally { // Reset any pending transfers result = Twain32Native.DsPendingTransfer( ApplicationId, DataSource.SourceId, DataGroup.Control, DataArgumentType.PendingXfers, Message.Reset, pendingTransfer); Logger.WriteLog(LOG_LEVEL.LL_NORMAL_LOG, "TransferPicturesIncremental...done."); } }