tags:

views:

1272

answers:

6

Using the DelphiTwain files from http://delphitwain.sourceforge.net/ and am getting some weird behavior.

  1. After each scan a little more memory is being held onto.
  2. After an hour or so of repetitive scans, the image scanned is zoomed in approxamately 10 times, and just the upper-left square inch is stored.

Has anyone had similar issues, or have some suggestions?

Code below...

try
  try
    Twain := TDelphiTwain.Create(self);

    Twain.OnTwainAcquire := TwainAcquireHandler; //manually set the event handler
    Twain.OnSourceFileTransfer := TwainSourceFileTransfer;
    Twain.OnSourceSetupFileXfer := TwainSourceSetupFileXfer;

    Twain.LoadLibrary;
    Twain.LoadSourceManager;
    Twain.Source[0].Loaded := TRUE;
    Twain.Source[0].TransferMode := ttmFile;
    Twain.Source[0].EnableSource(false, false);
  except on e : exception do
    showmessage('Error loading Scanner.');
  end;

  try
    while Twain.Source[0].Enabled do
      Application.ProcessMessages;
  except on e : exception do
    showmessage('Error Scanning Packing List.');
  end;
finally
  Twain.Source[0].Loaded := FALSE;
  Twain.UnloadSourceManager(true);
  Twain.UnloadLibrary;
  Twain.Destroy;
end;
A: 

I can't address the problem you're reporting but you have a busy loop there that will gobble CPU time.

Loren Pechtel
+2  A: 

Examining the code within these calls may be fruitful:

TwainAcquireHandler;
TwainSourceFileTransfer;
TwainSourceSetupFileXfer;

Do any of those create any objects without freeing them?

If you are using Delphi 2006 or higher, then you can add this line to your .DPR file:

 ReportMemoryLeaksOnShutdown := True;

Then reproduce the memory leak, close your app... and it will describe the leaks in detail. A little more info about this can be found here.

On another note, I'd suggest replacing

Twain.Destroy;

with

FreeAndNil(Twain);

.Destroy will call the destructor directly, while FreeAndNil is a safer alternative that will also prevent the "Twain" variable from pointing anywhere dangerous. (See the accepted answer to this question).

JosephStyons
You don't know what FreeAndNil really does, or else you wouldn't have suggested it as a solution to a memory leak.
Rob Kennedy
Revised in response to your comment. It is still safer, though.
JosephStyons
A: 

What are you doing when you get the Image, did you keep in memory? Or the library can have some memory leaks, you can check if it is true with FastMM4.

Cesar Romero
+3  A: 

Since the TDelphiTwain appears to be a component you are creating in code, I would recommend passing in nil for the constructor and calling the .Free method or (as suggested by Joseph) FreeAndNil.

Twain := TDelphiTwain.Create(nil);
try
  try
    Twain.OnTwainAcquire := TwainAcquireHandler; //manually set the event handler
    Twain.OnSourceFileTransfer := TwainSourceFileTransfer;
    Twain.OnSourceSetupFileXfer := TwainSourceSetupFileXfer;

    Twain.LoadLibrary();
    Twain.LoadSourceManager();
    Twain.Source[0].Loaded := True;
    Twain.Source[0].TransferMode := ttmFile;
    Twain.Source[0].EnableSource(False, False);
  except on e : exception do
    showmessage('Error loading Scanner.');
  end;

  try
    while Twain.Source[0].Enabled do
      Application.ProcessMessages;
  except on e : exception do
    showmessage('Error Scanning Packing List.');
  end;
  Twain.Source[0].Loaded := False;
  Twain.UnloadSourceManager(True);
  Twain.UnloadLibrary();
finally
  FreeAndNil(Twain);
end;

I would also recommend better exception handling, but not related to question you asked. The only thing users will see and report to you (or worse, the quiet guy in the corner responsible for your IT support who loves to get non-descriptive errors from users) is 'Error doing something'

Good luck

Another area to look at is if the scanner supports WIA (Windows Image Acquisition)

var
  DevMgr: IDeviceManager;
  Scanner: Idevice;
  Picture: IItem;
  Image: OleVariant;
  AImage: IImageFile;
begin
  DevMgr := CreateOleObject('WIA.DeviceManager') as IDeviceManager;

  // Figure out which device is the scanner
  Scanner:= DevMgr.DeviceInfos.Item[1].Connect;

  //Command: Figure out which command scans..
  Picture := Scanner.ExecuteCommand(Scanner.Commands.Item[1].CommandID);

  //Transfer as JPG
  Image := Picture.Transfer(Picture.Formats.Item[1]);

  //Save the image
  AImage := IImageFile(Image);
  AImage.SaveFile('c:\wia_viaScanner\image.' + AImage.FileExtension);
end;

More info on the WIA library can be found here.. http://msdn.microsoft.com/en-us/library/ms629859(VS.85).aspx

KevinRF
A: 

to KevinRF:
I need to use WIA automation in Delphi 7 project. I registered WIAAut.dll in my system, import this library into Delphi and past your programm code into my project and got some errors:

Scanner:= DevMgr.DeviceInfos.Item[1].Connect;

Types of actual and formal var parameters must be identical
in "Item" must be Item[var Index: OleVariant], but "1" is integer

What's wrong, what i need to made it works?

Renat, this should be made a separate question.
Spike0xff
A: 

Got the same error any help?

pablo duarte