Sección 4: Encontrar el comienzo de JPEG en BLOB
Formato de tipo de objeto OLE: ¡toma tres!
Ahora todo lo que tenemos que hacer es almacenar la imagen en el disco (como un archivo binario simple) y comprender qué contiene.
Todos los archivos de imagen (formatos) tienen encabezados de archivo que identifican de forma única la imagen. Los archivos de imagen JPG comienzan con la llamada etiqueta SOI, cuyo valor hexadecimal es $FFD8.
La siguiente línea de código almacena el valor del campo de imagen en el archivo correspondiente (BlobImage.dat) en el directorio de trabajo. Coloque este código en el evento OnCreate del formulario y elimínelo después de iniciar el proyecto.
ADOTable1Picture.SaveToFile('BlobImage.dat');
Una vez que tengamos este archivo. Podemos utilizar el editor Hex para ver su contenido.
¿Lo crees? MS Access almacena la ruta al objeto OLE conectado en el campo del objeto OLE como parte de la definición del objeto. Debido a que la definición de almacenamiento de los objetos OLE no está documentada (¡¿¡Esto viene directamente de MS), no hay forma de saber qué datos reales de la imagen obtendrán antes de escribirlos.
Considere esta pregunta en dos partes. Primero: necesitamos encontrar 'FFD8' y comenzar a leer la imagen desde allí. Segundo: 'FFD8' no siempre puede estar en la misma posición en el archivo. Conclusión: Necesitamos una función que devuelva la ubicación de la etiqueta SOI de un archivo JPG almacenado como un objeto OLE en la base de datos de Access.
La forma correcta: ¡toma cuatro!
Con un campo de tipo Blob proporcionado, nuestra función debería devolver la posición de la cadena 'FFD8' en ADOBlobStream. ReadBuffer lee datos de la secuencia byte a byte. Cada llamada a ReadBuffer mueve la posición de la secuencia byte a byte. La función devuelve la posición de la secuencia cuando dos bytes juntos conducen al marcador SOI. Esta es la función:
función JpegStartsInBlob(PicField:TBlobField):entero;
var
bS: TADOBlobStream;
búfer: Palabra;
hx: cadena;
comenzar
Resultado := -1;
bS := TADOBlobStream.Create(PicField, bmRead);
intentar
mientras que (Resultado = -1) y (bS.Position + 1 < bS.Size) lo hacen
comenzar
bS.ReadBuffer(búfer, 1);
hx:=IntToHex(búfer, 2);
si hx = 'FF' entonces comienza
bS.ReadBuffer(búfer, 1);
hx:=IntToHex(búfer, 2);
si hx = 'D8' entonces Resultado: = bS.Position - 2
de lo contrario, si hx = 'FF', entonces
bS.Posición := bS.Posición-1;
fin; //si
fin; //mientras
finalmente
bS.Gratis
fin; //intenta
fin;
Una vez que tengamos la ubicación del marcador SOI, podemos usarlo para encontrar la ubicación de la imagen en la secuencia ADOBlob.
utiliza jpeg;
...
Procedimiento TForm1.btnShowImageClick(Remitente: TObject);
var
bS: TADOBlobStream;
Imagen: TJpegImage;
comenzar
bS := TADOBlobStream.Create(AdoTable1Picture, bmRead);
intentar
bS.Seek(JpegStartsInBlob(AdoTable1Picture),soFromBeginning);
Imagen:=TJpegImage.Create;
intentar
Pic.LoadFromStream(bS);
ADOImage.Picture.Graphic:=Imagen;
finalmente
Imagen.Gratis;
fin;
finalmente
bS.Gratis
fin;
fin;
Ejecute el proyecto, ¡OK!
Ahora bien, ¿quién puede decir que programar no es divertido?
Nota: En el programa de código real, agregaremos código para leer y mostrar la imagen de la fila actual en el evento AfterScroll de TDataSet (está en el procedimiento del evento ADOTable1AfterScroll). El evento AfterScroll ocurre cuando la aplicación se desplaza de un registro a otro.
¡Idea cinco!
De eso se trata este capítulo. Ahora puedes almacenar y mostrar todas las imágenes JPG que te interesen. En la última página de este artículo, proporcionaré el código completo (unidad formulario1); toda la disposición de los datos se coloca en el evento OnCreate del formulario. Esto garantiza que los tres componentes estén conectados correctamente; no es necesario utilizar el Inspector de objetos al diseñar.
Lo admito, este capítulo no es para principiantes, ¡pero el mundo es un lugar cruel! Otra cosa: ¡notas que al final ni siquiera sabes cómo cambiar (o agregar algunas nuevas) imágenes a la tabla! ¡Sí, esa es otra historia!