protected void TransferPictures() { // see http://www.twain.org/wp-content/uploads/2017/03/TWAIN-2.4-Specification.pdf // page (3-20) if (DataSource.SourceId.Id == 0) { return; } PendingXfers pendingTransfer = new PendingXfers(); TwainResult result; try { do { pendingTransfer.Count = 0; // the Twain source will fill this in during DsPendingTransfer IntPtr hbitmap = IntPtr.Zero; // 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; } Bitmap bitmap; try { // Transfer the image from the device result = Twain32Native.DsImageTransfer( ApplicationId, DataSource.SourceId, DataGroup.Image, DataArgumentType.ImageNativeXfer, Message.Get, ref hbitmap); if (result != TwainResult.XferDone) { DataSource.Close(); break; } if (hbitmap == IntPtr.Zero) { throw new TwainException("Transfer complete, but bitmap pointer is still null."); } bitmap = BitmapRenderer.NewBitmapFromHBitmap(hbitmap); } finally { if (hbitmap != IntPtr.Zero) { Kernel32Native.GlobalFree(hbitmap); hbitmap = 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; } // fire the transfer event... TransferImageEventArgs args = new TransferImageEventArgs(bitmap, pendingTransfer.Count != 0, 1.0f); TransferImage(this, args); if (!args.ContinueScanning) { break; } }while (pendingTransfer.Count != 0); } finally { // Reset any pending transfers result = Twain32Native.DsPendingTransfer( ApplicationId, DataSource.SourceId, DataGroup.Control, DataArgumentType.PendingXfers, Message.Reset, pendingTransfer); } }