Abschnitt 4: Den Anfang von JPEG in BLOB finden
OLE-Objekttypformat – nehmen Sie drei!
Jetzt müssen wir nur noch das Bild auf der Festplatte speichern (als einfache Binärdatei) und verstehen, was sich darin befindet.
Alle Bilddateien (Formate) verfügen über Dateikopfzeilen, die das Bild eindeutig identifizieren. JPG-Bilddateien beginnen mit einem sogenannten SOI-Tag, dessen Hexadezimalwert $FFD8 ist.
Die folgende Codezeile speichert den Bildfeldwert in der entsprechenden Datei (BlobImage.dat) im Arbeitsverzeichnis. Platzieren Sie diesen Code im OnCreate-Ereignis des Formulars und entfernen Sie ihn nach dem Start des Projekts.
ADOTable1Picture.SaveToFile('BlobImage.dat');
Sobald wir diese Datei haben. Wir können den Hex-Editor verwenden, um seinen Inhalt anzuzeigen.
Glaubst du es? MS Access speichert den Pfad zum verbundenen OLE-Objekt im OLE-Objektfeld als Teil der Objektdefinition. Da die Speicherdefinition von OLE-Objekten nicht dokumentiert ist (!? Dies kommt direkt von MS), gibt es keine Möglichkeit zu wissen, was die tatsächlichen Bilddaten erhalten, bevor sie geschrieben werden.
Betrachten Sie diese Frage in zwei Teilen. Erstens: Wir müssen „FFD8“ finden und von dort aus mit dem Lesen des Bildes beginnen. Zweitens: „FFD8“ kann nicht immer an derselben Position in der Datei stehen. Fazit: Wir benötigen eine Funktion, die den Speicherort des SOI-Tags einer JPG-Datei zurückgibt, die als OLE-Objekt in der Access-Datenbank gespeichert ist.
Der richtige Weg – nimm vier!
Wenn ein Feld vom Typ Blob bereitgestellt wird, sollte unsere Funktion die Position der Zeichenfolge „FFD8“ im ADOBlobStream zurückgeben. ReadBuffer liest Daten Byte für Byte aus dem Stream. Jeder Aufruf von ReadBuffer verschiebt die Position des Streams Byte für Byte. Die Funktion gibt die Position des Streams zurück, wenn zwei Bytes zusammen zum SOI-Marker führen. Das ist die Funktion:
function JpegStartsInBlob(PicField:TBlobField):integer;
var
bS: TADOBlobStream;
Puffer: Wort;
hx: Zeichenfolge;
beginnen
Ergebnis := -1;
bS := TADOBlobStream.Create(PicField, bmRead);
versuchen
während (Ergebnis = -1) und (bS.Position + 1 < bS.Größe) dies tun
beginnen
bS.ReadBuffer(buffer, 1);
hx:=IntToHex(buffer, 2);
Wenn hx = 'FF', dann beginnen
bS.ReadBuffer(buffer, 1);
hx:=IntToHex(buffer, 2);
wenn hx = 'D8' dann Ergebnis := bS.Position - 2
sonst wenn hx = 'FF' dann
bS.Position := bS.Position-1;
Ende; //wenn
Ende; //während
Endlich
bS.Frei
Ende; //versuchen
Ende;
Sobald wir die Position der SOI-Markierung haben, können wir sie verwenden, um die Position des Bildes im ADOBlob-Stream zu finden.
verwendet JPEG;
...
PROcedure TForm1.btnShowImageClick(Sender: TObject);
var
bS: TADOBlobStream;
Bild: TJpegImage;
beginnen
bS := TADOBlobStream.Create(AdoTable1Picture, bmRead);
versuchen
bS.Seek(JpegStartsInBlob(AdoTable1Picture),soFromBeginning);
Pic:=TJpegImage.Create;
versuchen
Pic.LoadFromStream(bS);
ADOImage.Picture.Graphic:=Pic;
Endlich
Bildfrei;
Ende;
Endlich
bS.Free
Ende;
Ende;
Führen Sie das Projekt aus, OK!
Wer kann nun sagen, dass Programmieren keinen Spaß macht?
Hinweis: Im echten Codeprogramm fügen wir Code hinzu, um das Bild aus der aktuellen Zeile im AfterScroll-Ereignis von TDataSet zu lesen und anzuzeigen (es befindet sich in der ADOTable1AfterScroll-Ereignisprozedur). Das AfterScroll-Ereignis tritt auf, wenn die Anwendung von einem Datensatz zum anderen scrollt.
Idee fünf!
Darum geht es in diesem Kapitel. Jetzt können Sie alle JPG-Bilder, die Sie interessieren, speichern und anzeigen. Auf der letzten Seite dieses Artikels werde ich den vollständigen Code (Form1-Einheit) bereitstellen; die gesamte Datenanordnung wird im OnCreate-Ereignis des Formulars platziert. Dadurch wird sichergestellt, dass alle drei Komponenten korrekt verbunden sind – Sie müssen beim Entwerfen nicht den Objektinspektor verwenden.
Ich gebe zu, dieses Kapitel ist nichts für Anfänger, aber die Welt ist ein grausamer Ort! Noch etwas: Sie bemerken, dass Sie am Ende nicht einmal wissen, wie Sie Bilder in der Tabelle ändern (oder neue hinzufügen) können! Ja, das ist eine ganz andere Geschichte!