[gelöst] Bildformat Type erkennen (jpg - png)

Für Probleme bezüglich Grafik, Audio, GL, ACS, ...
Antworten
oleg
Beiträge: 31
Registriert: So 6. Okt 2019, 17:04
OS, Lazarus, FPC: Win10Pro-(Laz 2.2.0 - FPC 3.2.0)-Rasp4(8GB)+MySQL+GITEA 1.20.2 <-> GIT 2.44.0
Wohnort: Leipzig

[gelöst] Bildformat Type erkennen (jpg - png)

Beitrag von oleg »

Hallo, ich bräuchte mal bitte Unterstützung um ein Problem zu lösen.
Ich speichere Bilder für Dokumentationszwecke in einer Datenbank.

Code: Alles auswählen

  ....
  Add.SQL ( ... ) 
    ParamByName('picture').LoadFromFile(OpenDialog.FileName, ftBlob); 
  Execute;
  ....
Ich lade die Bilder aus der Datenbank mit:

Code: Alles auswählen

   SQL ....
         BlobStream := TMemoryStream.Create;
          TBlobField(FieldByName('picture')).SaveToStream(BlobStream);
         BlobStream.Position := 0;
         Image1.Picture.LoadFromStream(BlobStream);
         BlobStream.Free;   

Das Problem: bisher hatte ich nur jpg Bilder gespeichert, jetzt sollen noch png Image Daten dazukommen.
In die Datenbank speichern und auslesen funktioniert fehlerfrei. Wenn ich allerdings die angezeigten Bilder wieder auf die Festplatte des Benutzers speichern möchte, brauche ich dazu die korrekte Dateierweiterung. Diese will ich aber auf keinen Fall mit in die Datenbank in ein extra Feld speichern.

Code: Alles auswählen

 ....
     SaveDialog.DefaultExt:= 'jpg';
     SaveDialog.Filter := 'JPEG (Bild Datei)|*.jpg|PNG (Portable Network Grafik)|*.png';
     SaveDialog.FileName := MyFileName + '.jpg';

 if SaveDialog.Execute then begin
      Image1.Picture.Graphic.SaveToFile(SaveDialog.FileName);  
 ....     
Testweise habe ich es dem Benutzer selbst überlassen, in welchem Format er das angezeigte Bild speichern möchte, Das wirft mir aber beim erneuten Laden des Bildes einen Fehler: "Wrong Image Format" - zumindest wenn ich eine zuvorige png-Datei als jpg speichere.
Wo kann ich abfragen und sicherstellen, unter welchem Dateityp ich das Bild speichern muss.
Zuletzt geändert von oleg am Mo 1. Apr 2024, 09:08, insgesamt 2-mal geändert.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2805
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Bildformat Type erkennen (jpg - png)

Beitrag von m.fuchs »

oleg hat geschrieben: Mo 1. Apr 2024, 08:26 Testweise habe ich es dem Benutzer selbst überlassen, in welchem Format er das angezeigte Bild speichern möchte, Das wirrft mir aber beim erneuten Laden des Bildes einen Fehler: "Wrong Image Format" - zumindest wenn ich eine zuvorige png-Datei als jpg speichere.
Du musst dann auch im richtigen Format speichern, wenn der Benutzer das Format auswählen darf:

Code: Alles auswählen

if SaveDialog1.Execute then begin
  if SaveDialog1.FileName.ToLower.EndsWith('.png') then
    Image1.Picture.PNG.SaveToFile(SaveDialog1.FileName)
  else if SaveDialog1.FileName.ToLower.EndsWith('.jpg') then
    Image1.Picture.Jpeg.SaveToFile(SaveDialog1.FileName);
end;
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

oleg
Beiträge: 31
Registriert: So 6. Okt 2019, 17:04
OS, Lazarus, FPC: Win10Pro-(Laz 2.2.0 - FPC 3.2.0)-Rasp4(8GB)+MySQL+GITEA 1.20.2 <-> GIT 2.44.0
Wohnort: Leipzig

Re: Bildformat Type erkennen (jpg - png)

Beitrag von oleg »

Vielen Dank, das ist tatsächlich die einfachste Lösung.
Direkt probiert, und funktioniert. Da hab ich wohl zu kompliziert gedacht.

Benutzeravatar
theo
Beiträge: 10856
Registriert: Mo 11. Sep 2006, 19:01

Re: Bildformat Type erkennen (jpg - png)

Beitrag von theo »

oleg hat geschrieben: Mo 1. Apr 2024, 09:04 Vielen Dank, das ist tatsächlich die einfachste Lösung.
Direkt probiert, und funktioniert. Da hab ich wohl zu kompliziert gedacht.
Es geht noch einfacher.

Code: Alles auswählen

 Image1.Picture.SaveToFile(SaveDialog1.FileName)
"Picture" wählt selber den Typ anhand der Erweiterung.
Du hast ursprünglich den Umweg über "Graphic" gemacht, da geht das nicht.

wp_xyz
Beiträge: 5129
Registriert: Fr 8. Apr 2011, 09:01

Re: [gelöst] Bildformat Type erkennen (jpg - png)

Beitrag von wp_xyz »

TPicture ist eine Klasse für "Multi-Format"-Bilder, also für alle Bildformate, die in der Anwendung registriert sind. Und wenn du ein Picture.SaveToFile(...) aufrufst, wird das geladene Bild automatisch in das Format konvertiert, das anhand der Dateiendung gefunden wird. Eben ausprobiert. Genauso wie beim Laden: Picture.LoadFromFile() findet automatisch den richtigen Reader für das vorhandene Bildformat.

Dein Fehler im ersten Post ist also nur, dass du Image.Picture.Graphic.SaveToFile aufrufst und damit die Multi-Format-Fähigkeiten von TPicture umgehst. Richtig wäre:

Code: Alles auswählen

 if SaveDialog.Execute then 
    // Image1.Picture.Graphic.SaveToFile(SaveDialog.FileName);       
    Image1.Picture.SaveToFile(SaveDialog.FileName); 
[EDIT]
Ah, theo war 1 Minute schneller...

oleg
Beiträge: 31
Registriert: So 6. Okt 2019, 17:04
OS, Lazarus, FPC: Win10Pro-(Laz 2.2.0 - FPC 3.2.0)-Rasp4(8GB)+MySQL+GITEA 1.20.2 <-> GIT 2.44.0
Wohnort: Leipzig

Re: [gelöst] Bildformat Type erkennen (jpg - png)

Beitrag von oleg »

okay. Das hatte ich so gar nicht auf dem Schirm. Super einfach erklärt, verstanden und daraus gelernt.
Manchmal sieht man die einfachen Dinge auch erst, wenn jemand mit genau einem Finger drauf zeigt.

icho2099
Beiträge: 47
Registriert: Fr 21. Feb 2020, 19:17
OS, Lazarus, FPC: Win10/64
CPU-Target: 64 Bit
Wohnort: Osterholz-Scharmbeck

Re: [gelöst] Bildformat Type erkennen (jpg - png)

Beitrag von icho2099 »

Ich hätte dazu noch eine Frage:
Wenn man nun aber möchte, dass ein in der DB gespeichertes jpg zwingend als jpg und ein png als png
zurück als Datei geschrieben wird, es also nicht dem Anwender überlassen möchte das zu entscheiden,
lässt sich der Typ der Daten dann aus dem Inhalt ermitteln?
Gibt es für die Bilddateien eine Art Kennung oder müsste man sich selber eine Kennung basteln und diese
beim Speichern im Blob vor der Datei selber ablegen und beim Lesen auswerten?

Benutzeravatar
theo
Beiträge: 10856
Registriert: Mo 11. Sep 2006, 19:01

Re: [gelöst] Bildformat Type erkennen (jpg - png)

Beitrag von theo »

icho2099 hat geschrieben: Mo 1. Apr 2024, 13:24 Gibt es für die Bilddateien eine Art Kennung oder müsste man sich selber eine Kennung basteln und diese
beim Speichern im Blob vor der Datei selber ablegen und beim Lesen auswerten?
z.B. so:

Code: Alles auswählen

uses fpImage;

function GetImageType(const AFileName: string): string;
var
  stream: TStream;
  ImData: TIHData;
begin
  Result := '';
  stream := TFileStream.Create(AFileName, fmOpenRead);
  try
    ImData := TFPCustomImage.FindHandlerFromStream(stream);
    if ImData <> nil then
      Result := ImData.TypeName + ' / ' + ImData.Extension;
  finally
    stream.Free;
  end;
end;

....
  Caption := GetImageType('/home/theo/Bilder/komisch.jpg');
  
Man kann nat. auch einen anderen Streamtyp nehmen.

wp_xyz
Beiträge: 5129
Registriert: Fr 8. Apr 2011, 09:01

Re: [gelöst] Bildformat Type erkennen (jpg - png)

Beitrag von wp_xyz »

icho2099 hat geschrieben: Mo 1. Apr 2024, 13:24 Gibt es für die Bilddateien eine Art Kennung oder müsste man sich selber eine Kennung basteln und diese
beim Speichern im Blob vor der Datei selber ablegen und beim Lesen auswerten?
Jedes (Bild-)Format speichert im Header typische Informationen, an denen man den Format-Typ erkennen kann (einfach sind z.B. Bitmap-Dateien, die haben z.B. am Anfang ein 'BM'). TPicture verwendet für die Format-Detektierung den Mechanismus, der in TFPCustomImage, dem Vorfahren aller Pixel-Bilder in der Lazarus/FPC-Welt, eingebaut ist. Letztendlich ist es die Klassen-Methode FindReaderFromStream, die die Reader-Klasse zurückliefert, die die betreffende Datei lesen kann. Bei jpeg wäre das die TFPReaderJPEG-Klasse, die verfügbar ist, sobald die Unit fpReadJPEG in einer uses-Zeile eingefügt ist. FindReaderFromStream prüft alle verfügbaren Reader-Klassen, ob sie am Dateiheader das entsprechende Format erkennen; es werden nur ein paar Bytes gelesen.

Code: Alles auswählen

uses
  FPImage, FPReadJPEG, FPReadPNG;
  
function IsJpeg(AStream: TStream): Boolean;
var
  P: Int64;
begin
  P := AStream.Position;
  Result := TFPCustomImage.FindReaderFromStream(AStream) = TFPReaderJPEG;
  AStream.Position := P;
end;

function IsPNG(AStream: TStream): Boolean;
var
  P: Int64;
begin
  P := AStream.Position;
  Result := TFPCustomImage.FindReaderFromStream(AStream) = FPReaderPNG;
  AStream.Position := P;
end;
Bin nicht sicher, ob die hier zusätzlich verwendete Stream-Repositionierung notwendig ist. Ist auf jeden Fall zur Sicherheit, falls die FindReaderStream-Methode den Stream nicht auf die Start-Position zurückspult.

Antworten