Page 1 of 1

Scanning from different devices ...

Posted: Mon Jan 03, 2011 12:09 pm
by MichaelPeters
Hi everybody,

I´m currently writing a little scanning app, that´s supposed to be used in our warehouse. A typical szenario will be, that the users scan <n> pages of documents, and in some cases additionally some photos for any goods with damages. All together these images build a document set to be stored as a multipage tiff within our archive.

My idea was, that the user can retrieve the photos from the camera by twain as well. At the same time I´m showing all scanned images as 20% previews on a scrollable panel at the left side of the window. Selecting one of those preview images by clicking on it´s pic box displays a detailed image (100%) in a picturebox on the right side of the window. At any time it must be possible to click one of the previews and e.g. use functions as rotate or deskew.

Since the user can change the scan device as often as he wants, the images within the device object will be lost on any of those changes, while I still need access to any original und unscaled Acquired Images to display it in the detailed pic box or to rotate it. Due to that I decided to store all AcquiredImages with an array:

Code: Select all

public AcquiredImage[] ScannedImages = new AcquiredImage[100];
Everything seemed to be fine, until I found, that after a device change I cannot access any image from this array, that has been scanned from the previouly selected device. To make this easier to understand, I wrote 2 functions to show what´s causing the problem.

The following code is based on the assumption, that ScannedImages[0] is e.g. a document from a canon doc scanner, while ScannedImages[1] is a photo retrieved by twain from an iPhone ->
All code like the usage of finalImg has been removed, to get it to the point. I just load ScannedImage[1] from my array, make a 2.5 second pause and then try to load ScannedImage[0] (which came from another device) by "getAsBitmap" from my array:

Code: Select all

       private void ImageTest()
            Size MySize = new Size(pictureBoxDetailed.Width, pictureBoxDetailed.Height);
            AcquiredImage CurrentImage = ScannedImages[1];
            Bitmap finalImg = new Bitmap(CurrentImage.GetAsBitmap(), MySize.Width, MySize.Height);


        private void ImageTest2()
            Size MySize = new Size(pictureBoxDetailed.Width, pictureBoxDetailed.Height);
            AcquiredImage CurrentImage = ScannedImages[0];

[b]            Bitmap finalImg = new Bitmap(CurrentImage.GetAsBitmap(), MySize.Width, MySize.Height); <--- this line generates a NullReferenceException[/b]
I know, what a nullReferenceException tries to tell me, but the debugger shows, that CurrentImage (and due to that ScannedImages[0]) has a valid image oth the type "AcquiredImage".

Since the device object, the image within ScannedImages[0] came from, is not existing anymore, there seems to be a reference to that non existing device object as part of the acquired image?

If I´m right, this brings up the final question, how one would handle AcquiredImages from different devices with on Windows form?

Thanks in advance for any help or hint.


Re: Scanning from different devices ...

Posted: Tue Jan 04, 2011 10:38 am
by Alex
Hello Michael,

Each device (Device class) has collection of acquired images (AcquiredImageCollection class). Collection of acquired images is cleared
when device is changed in our Twain Advanced Demo (see the InitCurrentDevice method of the MainForm).

Also AcquiredImage class has the Disposed property - check this property before using AcquiredImage object.

Best regards, Alexander

Re: Scanning from different devices ...

Posted: Wed Jan 05, 2011 8:54 pm
by MichaelPeters
Thanks Alex,

the tricky thing seems to be, that if I store an image from the image collection with a device to an array, I am copying some kind of reference and not the image itself.

Code: Select all

ScannedImages[1] = _device.AcquiredImages[Index];
As soon, as _device ist closed, and another device opened, there is no chance to use ScannedImages[1] anymore.

The solution, I found:
I create an array for the Devices, where the size of that array is the device count. If a new device is selected, a new instance of device is created within that array and won´t be destroyed, until the app is finished. By that, every device won´t loose its image collection. I just have to maintain the index values related to the pic boxes - e.g. pic box 1 is related to _device[DeviceIndex].AcquiredImages[ImageIndex] ...

Code: Select all

        public DeviceManager _deviceManager;
        public Device[] _deviceList;
        Int32 DeviceCount = _deviceManager.Devices.Count;
        _deviceList = new Device[DeviceCount];
        Bitmap finalImg = new Bitmap(_deviceList[_activeDeviceIndex].AcquiredImages[Index].GetAsBitmap(true) ....

        private void openDevice()
            if (!_deviceIsOpen[_activeDeviceIndex])
                    _activeDeviceIndex = _deviceManager.Devices.CurrentIndex;
                    _deviceList[_activeDeviceIndex] = _deviceManager.Devices.Current;
                    _deviceIsOpen[_activeDeviceIndex] = true;


                    showUIToolStripMenuItem.Checked = _deviceList[_activeDeviceIndex].ShowUI;
                    modalUIToolStripMenuItem.Checked = _deviceList[_activeDeviceIndex].ModalUI;
                    _deviceList[_activeDeviceIndex].AcquiredImages.Capacity = 20;

                catch (TwainDeviceManagerException ex)
                    MessageBox.Show(ex.Message, "Open device manager");
This one seems to work :)