Tema: objeto ole
Ver Mensaje Individual
  #6  
Antiguo 31-10-2003
Avatar de marcoszorrilla
marcoszorrilla marcoszorrilla is offline
Capo
 
Registrado: may 2003
Ubicación: Cantabria - España
Posts: 11.221
Reputación: 10
marcoszorrilla Va por buen camino
Léete esta información:

RTL reference|Glossary|Tips/Tricks|FREE App/VCL|Best'O'Net|Books|Link To

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:

Código:
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;
Un saludo.
__________________
Guía de Estilo de los Foros
Cita:
- Ça c'est la caisse. Le mouton que tu veux est dedans.
Responder Con Cita