1. Computing
Pictures inside a database
Page 4: Seeking the start of Jpeg in the BLOB.
 More of this Feature
• Page 1: BLOBs in Access
• Page 2: DBImage.NOT
• Page 3: Streaming JPG
• Page 5: Project's Code

Printer friendly versionPrinter friendly version
 Join the Discussion
"Post your views and comments to this chapter of the free Delphi database Programming Course"
Discuss!
  Related Resources
• free DB Course.TOC
• Delphi DB articles
 

  OLE object type format - take three!
All this leaves us with nothing but to store the picture to a disk (as an ordinary binary file) and see what's inside it.
One nice thing with picture files (formats) is that all have some header that uniquely identifies the image. The JPG picture file starts with the, so called, SOI marker that has the value of $FFD8 hex.

This next line of code stores the value of the Picture field to a file (BlobImage.dat) in the working directory. Assign this code in the OnCreate event for the form, start the project and remove the code.

ADOTable1Picture.SaveToFile('BlobImage.dat');

Once we have the file, we can use some Hex editor to see it's content.

Jpeg as OLE object binary file

Would you believe this! MS Access stores the path of a linked OLE object as part of the object's definition in the OLE object field. Because the definition of OLE object storage is not documented (!? this is straight from MS) there is no way to know what gets written before the actual image data.

Think about this twice. First: we'll need to seek to the 'FFD8' and read the image from there. Second, the 'FFD8' might not always be at the same position in the file. Conclusion: we need a function that returns the position of the SOI marker for the JPG file stored as OLE object in an Access database.

  The correct way - take four!
Provided with the Blob type field our function should return the position of the 'FFD8' string inside the ADOBlobStream. The ReadBuffer reads byte by byte from the stream. Each call to ReadBuffer moves the position of the stream by one. When two bytes together (as hex values) result in SOI marker the function returns the stream position. This is the function:

function JpegStartsInBlob
         (PicField:TBlobField):integer;
var
 bS     : TADOBlobStream;
 buffer : Word;
 hx     : string;
begin
 Result := -1;
 bS := TADOBlobStream.Create(PicField, bmRead);
 try
  while (Result = -1) and
        (bS.Position + 1 < bS.Size) do
  begin
   bS.ReadBuffer(buffer, 1);
   hx:=IntToHex(buffer, 2);
   if hx = 'FF' then begin
     bS.ReadBuffer(buffer, 1);
     hx:=IntToHex(buffer, 2);
     if hx = 'D8' then Result := bS.Position - 2
     else if hx = 'FF' then
      	bS.Position := bS.Position-1;
   end; //if
  end; //while
 finally
  bS.Free
 end;  //try
end;

Once we have the position of the SOI marker we use it to seek to it in the ADOBlob stream.

uses jpeg;
...
procedure TForm1.btnShowImageClick(Sender: TObject);
var
  bS  : TADOBlobStream;
  Pic : TJpegImage;
begin
  bS := TADOBlobStream.Create
        (AdoTable1Picture, bmRead);
  try
    bS.Seek(JpegStartsInBlob(AdoTable1Picture),
            soFromBeginning);
    Pic:=TJpegImage.Create;
    try
     Pic.LoadFromStream(bS);
     ADOImage.Picture.Graphic:=Pic;
    finally
     Pic.Free;
    end;
  finally
    bS.Free
  end;
end;

Run the project and voila!

JPG image from MS Access with ADO

Who can now say that programming isn't FUN?

Note: in real code application we would have the code to read and display the image from the current row in the AfterScroll event of a TDataSet (that is in the ADOTable1AfterScroll event procedure). AfterScroll occurs after an application scrolls from one record to another.

  Take five!
That's it for this chapter. You can now store and display all your favorite JPG pictures. In the last page of this article I have provided you with the entire code (form1's unit); all the data assignment is placed in the OnCreate event of the form. This ensures that all three components are correctly linked - you don't need to use the Object Inspector at design-time.
I agree, the chapter was not designed for beginners, but hey the World is cruel. Another thing: did you mentioned that at the end you don't know how to change (or add some new) picture in a table! We'll, that's whole another story!

Hm, ok I give up! Take a look at the code ... see the "SaveJpegToTable" procedure? This one does the job of placing a picture inside a database.

Next page > Project's Code > Page 1, 2, 3, 4, 5

DB Course Next Chapter >>
>> Chapter 4: Data browsing

©2014 About.com. All rights reserved.