Ich habe TDBGrid erweitert um Bilder aus BLob-Felder anzuzeigen. Dabei sind mir einige bedenkenswerte Dinge aufgefallen.
Es hat mich sehr erstaunt, dass ich ein JPGBild welches ich problemlos per TDBImage als BLOB in eine SQLIte DB schreiben und auch lesen konnte, nicht aus dem BLOB-Stream des Feldes in ein TPicture laden konnte. Beim Versuch aus den Stream zu lesen kam die Meldung "Unbekanntes Bildformat".
Die Ursache offenbarte sich mir nach einiger Zeit der Recherche. TDBImage schreibt in den Blob-Stream eine Kennung den sogenannten Header, welcher beim späteren Lesen dem TDBImage-Feld sagen soll, was für ein Typ von Grafik (JPG, GIF, etc.) denn dort gespeichert ist.
Warum TDBImage diese Information nicht aus dem Header des Bildes auslesen kann bleibt mir ein Mysterium, da z.B. TPicture genau das kann.
In den neueren Versionen von Lazarus kann man dieses "Feature" von TDBImage deaktivieren (WriteHeader := False), mit der Folge, dass TDBImage seine in die DB geschriebenen Bilder nicht mehr laden kann. Was für ein Fortschritt

Für mich aber keine Lösung, da ich in meiner Anwendung sowohl TDBImage als auch ein TDBGrid mit Bildern anzeigen will.
Der folgende Code kloppt die Bilder brutal in die Zellen ohne auf die Aspect-Ratio Rücksicht zu nehmen. Das kann man einfach verbessern.
Mir geht es hier nur darum zu Zeigen, wie man das oben genannte Problem löst. Läuft unter Debian/Windows 64 Bit. Nicht getestet unter 32 Bit!
Code: Alles auswählen
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
ms : TMemoryStream; // Buffer for the image data
Image : TPicture; // Image Instance as source for drawing into the canvas of the grid cell
Field : TField; // The Field of the current cell in the DBGrid
BlobField : TBlobField; // The Field casted to a BlobField
begin
with (Sender As TDBGrid) do
begin
Field := Column.Field;
if Field.isBlob then // Do we deal with a blob field?
begin
ms := TMemoryStream.Create;
BlobField := TBlobField( Field );
if BlobField.BlobSize > 0 then // The blob maybe empty
begin
BlobField.SaveToStream(ms);
if ms.Position > 0 then // The blob may be empty, check again (redundant checking?)
begin
ms.Position := 8 ; //Skip TDBImage induced type code header. Not tested if the length of the header is platform dependend.
Image := TPicture.Create;
try
Image.LoadFromStream( ms ) ;
ms.Free ;
Canvas.StretchDraw(Rect, Image.graphic);
image.free;
except
end;
end;
end
else
begin // Draw a red cross in the cell if the Blob is empty
Canvas.Brush.color:= clwhite;
Canvas.Rectangle(Rect.Left, Rect.Top, Rect.Right, Rect.Bottom);
Canvas.Pen.color:= clred;
Canvas.Line(Rect.Left, Rect.Top, Rect.Right, Rect.Bottom );
Canvas.Line(Rect.Right, Rect.Top, Rect.Left, Rect.Bottom );
end;
end;
end;
end;
Auch lief der unter Debian entwickelte Code unter Windows out of the Box. Lazarus hält also sein Versprechen "Write Once compile everywhere". Und das ist unter Python tatsächlich nicht so einfach der Fall.
Aber mich haben andere Dinge furchtbar abgeschreckt:
* Gibt es kein Paket-System für Lazarus? Also wie CPAN, PyPI, etc. hat doch heute jede Programmiersprache einen Paket-Server und entsprechende Client-Tools um 3rd-Party-Pakete für jede Plattform standartisiert und reproduzierbar zur Verfügung zu stellen.
* Wie kann es sein, dass solche Inkompatibilitäten wie zwischen TPicture und TDBImage überhaupt auftreten? Wie kann es sein, dass der Fix an einer Komponente diese außer Gefecht setzt? In den 20 Jahren die ich mit Python programmiere ist es mir, mal abgesehen vom debuggen von Netzwerk-Protokollen, nie nötig gewesen einen Byte-Stream einer Komponente der Klassen-Bibliothek debuggen zu müssen.
* Es scheint mir keine Unterstützung für unterschiedliche VCS in Lazarus zu geben?
Ich weiß wie unfair es ist an eine Nischen-Sprache wie Lazarus die Anforderungen von Main-Stream-Sprachen wie Python zu stellen.
Aber Python war auch mal ein Nischen-Sprache. Diese Nische hat Python verlassen, in dem es sich großen Anforderungen gestellt hat und diese gemeistert hat.
Beste Grüße
Volker