1

How can I incrementally scan a document on Windows, from C#, while getting callbacks to show pieces of the image as they come in, and update my own custom progress UI?

It looks like the scanner API options include:

  • WIA, WIA Script Automation (windows)
  • TWAIN (windows, linux)
  • ImageKit and ImageCaptureCore (MacOS)
  • SANE (linux)
  • ISIS (windows, expensive commercial).

My attempt on WIA Script Automation:

I have a simple C# application which uses Windows WIA Script Automation to scan a document. (see the code on github) However, during the Scan the UI is hijacked by a popup progress dialog.

The current code scans using the WIA Scripting CommonDialog.showTransfer (see here), which shows a popup progress bar dialog. I understand I can instead use Item.Transfer, however, it blocks for the entire duration and offers no callback so I can update my own custom progress UI (or cancel the transfer).

Is there any way to do a non-blocking scan with WIA, or to get progress callbacks?

Do I have to use TWAIN?

David Jeske
  • 2,306
  • 24
  • 29

1 Answers1

1

It looks like there are two options for non-blocking streaming scanning on Windows:

WIA COM

It's important to note that WIA has both a high-level "script automation" interface and a low-level COM interface. Using the low level WIA COM provides a stream based data-transfer method using IWiaTransfer and IWiaTransferCallback.

Unfortunately, the C# WIA wrappers I can find are using the script automation interface, which does not provide a streaming scan interface.

Twain

Page 4-20 of the Twain Specification, titled Buffered Memory Mode Transfer, explains how to use a fixed-size buffer to incrementally transfer the scan data using the commands DAT_SETUPMEMXFER and DAT_IMAGEMEMXFER. This still blocks for each incremental memory buffer, but after each buffer it allows the application to show the partial incoming data, and continue the transfer or cancel it.

I tried twain-cs and twain-dsm as supplied by twain.org, but they don't see my scanner. I'd also like to avoid have to install the LGPL twaindsm.dll.

The twaindotnet wrapper provides some Twain support which works and doesn't require the native TwainDSM DLL. Unfortunately, it doesn't (yet) support Buffered Memory Transfers. Therefore, I extended it.

My incremental_scanning branch of twaindotnet is able to incrementally show the image pixels as they arrive, right in the native UI. However, it still blocks the UI thread for each incremental transfer chunk. It's not clear if this blocking can be moved to a background thread or not.

youtube video of incremental scan progress

David Jeske
  • 2,306
  • 24
  • 29
  • How could your project set incremental preview? I set `UseIncrementalMemoryXfer` to true and the result didn't change. – Dia Dec 13 '17 at 05:33
  • What scanner are you using? What "result" are you referring to? Is this your own app, or one of the test apps? – David Jeske Dec 14 '17 at 07:28
  • Update: I'm using a penpower card A8 scanner, and I was using your WPF testing app. I set `UseIncrementalMemoryXfer` to true. If I choose default twain device, the resulting image is always black and white, and `TransferImage` event is fired only once after scanning complete. If I choose WIA mode of my scanner, `TransferImage` event will fired incrementally, but the blue color is missing in the resulting images. – Dia Dec 19 '17 at 02:05
  • The twain driver is in control of whether or not it implements incremental transfers. twaindotnet always uses twain, so when you choose WIA, you are actually choosing a "twain via wia" driver supplied by your scanner vendor, that implements twain support on top of their WIA driver. My guess is that their "twain via wia" driver supports twain incremental transfers, while their straight (legacy) twain driver does not. As for why the twain-via-wia driver doesn't include the blue, it is either a bug in their driver, or a bug in twain.net. Download a different free scanner app, and test it. – David Jeske Dec 20 '17 at 20:45
  • If you need more help debugging, you can find my email address in my network profile. Shoot me an email. – David Jeske Dec 20 '17 at 20:51
  • I solved my color problem, its just my fault. However I think your `TransferPixelsRGB()` function might have problem, if `memxfer_src.Memory` length is not a multiple of 4-bytes. I add some dummy bytes to fill between each scan lines, and my image finally lookss good. – Dia Dec 21 '17 at 06:49