0

I am trying to scan images using twaindotnet, and as long as the user keeps scanning I want to add the scanned image to the already scanned image.

In other words, when the user does his first scan, he well see the scan appear in an PictureBox, and when he performs his second scan, he will see in the PictureBox the first scan and below that the second scan.
After the third scan he will see in the PictureBox the first scan, below that the second scan and below that the third scan.
And so on...

So in the PictureBox there should actual be one large image, that has the combined height of all scans.

So I tried this

        private void buttonScan_Click(object sender, EventArgs e)
        {
            _twain = new Twain(new WinFormsWindowMessageHook(this));

            _twain.ScanningComplete += _twain_ScanningComplete;
            _twain.TransferImage += _twain_TransferImage;
            _twain.SelectSource(_twain.SourceNames[0]);
            ScanSettings scanSettings = new ScanSettings();

            /// to do: figure out how to use scansettings
            //scanSettings.Page.Size = TwainDotNet.TwainNative.PageType.A4;
            //scanSettings.Resolution.Dpi = 800;

            _twain.StartScanning(scanSettings);
        }

        private void _twain_ScanningComplete(object sender, ScanningCompleteEventArgs e)
        {
            buttonNextStep.Enabled = true;

            _twain.ScanningComplete -= _twain_ScanningComplete;
            _twain.TransferImage -= _twain_TransferImage;
        }


        private void _twain_TransferImage(object sender, TransferImageEventArgs e)
        {
            if (e.Image != null)
            {
                if (pictureBox1.Image == null)
                {
                    pictureBox1.Image = e.Image;
                }
                else
                {
                    Bitmap bitmap = new Bitmap(pictureBox1.Image.Width, pictureBox1.Image.Height + e.Image.Height);
                    using (Graphics g = Graphics.FromImage(bitmap))
                    {
                        g.DrawImage(pictureBox1.Image, 0, 0);
                        g.DrawImage(e.Image, 0, pictureBox1.Image.Height);

                        pictureBox1.Image = bitmap;
                    }
                }
            }
        }

which I based on this answer

It does puts the new scan in the picturebox below the prior scan, but it also creates a large empty area. It looks like the height of the image is not doubled after the second scan, but is increased by 4 times the height (in stead of 2)

Is the Height property of the Image maybe different then the height of a bitmap ?
Or what else can cause this ?

In the gif below you see the result of 2 scans, I expect both scans to be above eachother without the gray space. Both are scanned from an A4 paper. When I scan the first paper there is no extra space at the end of the image, I already checked that.

enter image description here

GuidoG
  • 11,359
  • 6
  • 44
  • 79
  • You should probably use a collection of bitmaps to present thumbnails of the actual scans (saved to disk) and show separated images that *appear* to be just one. This because the size of a Bitmap object is quite limited (much more than one may think, test it). -- A scrollable FlowLayoutPanel can do the job. -- Remember, when you create the Bitmaps, to verify the current Dpi settings against the scanned image Dpi, otherwise you may get *weird results*. – Jimi Jun 20 '22 at 15:56
  • E.g., see the `CopyToArgb32()` method here: [Resizing a Bitmap used as watermark the result shows dark borders](https://stackoverflow.com/a/61977870/7444103) and the notes (not the code) here: [Image is not drawn at the correct spot](https://stackoverflow.com/a/51456467/7444103) -- Having a DpiAware app helps quite a lot – Jimi Jun 20 '22 at 16:00
  • @Jimi I need it in one picture that will be saved on disk after confirming it looks correct, so I cannot store it in separated images. The image that will be stored can be a jpeg so there is no size limit, but most images will only be made of one scan, only some times 2 scans are needed – GuidoG Jun 21 '22 at 05:32
  • The limitation is not about the Image Format or the file on disk, it's about the .Net Bitmap object you're storing in memory. The BitmapData of Bitmap object must occupy a contiguous space in memory and each dimension cannot exceed (`ushort.MaxValue - [Padding]`) = `65500` pixels. The contiguous memory is not determined by the quantity of physical memory available in a machine and it's variable: you may have an exception while creating or saving a Bitmap of ~480mp or ~650mp, you cannot say when -- Just keep in mind these parameters when building your Bitmaps (i.e., it's an FYI) – Jimi Jun 21 '22 at 11:24
  • Storing temp images on disc and showing thumbnails (doesn't mean *small*) doesn't prevent combining in a single file when saving. -- You may find out this is what most (because I cannot say *all* for certain) software that handle scans do. – Jimi Jun 21 '22 at 11:24
  • 1
    @Jimi I understand what you mean now, and I will make it like that afterall. It seems I already done that once, I wrote a demo application in Delphi some years ago to do exact this. I forgot about it, and now I have to write the actual application but unfortunate I need to use Winforms. Anyway, in the Delphi source I did it like you said, should have read that back again earlier :) – GuidoG Jun 21 '22 at 13:50

1 Answers1

1

Try forcing images .Width and .Height in g.DrawImage:

g.DrawImage(pictureBox1.Image, 0, 0, pictureBox1.Image.Width, pictureBox1.Image.Height);
g.DrawImage(e.Image, 0, pictureBox1.Image.Height, e.Image.Width, e.Image.Height);

Here is an explanation of this behavior: https://stackoverflow.com/a/47695040/2400834

tezzo
  • 10,858
  • 1
  • 25
  • 48