dynarithmic / twain_library

Dynarithmic TWAIN Library, Version 5.x
Apache License 2.0
60 stars 25 forks source link

Need to clear acquisition array during scan #45

Closed nswdxqq closed 1 year ago

nswdxqq commented 1 year ago

I'm evaluating the library for a scan project, and facing one problem with image acquisition as follows:

I need to acquire many images from scanner with one scan process;
I'm using buffered transfer from scanner;
During scanning a file for each image is created and the DIB is not needed anymore once the file is saved;
The memory keeps increasing during scanning and the program is out of memory finally;
So I'm curious if there is any way to clear the array of acquisition during scanning? And I'm using C# by the way.
dynarithmic commented 1 year ago

See the following for DTWAIN_SetUpdateDibProc.

If you can set up callbacks in C#, then this is what you can do:

What you could do is copy the DIB sent to you and save it to a file, and return a "dummy" small DIB your application created in your application. DTWAIN will recognize the DIB has been changed, and will free the memory of the original DIB it generated and replace it with your dummy DIB. This will not decrease the number of DIBs in the acquisition array, but will decrease the memory used.

Assuming you are using DTWAIN_AcquireBuffered(Ex), on return, you would simply go through the acquisitions (they will all be your dummy DIB), and you can simply call DTWAIN_ArrayDestroy() on the acquisition array (you don't want to delete the dummy dib, since you may want to use it for further acquisitions).

As to removing the DIB completely, I will look into this, as DTWAIN is designed to only remove the DIB completely on file transfers.

dynarithmic commented 1 year ago

Also, take a look at DTWDEMO.C and the DTWAIN_TN_QUERYPAGEDISCARD notification.

        case DTWAIN_TN_QUERYPAGEDISCARD:
        {
            LRESULT retVal;
            HANDLE h = DTWAIN_GetCurrentAcquiredImage(SelectedSource);
                        // Save the handle returned by DTWAIN_GetCurrentAcquiredImage
                        // ...
                        return 0; // throw the original DIB away
        }

See if something like this will work for you. When a 0 is returned, DTWAIN will remove the DIB memory.

In C#, you would set up a callback procedure:

                TwainAPI.DTWAIN_EnableMsgNotify(1); 
                TwainAPI.DTwainCallback64 twainCallback = TwainCallbackProc;
                TwainAPI.DTWAIN_SetCallback64(twainCallback, 0);

and TwainCallbackProc would have this layout:

private int TwainCallbackProc(int wParam, int lParam, long UserParam)
{
     if (wParam == TwainAPI.DTWAIN_TN_QUERYPAGEDISCARD)
     {
          DTWAIN_HANDLE ImageHandle = TwainAPI.DTWAIN_GetCurrentAcquiredImage(SelectedSource);
          if (ImageHandle != null)
          {
               // Save the handle to a file
               //...
           }
           return 0; // will delete the DIB from memory
      }
     return 1;
}
nswdxqq commented 1 year ago

OK, seems DTWAIN_TN_QUERYPAGEDISCARD works, need more evaluation, thanks!

dynarithmic commented 1 year ago

Great. I will close the ticket, and reopen if this solution doesn't work for you.