-3

I'm using Delphi 5 Enterprise because that's what the program I'm working with was written in. I have written a procedure which saves bitmaps to an Access database quite happily. Now I want to be able to retrieve the bitmaps. Saving the bitmaps, I use SaveToStream. Retrieving them, I used LoadFromStream but the compiler tells me that it doesn't recognise that function. The code is below:

 procedure TForm1.Button2Click(Sender: TObject);
 var
    Field : TBlobField;
    Stream : TStream;
    BMap : TBitMapImage;
 begin
   if BloBQuery.Active then
      begin
         Field := TBlobField(BlobQuery.FieldByName('Blob'));
         Stream := BlobQuery.CreateBlobStream(Field, bmRead);
         BMap := TBitMapImage.Create;
      try
         Image2.Picture.Graphic := BMap.LoadFromStream(Stream);
      finally
         BMap.Free;
         Stream.Free;
      end;
   end;
end;

Can anyone tell me when LoadFromStream won't work? It seems odd! Thanks.

The code which wrote the bitmap was:

    procedure TForm1.Button1Click(Sender: TObject);
var
  Field : TBlobField;
  Stream : TStream;
begin
   if (BlobQuery.Active = True) and (Image1.Picture.Graphic <> nil) then begin
       BlobQuery.Insert;
       Field := TBlobField(BlobQuery.FieldByName('Blob'));
       Stream := BlobQuery.CreateBlobStream(Field, bmWrite);
       try
          Image1.Picture.Graphic.SaveToStream(Stream);
       finally
          Stream.Free;
          BlobQuery.Post;
       end;
   end;
end;
Capfka
  • 353
  • 2
  • 6
  • 15
  • The compiler is telling you that `TBitmapImage` has no method named `LoadFromStream`. And that is correct. It also has no method named `SaveToStream`. So I'm not sure what your code is doing to save to the stream, but it certainly is not calling `SaveToStream` on a `TBitmapImage`. In order to give you proper help, we'll want to see the code that saves the image. Are you calling `Graphic.SaveToStream`, or `Graphic.Bitmap.SaveToStream`, or perhaps something else altogether? It's always worth reading error messages. The error message contains information, which you seem to have ignored. – David Heffernan Oct 26 '18 at 12:47
  • In the future, please include the **exact** error message in your post. – Ken White Oct 26 '18 at 12:47
  • Hi, the compiler error is: [Error] Unit1.pas(70): Undeclared identifier: 'LoadFromStream' – Capfka Oct 26 '18 at 12:50
  • The code which saved the bitmap was: procedure TForm1.Button1Click(Sender: TObject); var Field : TBlobField; Stream : TStream; begin if (BlobQuery.Active = True) and (Image1.Picture.Graphic <> nil) then begin BlobQuery.Insert; Field := TBlobField(BlobQuery.FieldByName('Blob')); Stream := BlobQuery.CreateBlobStream(Field, bmWrite); try Image1.Picture.Graphic.SaveToStream(Stream); finally Stream.Free; BlobQuery.Post; end; end; end; – Capfka Oct 26 '18 at 12:51
  • No! Not in comments. Edit the question. You've been here long enough now to know this. Please make an effort to ask high quality questions. When you've made the edit, read the code that you used to save the image, and see if it becomes obvious why the code to load it fails, and what it should really be. I'm sure if you think a little harder it will become obvious. – David Heffernan Oct 26 '18 at 12:51
  • You are confusing a bitmap with a bitmapimage. Additionally LoadFromStream does not return a bitmap. It doesn't return anything at all. Slow down, search some questions about loading/saving images to/from database. – Sertac Akyuz Oct 26 '18 at 12:55
  • 1
    In the comments to my deleted answer, you made it clear that you weren't interested in learning. I have fixed my answer, fixing the defect in the original version. But I really have no more enthusiasm for this process. – David Heffernan Oct 26 '18 at 13:18
  • I deleted the comments by accident. I am willing to learn, but since I've never used the debugger I don't know where to start. I haven't seen your fix. Thanks anyway. – Capfka Oct 26 '18 at 13:34
  • Perhaps you meant `Image2.Picture.Graphic.LoadFromStream(Stream);`? – Jerry Dodge Oct 26 '18 at 14:14
  • I tried that, but I still got the access error. – Capfka Oct 26 '18 at 16:55
  • And the debugging? – David Heffernan Oct 26 '18 at 17:46
  • Access error? You mean Access Violation? You reported a different error before. Anyway, not that it's the proper solution, I'm just proposing that may have been what you meant to put in that procedure, being the exact reverse of how you saved it. Although I know that's not the proper solution. – Jerry Dodge Oct 26 '18 at 19:43

1 Answers1

3

Assuming Image1.Picture.Graphic was pointing at a TBitmap object when you saved it to the DB, you need to use a TBitmap object instead of a TBitMapImage object when reading the image back out, eg:

procedure TForm1.Button2Click(Sender: TObject);
var
  Field : TBlobField;
  Stream : TStream;
  BMap : TBitmap;
begin
  if BlobQuery.Active then
  begin
    Field := TBlobField(BlobQuery.FieldByName('Blob'));
    Stream := BlobQuery.CreateBlobStream(Field, bmRead);
    try
      BMap := TBitmap.Create;
      try
        BMap.LoadFromStream(Stream);
        Image2.Picture.Graphic := BMap;
      finally
        BMap.Free;
      end;
    finally
      Stream.Free;
    end;
  end;
end;

Alternatively:

procedure TForm1.Button2Click(Sender: TObject);
var
  Field : TBlobField;
  Stream : TStream;
begin
  if BlobQuery.Active then
  begin
    Field := TBlobField(BlobQuery.FieldByName('Blob'));
    Stream := BlobQuery.CreateBlobStream(Field, bmRead);
    try
      Image2.Picture.Bitmap.LoadFromStream(Stream);
    finally
      Stream.Free;
    end;
  end;
end;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thanks Remy. I will try that in the morning. Much appreciated. – Capfka Oct 26 '18 at 16:57
  • Remy, thanks for that. Both of them work although the first approach is the one I need for what I am trying to do. Much appreciated. I knew it was something simple, Bitmap. Remember that! Thanks again. – Capfka Oct 27 '18 at 09:46
  • @Capfka Read Remy's answer again! Don't rely that you code will always save your image as bitmap and that you can later load it wuing TBitmap class. For instance if you go and load a JPG imate to your TImage component and then use your code for saving that image into database the image won't ba saved as bitmap but instead as JPEG image and you would then need to use TJPEGImage clas for loading it instead of TBitmap. So good aproach would be so that you also save the information about the image type into your database and then use that information when lading the image from database. – SilverWarior Oct 29 '18 at 10:31
  • Or, at least look at the first few bytes of the stored image data to determine the image type. Different image types have unique signature bytes – Remy Lebeau Oct 29 '18 at 13:51
  • Actually there is a better way that I haven't remembered before. And that is to actually use `TImage.Picture.SaveToStrem` fwhen saving and `TImage.Picture.LoadFromStream` when loading image from stream. This way the loading routine check the image type automatically and creates needed container for it. Data about which image type is stored in stream is written with SaveToStream routine of TPciture or of any TGraphic descendant http://docwiki.embarcadero.com/Libraries/Tokyo/en/Vcl.Graphics.TPicture.LoadFromStream – SilverWarior Oct 29 '18 at 14:55
  • @SilverWarior if it does (which I can't verify since I don't have Berlin+ installed), that must be new functionality added recently. It certainly did not exist in D5, which the OP is using. In D5 (and up to just a few years ago, at least), `TPicture.(SaveTo|LoadFrom)Stream()` simply called `TPicture.Bitmap.(SaveTo|LoadFrom)Stream()` unconditionally, so it could only save/load BMP images. – Remy Lebeau Oct 29 '18 at 20:24
  • Thaks to both Remy and SilverWarrior for the further information. Fortunately, I am only creating bitmaps of barcodes for temporary use in a report, so the dangers that SilverWarrior mentions won't come into play. It's been a interesting journey for me as a very part-time Delphi user. Again, thanks to you both. – Capfka Oct 30 '18 at 11:43