Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi PNG-Bild aus BLOB-Feld in Image laden (https://www.delphipraxis.net/156928-png-bild-aus-blob-feld-image-laden.html)

scrat1979 20. Dez 2010 19:50

Datenbank: Absolute Database • Version: 6 • Zugriff über: ABS-Komponenten

PNG-Bild aus BLOB-Feld in Image laden
 
Hallo zusammen,

ich versuche gerade ein PNG-Bild, welches in einem BLOB-Feld einer Datenbank liegt, in eine Image-Komponente zu bekommen. Die Image-Komponente kann auch PNG darstellen, das Laden eines PNG-Bildes mittels OI funktioniert jedenfalls problemlos. Speichere ich das Bild
in einem FileStream und speicher es, dann kann ich es auch problemlos öffnen, also am Zugriff auf die DB oder an einem "korrupten" Header scheint es nicht zu liegen. Nach dem Aufrufen der Funktion erhalte ich eine Zugriffsverletzung...

Delphi-Quellcode:
var
  BlobStream: TStream;
  aq : tabsquery;
begin
      aq := tabsquery.Create(nil);
      aq.DatabaseName := 'xyz';
      aq.SQL.Add('SELECT bild FROM tbltest WHERE id = 1');
      aq.Open;
      BlobStream := aq.CreateBlobStream(aq.FieldByName('bild'),bmRead);
      ImageAnswer.Picture.Graphic.LoadFromStream(BlobStream); // liegt auf der Form!!!
      BlobStream.Free;
      aq.Close;
      aq.Free;
end;
Kann sich jemand vorstellen, warum das nicht funktioniert???

Danke im Voraus,
Michael

mkinzler 20. Dez 2010 19:54

AW: PNG-Bild aus BLOB-Feld in Image laden
 
Besser:
Delphi-Quellcode:
aq.SQL.Text := 'SELECT bild FROM tbltest WHERE id = 1';
In welcher Zeile kommt die Zugriffsverletzung

Bernhard Geyer 20. Dez 2010 20:01

AW: PNG-Bild aus BLOB-Feld in Image laden
 
Du musst das PNG erst in eine temporäre Instanz der PNG-Imagekomponente laden. TPicture kann nur beim laden aus einer Datei über die Dateiextension das Grafikformat erkennen. Beim Stream als Stream müsste hier noch der Klassenname der entsprechenden Grafikkomponente am Anfangen stehen. Einfach mal ein PNG mit der IDE zuweisen und dann die DFM anschauen. Dort steht etwas in der Art: "TPNGImage" vor den eigentlichen PNG-Stream.

scrat1979 21. Dez 2010 08:27

AW: PNG-Bild aus BLOB-Feld in Image laden
 
Zitat:

Zitat von Bernhard Geyer (Beitrag 1069660)
Du musst das PNG erst in eine temporäre Instanz der PNG-Imagekomponente laden. TPicture kann nur beim laden aus einer Datei über die Dateiextension das Grafikformat erkennen. Beim Stream als Stream müsste hier noch der Klassenname der entsprechenden Grafikkomponente am Anfangen stehen. Einfach mal ein PNG mit der IDE zuweisen und dann die DFM anschauen. Dort steht etwas in der Art: "TPNGImage" vor den eigentlichen PNG-Stream.

Hmmmm, dachte, ich hätte das schonmal versucht. ich werde es im laufe des Tages testen und mein Feedback abgeben

@mkinzler: die Zugriffsverletzung kommt beim "..LoadFromStream(...);". wie gesagt, die gleiche Anweisung mit einem TFileStream funktioniert problemlos. Es müsste wohl tatsächlich ein spezifisches Problem mit dem Laden in die TImage-Komponente sein.

Danke schonmal!

scrat1979 21. Dez 2010 15:29

AW: PNG-Bild aus BLOB-Feld in Image laden
 
Zitat:

Zitat von Bernhard Geyer (Beitrag 1069660)
Du musst das PNG erst in eine temporäre Instanz der PNG-Imagekomponente laden. TPicture kann nur beim laden aus einer Datei über die Dateiextension das Grafikformat erkennen. Beim Stream als Stream müsste hier noch der Klassenname der entsprechenden Grafikkomponente am Anfangen stehen. Einfach mal ein PNG mit der IDE zuweisen und dann die DFM anschauen. Dort steht etwas in der Art: "TPNGImage" vor den eigentlichen PNG-Stream.

UPDATE: Funktioniert perfekt! Hatte damals vergessen, die Unit "PNGImage" einzubinden!! Danke!

Deep-Sea 21. Dez 2010 15:33

AW: PNG-Bild aus BLOB-Feld in Image laden
 
Tipp: Nutze doch bitte try-finally-Blöcke:
Delphi-Quellcode:
aq := tabsquery.Create(nil);
try
  // Tue etwas mit aq
finally
  aq.Free;
end;
:thumb:

scrat1979 21. Dez 2010 16:45

AW: PNG-Bild aus BLOB-Feld in Image laden
 
Zitat:

Zitat von Deep-Sea (Beitrag 1069802)
Tipp: Nutze doch bitte try-finally-Blöcke:
Delphi-Quellcode:
aq := tabsquery.Create(nil);
try
  // Tue etwas mit aq
finally
  aq.Free;
end;
:thumb:

Schon klar :-) Wollte aber nur den wesentlichen Code posten. Trotzdem Danke für den Hinweis, Deep-Sea!!!

Laaeris 2. Sep 2020 10:14

AW: PNG-Bild aus BLOB-Feld in Image laden
 
Zitat:

Zitat von scrat1979 (Beitrag 1069801)
Zitat:

Zitat von Bernhard Geyer (Beitrag 1069660)
Du musst das PNG erst in eine temporäre Instanz der PNG-Imagekomponente laden. TPicture kann nur beim laden aus einer Datei über die Dateiextension das Grafikformat erkennen. Beim Stream als Stream müsste hier noch der Klassenname der entsprechenden Grafikkomponente am Anfangen stehen. Einfach mal ein PNG mit der IDE zuweisen und dann die DFM anschauen. Dort steht etwas in der Art: "TPNGImage" vor den eigentlichen PNG-Stream.

UPDATE: Funktioniert perfekt! Hatte damals vergessen, die Unit "PNGImage" einzubinden!! Danke!

Ich habe sicher nicht genug Erfahrung, jedenfalls verstehe ich nicht, wie Dein endgültiger Ladecode nun aussieht:roll:. Kannst Du ihn vielleicht einmal posten?
Speicherst Du PNG auch im Blobfeld und ist der Code, wenn ja, "äquivalent"?

Liebe Grüße,

David

joachimd 3. Sep 2020 08:31

AW: PNG-Bild aus BLOB-Feld in Image laden
 
Delphi-Quellcode:
var png: TPngImage;

...
  png := TPngImage.Create;
  png.LoadFromStream(BlobStream);
  Picture.Graphic.Assign(png);
...

himitsu 3. Sep 2020 09:48

AW: PNG-Bild aus BLOB-Feld in Image laden
 
Alte Delphis schauten immer nur auf die Dateiendung, also nur im Picture.LoadFromFile,
aber seit einer Weile ist im Picture.LoadFromStream ein Code drin, der auf die MagicBytes (FileHeader) guckt.

Drum geht es jetzt auch direkt mit
Delphi-Quellcode:
Image.Picture.LoadFromStream(BlobStream);
,
ohne dass man vorher selber im Image.Picture.Graphic den "richtigen" Typ bereitstellen muss.

Laaeris 9. Sep 2020 13:35

AW: PNG-Bild aus BLOB-Feld in Image laden
 
Liste der Anhänge anzeigen (Anzahl: 2)
...erstmal supervielen Dank für die fixen Antworten. Ich vermute das Laden funktioniert nun, aber ich bekomme einen CRC-Fehler beim Laden, also vermute ich ich mache das Speichern komplett falsch. Ich habe dazu keinen Codeschnipsel gefunden, aber vielleicht drückt mal jemand meine Nase (ruhig doll drücken) auf einen Thread mit einem einfachen Code?

Laden:
Delphi-Quellcode:
var
  PNG_Bild      : TPNGImage;
  BildLadenQuery : TMyQuery;
  BlobStream    : TStream;
begin (*of Button_WappenbildvonDBinImageClick*)
  PNG_Bild:=TPNGImage.Create;
  BildLadenQuery:=TMyQuery.Create(BBM_Datamodule);
  try
    BildLadenQuery.Connection:=BBM_Datamodule.BMMConn;
    BildLadenQuery.SQL.Text := 'Select Wappenbild from BBM_Verein where idVerein=:ID';
    BildLadenQuery.Params[0].Value := Aktiv_Verein_ID;
    BildLadenQuery.ExecSQL;

    BlobStream := BildLadenQuery.CreateBlobStream(BildLadenQuery.FieldByName('Wappenbild'),bmRead);
    PNG_Bild.LoadFromStream(BlobStream);
    Image_Wappen1.Picture.Assign(PNG_Bild);
  finally
    PNG_Bild.Free;
    BildLadenQuery.Free;
  end; (*of finally*)
Speichern:
Delphi-Quellcode:
var
  PictureFile      : TFileName;
  PNG_Bild         : TPNGImage;
  BildSpeicherQuery : TMyQuery;
  BlobStream       : TStream;
begin
  PNG_Bild:=TPNGImage.Create;
  BildSpeicherQuery:=TMyQuery.Create(BBM_Datamodule);
  try
    OpenDialog_NamenHauptform.Execute;
    FileExists(OpenDialog_NamenHauptform.FileName);
    PNG_Bild.LoadFromFile(OpenDialog_NamenHauptform.FileName);

    BildSpeicherQuery.Connection:=BBM_Datamodule.BMMConn;
    BildSpeicherQuery.SQL.Text := 'Update BBM_Verein set Wappenbild=:BILD Where idVerein=:ID';
    BildSpeicherQuery.Params[0].Assign(PNG_Bild);
    BildSpeicherQuery.Params[1].Value := Aktiv_Verein_ID;
    //BildSpeicherQuery.Parameters[1].Assign(itPNG);
    BildSpeicherQuery.ExecSQL;

  finally
    PNG_Bild.Free;
    BildSpeicherQuery.Free;
  end; (*of finally*)
EDIT: Habe gerade mit der Workbench das PNG-File direkt in die DB geladen. Ob man das so naiv machen kann weiss ich nicht. Effekt: BLOB-Byteanzeige ist bei 147 KB (das passt), ladbar ist es nicht (CRC-Fehler wie zuvor).

Liebe Grüße,

David

Klaus01 9. Sep 2020 13:43

AW: PNG-Bild aus BLOB-Feld in Image laden
 
.. ist die Blob-Größe Deiner Datenbank auf 64kByte begrenzt?

Grüße
Klaus

KodeZwerg 9. Sep 2020 13:49

AW: PNG-Bild aus BLOB-Feld in Image laden
 
Hier "delphi-load-image-save-as-blob-in-a-sql-database" werden mehrere möglichkeiten angesprochen, vielleicht ist ja auch eine für dich dabei.

Laaeris 13. Sep 2020 12:16

AW: PNG-Bild aus BLOB-Feld in Image laden
 
Zitat:

Zitat von Klaus01 (Beitrag 1473309)
.. ist die Blob-Größe Deiner Datenbank auf 64kByte begrenzt?

Grüße
Klaus

Nein, siehe "Direktladetest", da gibt es keine Begrenzung.

Liebe Grüße,

David

dataspider 13. Sep 2020 12:25

AW: PNG-Bild aus BLOB-Feld in Image laden
 
Ich kenne AbsoluteDatabase und die Komponenten nicht.
Aber du benutzt beil Laden für ein Select ExecSQL.

Das könnte Probleme bereiten.
Ändert sich was, wenn du statt BildLadenQuery.ExecSQL BildLadenQuery.Open verwendest?

[EDIT]
Man kann beim Laden einfach mal den Inhalt des Blobfeldes auf Platte scheiben:
TBlobField(BildLadenQuery.FieldByName('Wappenbild' )).SaveToFile('x.png') und vergleichen...
[/EDIT]


Frank

dataspider 13. Sep 2020 13:17

AW: PNG-Bild aus BLOB-Feld in Image laden
 
Zitat:

Zitat von Laaeris (Beitrag 1473308)

Speichern:
Delphi-Quellcode:
  BildSpeicherQuery.Params[0].Assign(PNG_Bild);

Ich glaube nicht, dass das funktioniert.
Ich würde das in etwa so machen:

Delphi-Quellcode:
procedure BildLaden;
var
  BildSpeicherQuery: TMyQuery;
  ImageStream: TMemoryStream;
begin
  if OpenDialog_NamenHauptform.Execute then
  begin
    ImageStream := TMemoryStream.Create;
    try
      BildSpeicherQuery := TMyQuery.Create(BBM_Datamodule);
      try
        BildSpeicherQuery.Connection := BBM_Datamodule.BMMConn;
        BildSpeicherQuery.SQL.Text := 'Update BBM_Verein set Wappenbild=:BILD Where idVerein=:ID';

        ImageStream.LoadFromFile(OpenDialog_NamenHauptform.FileName);
        ImageStream.Position := 0; // vorsichtshalber
        BildSpeicherQuery.Params[0].SetBlobData(ImageStream.Memory, ImageStream.Size);
        BildSpeicherQuery.Params[1].Value := Aktiv_Verein_ID;
        BildSpeicherQuery.ExecSQL;
      finally
        BildSpeicherQuery.Free;
      end;
    finally
      ImageStream.Free;
    end;
  end;
end;

Laaeris 8. Nov 2020 18:14

AW: PNG-Bild aus BLOB-Feld in Image laden
 
Liste der Anhänge anzeigen (Anzahl: 1)
[QUOTE=dataspider;1473505]
Zitat:

Zitat von Laaeris (Beitrag 1473308)
Ich glaube nicht, dass das funktioniert.
Ich würde das in etwa so machen:
...

Hey Frank,

die Prozedure läuft fehlerfrei durch - topp. Ich kann noch nicht laden (immer noch PNG-CRC Fehler wie oben), aber ich habe in der Datenbank auf das Feld geschaut, es hat die Größe 65535 Byte. Solche Zahlen machen mich dann nervös, und laut MYSQL-Workbench sieht das Bild wie angehängt aus - irgendwie halb. Immerhin erkennt zumindest die DB das ganze als Image.

Was glaubst Du, woran das liegt?

Liebe Grüße,
David

P.S. (nachedit): Bin gerne bereit dass in diesen verrückten Coronazeiten mal 5 Minuten als Websession zu lösen und die Lösung dann hier zu posten. :-)

dataspider 10. Nov 2020 13:17

AW: PNG-Bild aus BLOB-Feld in Image laden
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich hab mal ein Projekt zum Testen hochgeladen.
Da kannst du mit einem ClientDataset etwas experimentieren.

Frank

Delphi.Narium 10. Nov 2020 14:03

AW: PNG-Bild aus BLOB-Feld in Image laden
 
[QUOTE=Laaeris;1476911]
Zitat:

Zitat von dataspider (Beitrag 1473505)
Zitat:

Zitat von Laaeris (Beitrag 1473308)
Ich glaube nicht, dass das funktioniert.
Ich würde das in etwa so machen:
...

Hey Frank,

die Prozedure läuft fehlerfrei durch - topp. Ich kann noch nicht laden (immer noch PNG-CRC Fehler wie oben), aber ich habe in der Datenbank auf das Feld geschaut, es hat die Größe 65535 Byte. Solche Zahlen machen mich dann nervös, und laut MYSQL-Workbench sieht das Bild wie angehängt aus - irgendwie halb. Immerhin erkennt zumindest die DB das ganze als Image.

Was glaubst Du, woran das liegt?

Liebe Grüße,
David

P.S. (nachedit): Bin gerne bereit dass in diesen verrückten Coronazeiten mal 5 Minuten als Websession zu lösen und die Lösung dann hier zu posten. :-)

Kann es sein, dass das Blobfeld schlicht und einfach zu klein für das Bild ist?

65536 ist halt der höchste Wert, den man mit 'nem Word darstellen kann und der Größe eines Blobs bei MySQL entspricht. (https://www.tutorialspoint.com/What-...olumn-in-MySQL)

Wenn man größere Bilder speichern will, sollte man einen entsprechend größeren Blobtyp nehmen.

Laaeris 15. Nov 2020 16:10

AW: PNG-Bild aus BLOB-Feld in Image laden
 
Zitat:

Zitat von Delphi.Narium (Beitrag 1477040)
Kann es sein, dass das Blobfeld schlicht und einfach zu klein für das Bild ist?

65536 ist halt der höchste Wert, den man mit 'nem Word darstellen kann und der Größe eines Blobs bei MySQL entspricht. (https://www.tutorialspoint.com/What-...olumn-in-MySQL)

Wenn man größere Bilder speichern will, sollte man einen entsprechend größeren Blobtyp nehmen.

Und das war der entscheidende Hinweis, alles andere war schon komplett korrekt, also das Laden und Speichern. Aber ich musste das Datenbankfeld von BLOB in der MySQLDatenbank auf MEDIUMBLOB stellen und schon ging es (TINYBLOB Up to 255 bytes; BLOB Up to 64 Kb; MEDIUMBLOB Up to 16 Mb, LONGBLOB Up to 4 Gb).

Speichern also mit:
Delphi-Quellcode:
var
  BildSpeicherQuery : TMyQuery;
  ImageStream      : TMemoryStream;
begin (*TForm_Hauptuebersicht.Button_WappenbildvonDateiinDatenbankClick*)
  if OpenDialog_NamenHauptform.Execute then
  begin (*Opendialog*)
    ImageStream := TMemoryStream.Create;
    try
      BildSpeicherQuery := TMyQuery.Create(BBM_Datamodule);
      try
        BildSpeicherQuery.Connection := BBM_Datamodule.BMMConn;
        BildSpeicherQuery.SQL.Text := 'Update BBM_Verein set Wappenbild=:BILD Where idVerein=:ID';

        ImageStream.LoadFromFile(OpenDialog_NamenHauptform.FileName);
        ImageStream.Position := 0; // vorsichtshalber
        BildSpeicherQuery.Params[0].SetBlobData(ImageStream.Memory, ImageStream.Size);
        BildSpeicherQuery.Params[1].Value := Aktiv_Verein_ID;
        BildSpeicherQuery.ExecSQL;
      finally
        BildSpeicherQuery.Free;
      end; (*of QueryCreate*)
    finally
      ImageStream.Free;
    end; (*of Streamload*)
  end; (*Opendialog*)
end; (*of TForm_Hauptuebersicht.Button_WappenbildvonDateiinDatenbankClick*)
Laden mit:
Delphi-Quellcode:
var
  PNG_Bild      : TPNGImage;
  BildLadenQuery : TMyQuery;
  BlobStream    : TStream;
begin (*of Button_WappenbildvonDBinImageClick*)
  PNG_Bild:=TPNGImage.Create;
  BildLadenQuery:=TMyQuery.Create(BBM_Datamodule);
  try
    BildLadenQuery.Connection:=BBM_Datamodule.BMMConn;
    BildLadenQuery.SQL.Text := 'Select Wappenbild from BBM_Verein where idVerein=:ID';
    BildLadenQuery.Params[0].Value := Aktiv_Verein_ID;
    BildLadenQuery.ExecSQL;

    BlobStream := BildLadenQuery.CreateBlobStream(BildLadenQuery.FieldByName('Wappenbild'),bmRead);
    PNG_Bild.LoadFromStream(BlobStream);
    Image_Wappen1.Picture.Assign(PNG_Bild);
  finally
    PNG_Bild.Free;
    BildLadenQuery.Free;
  end; (*of finally*)
Vielen Dank an Euch und bleibt gesund!


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:31 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz