MS Access guarda las imagenes en campos de tipo objeto OLE. La informacion que guarda es el stream del archivo .bmp con una cabecera que contiene la aplicacion con la que tiene que abrir el stream. El stream entero es inservible para trabajar directamente con freepascal/Lazarus asi que lo que viene a continuacion es una manera de usar ese objeto OLE para incrustarlo en un Dbf y poder trabajar mas agilmente en Lazarus.
A continuacion vamos a mostrar distintos contenidos de streams para entender que vamos haciendo.
Archivo BMP :

Como se puede ver “BM” marca el inicio del stream.
Archivo BMP incrustado en un campo de tipo objeto OLE de MS Access :

Aqui se puede observar la cabecera que comentabamos antes.
Archivo BMP incrutado en un campo de tipo BLOB en un Dbf :

Observamos que la cabecera se reduce en comparacion al objeto OLE.
Para conseguir nuestro objetivo lo primero que tenemos que hacer es determinar la posicion del “BM” para poder extraer la informacion que nos interesa, para este fin usamos la siguiente funcion:
function buscaPosicionBM(STmp : TStream) : Integer;
var
i : Integer;
begin
STmp.Seek(0,0);
for i:=0 to 100 do
begin
if STmp.ReadByte = 66 then
if STmp.ReadByte = 77 then
buscaPosicionBM:=STmp.Position-2;
end;
end;
Y a continuacion toda la chicha, o sea, cargamos el objeto OLE en un stream, le quitamos la informacion innecesaria para nosotros y lo metemos en un campo blob de un Dbf.
procedure carga;
var
Stream, StreamClean : TStream;
FieldStr : String;
PFieldStr : PChar;
posicion : Integer;
begin
// Cargamos el objeto OLE al Stream
Stream := TMemoryStream.Create;
Stream := q.CreateBlobStream(q.FieldByName(’DIBUJO’), bmRead);
// Conseguimos la posicion del “BM”
posicion :=buscaPosicionBM(Stream);
// Creamos el stream para añadir despues al Dbf
StreamClean := TMemoryStream.Create;
// Añadimos la cabecera para el Dbf
StreamClean.WriteByte(3);
StreamClean.WriteByte(0);
StreamClean.WriteByte(0);
StreamClean.WriteByte(0);
StreamClean.WriteByte(98);
StreamClean.WriteByte(109);
StreamClean.WriteByte(112);
// Nos posicionamos correctamente y copiamos la informacion necesaria
Stream.Seek(posicion, soFromBeginning);
StreamClean.Position:=7;
StreamClean.CopyFrom(Stream,Stream.Size - posicion);
StreamClean.Seek(0,0);
SetLength(FieldStr, StreamClean.Size);
PFieldStr := PChar(FieldStr);
StreamClean.Read(PFieldStr^, StreamClean.Size);
// Volcamos el Stream creado al Dbf
reportDbf.Append;
reportDbf.FieldByName(’Codigo’).Assign(q.FieldByName(’Codigo’));
reportDbf.FieldByName(’descripcion’).Assign(q.FieldByName(’descripcion’));
reportDbf.FieldByName(’dibujo’).Value := FieldStr;
reportDbf.Post;
// Liberamos recursos
Stream.Free;
archivoLog.Free;
end;
Comentar que q es un TSQLQuery de SQLdb, reportDbf es un TDbf y he usado el programa Hexplorer para ver los entresijos de los streams.
Si algo no ha quedado muy claro me dejais un comentario e intentare explicarme lo mejor que pueda O:)