This repository has been archived by the owner on Nov 17, 2020. It is now read-only.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
TLDR - This patch allows scanned image data to arrive incrementally, instead of only once the scan is done. It also may have lower memory consumption during the scan, because twain hands off incremental buffers to TwainDotNet. (though it could be lower still, see below)
Detailed Changes
This patch adds a new
DataSourceManager.UseIncrementalMemoryXfer
boolean flag (default false), which when set to true causes TwainDotNet to use new code for incremental TWAINImageMemXfer
, instead of the existing blockingImageNativeXfer
. This allows the image to appear incrementally, and lower memory consumption, because the marshalling handoffs between Twain, TwainDotNet, and managed Bitmaps occur in smaller incremental buffers.This patch also fixes a memory leak in
DataSourcemanager.TransferPictures()
, where hbitmap is not deallocated if a TWAIN failure code causes an early-exit before the IDisposableBitmapRenderer
was created to manage it's lifetime. The hbitmap to Bitmap conversion is now a static method, andTransferPictures()
closes lifetime on hbitmap in a finally clause.Unfortunately, the diff display for
TransferPictures
andTransferPicturesIncremental
are a bit intermingled, because these two functions are adjacent and have some similar pre and post code around the transfers.It also adds a
TwainBool
enum, because this added tests for twain boolean values, and it felt a bit error prone to just use "1" and "0" numbers.Areas for improvement:
The new MemoryXfer Incremental mode does not support 40bpp CMYK, or Planar RRR-GGG-BBB formats, because these formats are not supported by
Gdi32Native.SetDIBitsToDevice
. These formats could either be supported via other conversion means (using unsafe code), or the code could be changed to fallback to ImageNativeXfer (assuming it supports them). One wrinkle is that I can't find specific details of the TWAIN 40bit CMYK format in the spec.One of the benefits of incremental transfers is consuming less memory for very large scan images. This code does reduce memory consumption, but it could reduce it more. Currently
TransferPicturesIncremental
allocates a largeBitmap
to hold the entire finished image, to remain compatible with the existingTransferImageEventArgs
info. However, if a separateTransferImageEventIncrementalArgs
was made, that large allocation would be unnecessary.