3
votes

I have been trying to load image data stored in a varbinary mssql column to a TImage component using the code below, but it gives an error

 with Query_Refresh do
   Begin
     close;
     open;
     if RecordCount > 0 then
       Begin
         //Edit to allow the streaming of the fields
         Edit;

         //MyStream is of Type TStream
         MyStream := CreateBlobStream(FieldByName('MyBlobField'),bmWrite);

         //Loading to the image --- Error occurs on the line below
         MyImage.Picture.Graphic.LoadFromStream(MyStream);
       End;
   End;

Error is Access violation....

Please someone assist on how to do this

1
Access violation, means that you are trying to access a object that do not exists. which line is the error happening? FieldByName('MyBlobField') returns the instance of MyBLobField? I suggest you to remove your "with Query_Refresh do", it will make debug harder. - Cesar Romero
First, I'd get rid of the with statement and replace it with an explaining variable. Which line does the access violation occur on? - Kenneth Cochran
Error occured when trying to load the TStream to the Timage object - KE50
@Ceasar MyBlobField is just the name of the varbinary field in the database - KE50
shouldn't it be bmRead rather than bmWrite? - A Lombardo

1 Answers

6
votes

TPicture does not hold a TGraphic unless you tell it to. It starts out empty, so the Graphic property is null. That's why you get an access violation when you try to call methods on it.

If you don't already know what kind of graphic you've stored, you'll either have to write something that inspects the contents of the field to figure it out, or add another field to your database that describes the format of the graphic field.

Once you know what kind of graphic you have, you can create an instance of that class, load it from the stream, and assign it to the TPicture container. Free your graphic afterward since TPicture creates its own copy of the graphic. Here's an example:

var
  DBGraphicClass: TGraphicClass;
  Graphic: TGraphic;

// Implementing FieldValToGraphicClass is an exercise for the reader.
DBGraphicClass := FieldValToGraphicClass(FieldByName('MyBlobFieldType'));
Graphic := DBGraphicClass.Create;
try
  Graphic.LoadFromStream(MyStream);
  MyImage.Picture.Graphic := Graphic;
finally
  Graphic.Free;
end;

If the known type is always one of the graphic properties that TPicture already has, then you can access the type-specific property directly and skip the step of allocating your own graphic object. For example, if your database holds bitmaps, then you can access TPicture.Bitmap instead of TPicture.Graphic. Then TPicture will create a TBitmap object automatically. For example:

MyImage.Picture.Bitmap.LoadFromStream(MyStream);