Recent

Author Topic: [SOLVED] Database .LoadFromStream problem  (Read 1799 times)

daveinhull

  • Sr. Member
  • ****
  • Posts: 266
  • 1 divided by nothing must still be 1!
[SOLVED] Database .LoadFromStream problem
« on: September 21, 2017, 10:12:48 am »
Hi (again, and sorry for all the questions)

I've managed to save an image to an underlying database table using:
Code: Pascal  [Select]
  1.   form1.SQLQuery7.Params.ParamByName('org_logo').LoadFromFile(pFileName,ftBlob);

and now I wanted to add the ability to save an image from the clipboard. I'm using the following code which all seems to work until I hit the .Refresh when it causes an exception (RunError 203) that I've tracked down a line (ReadImageHeader) in DBIMage.inc.

Code: Pascal  [Select]
  1.   if Clipboard.HasFormat(PredefinedClipboardFormat(pcfBitmap)) then
  2.     form1.imOrgLogo.Picture.Bitmap.LoadFromClipboardFormat(PredefinedClipboardFormat(pcfBitmap));
  3.   ms := TMemoryStream.Create;
  4.   form1.imOrgLogo.Picture.Bitmap.SaveToStream (ms);
  5.   ms.Position:=0;
  6.   intCurrentRecord:=form1.SQLQuery1.FieldValues['ID'];
  7.   form1.SQLQuery7.SQL.Text := 'update maindata set org_logo = :org_logo where id = :ID';
  8.   form1.SQLQuery7.Params.ParamByName('id').Value:=intCurrentRecord;
  9.   form1.SQLQuery7.Params.ParamByName('org_logo').LoadFromStream (ms,ftBlob);
  10.   form1.SQLQuery7.ExecSQL;
  11.   form1.SQLTransaction1.CommitRetaining;
  12.   form1.SQLQuery1.Refresh;
  13.   form1.SQLQuery1.Locate ('ID',intCurrentRecord,[]);

It also errors when the program starts with the database entry already in the table, so I'm guessing it has something to do with the MemoryStream operations, but not sure what.

Could anyone give me a pointer as to why this might be happening.

Many thanks in advance.

Dave
« Last Edit: September 22, 2017, 07:59:53 am by daveinhull »
Version #:1.8.4 Date 2019-01-08 FPC Version: 3.0.4 and SVN Revision 57972 for x86_64-win64-win32/win64

daveinhull

  • Sr. Member
  • ****
  • Posts: 266
  • 1 divided by nothing must still be 1!
Re: Database .LoadFromStream problem
« Reply #1 on: September 22, 2017, 07:59:16 am »
Hi,

Ok, I've found out what the problem is and I hope it helps others (the clue is on the documentation, but I just missed it).
The problem is that in Lazarus some header information is stored along with the image data, which is not done in Delphi.
In the latest stable release of Lazarus some extra functionality was added to make programming more compatible, and two event handlers were added to images.
These are OnDBImageRead and OnDBImageWrite.
If these are set the code works fine and doesn't error.
rom Lazarus documentation
Quote
TDBImage

Delphi compatible behaviour can now be set.

Lazarus TDBImage by default saves information about the file type before the image data. This allows seamless use of various file formats (.jpg, .bmp,...). Delphi does not save information about the file type.

To allow programmers to use TDBImage more flexibly, including supporting Delphi compatibility, two events to TDBImage were added:


TOnDBImageRead = procedure(Sender: TObject; S: TStream; var GraphExt : string) of object;
TOnDBImageWrite = procedure(Sender: TObject; S: TStream; GraphExt : string) of object;

If the first event is defined then it is called instead of TDBImage reading from the stream and must return the file extension as GraphExt. For example:


procedure TMyForm.TDBImageDBImageRead(Sender: TObject; S: TStream;
  var GraphExt: string);
begin
   GraphExt := 'jpg';
end;

can be used when the type of the image is always JPEG.

Similarly, if OnDBImageWrite is present then this is called instead of TDBImage writing the file extension to the start of the BLOB in the database. For example:


procedure TMyForm.PhotoDBImageWrite(Sender: TObject;
  S: TStream; GraphExt: string);
begin
  if GraphExt <> 'jpg' then
    raise Exception.Create('Can only save a JPEG Image');
end;

also works for an implicit JPEG.

Hope this helps someone.

Thanks
Dave
Version #:1.8.4 Date 2019-01-08 FPC Version: 3.0.4 and SVN Revision 57972 for x86_64-win64-win32/win64

daveinhull

  • Sr. Member
  • ****
  • Posts: 266
  • 1 divided by nothing must still be 1!
Re: [SOLVED] Database .LoadFromStream problem
« Reply #2 on: September 22, 2017, 06:42:24 pm »
Hi,

Just found something else, which was hidden at the bottom of the Object Inspector.

There is a flag called WriteHeader which is set by default. If this is cleared then there is no need to include the two procedures I mentioned previously.

It pays to look right down the list of options  %)
Version #:1.8.4 Date 2019-01-08 FPC Version: 3.0.4 and SVN Revision 57972 for x86_64-win64-win32/win64