Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi TJpegImage - aus Stream geladene Grafik komprimieren (https://www.delphipraxis.net/112716-tjpegimage-aus-stream-geladene-grafik-komprimieren.html)

Matze 25. Apr 2008 22:27


TJpegImage - aus Stream geladene Grafik komprimieren
 
Hallo,

dieser Source speichert mir den Stream (TMemoryStream) korrekt auf der Festplatte:

Delphi-Quellcode:
JpegImage.LoadFromStream(AStream);
JpegImage.SaveToFile(SavePathName);
Sobald ich das Bild jedoch komprimieren möchte:

Delphi-Quellcode:
JpegImage.LoadFromStream(AStream);
JpegImage.CompressionQuality := 80;
JpegImage.Compress;
JpegImage.SaveToFile(SavePathName);
erhalte ich eine 0 KB große, natürlich kaputte, Jpg-Datei.

Woran liegt das? :?

Grüße, Matze

bitsetter 26. Apr 2008 00:03

Re: TJpegImage - aus Stream geladene Grafik komprimieren
 
Hi,

versuche es mal so:
Delphi-Quellcode:
 
  JpegImage.LoadFromStream(AStream);
  JpegImage.DIBNeeded;
  JpegImage.CompressionQuality := 80;
  JpegImage.Compress;
  JpegImage.SaveToFile(SavePathName);
Noch eine andere Variante:
Delphi-Quellcode:
   
var
   bmp: TBitmap;
begin
  ...
  bmp:= TBitmap.Create;
  ...
  JpegImage.LoadFromStream(AStream);
  bmp.Assign(JpegImage);
  JpegImage.Assign(bmp);
  JpegImage.CompressionQuality := 80;
  JpegImage.Compress;
  JpegImage.SaveToFile(SavePathName);
   ...

Matze 26. Apr 2008 07:30

Re: TJpegImage - aus Stream geladene Grafik komprimieren
 
Hallo bitsetter,

deine erste Variante funktioniert einwandfrei, vielen Dank! :thumb:

Ich würde gerne verstehen, wieso ich DIBNeeded brauche. In der Hilfe steht dazu folgendes, doch daraus werde ich nicht schlau:

OH zu "DIBNeeded":
Setzen Sie DIBNeeded ein, wenn für die JPEG-Grafik eine Bitmap-Darstellung erforderlich ist. Rufen Sie diese Methode zur Optimierung direkt vor dem Zeichnen auf (nicht während des Zeichnens).

Im Stream befindet sich nämlich eine Grafik im JPG-Format.

Grüße, Matze

Lossy eX 26. Apr 2008 08:39

Re: TJpegImage - aus Stream geladene Grafik komprimieren
 
Die Lösung ist ganz einfach. LoadFromStream lädt dein Bild und liest den Header des JPEGs ein. Und erst wenn du es auf ein Bitmap zuweist oder DIBNeeded aufrufst wird das Bild dekodiert. Das LoadFromStream ist innerhalb von ein paar Millisekunden fertig wärend das DIBNeeded durchaus schon etwas länger dauern kann.

Bei deiner ersten Methode LoadFromStream und SaveToStream sollte das JPEG auch unverändert wieder auf die Platte gespeichert werden. Also ohne es neu komprimieren zu müssen, da das eigentlich immer mit einem Qualitätsverlust einher geht.

Matze 26. Apr 2008 08:48

Re: TJpegImage - aus Stream geladene Grafik komprimieren
 
Hallo Lossy eX

Zitat:

Zitat von Lossy eX
Und erst wenn du es auf ein Bitmap zuweist oder DIBNeeded aufrufst wird das Bild dekodiert.

Hm und wenn ich das Bild versuche zu komprimieren ohne DIBNested zu nutzen bzw. ohne es einem Bitmap zuzuweisen, dann erzeugt Compress ein fehlerhaftes, leeres Bild? Das ist aber auch irgendwie komisch. :gruebel:

bitsetter 26. Apr 2008 12:17

Re: TJpegImage - aus Stream geladene Grafik komprimieren
 
Zitat:

Zitat von Matze
Hm und wenn ich das Bild versuche zu komprimieren ohne DIBNested zu nutzen bzw. ohne es einem Bitmap zuzuweisen, dann erzeugt Compress ein fehlerhaftes, leeres Bild? Das ist aber auch irgendwie komisch. :gruebel:

Für die Prozedur Compress wird das Feld FBitmap benötigt, welches mit DIBNested durch Aufruf der Funktion GetBitmap erzeugt wird. Wenn du nur das Bild von einem Stream lädst, dann ist FBitmap = nil.
Dummerweise wird in der Prozedur Compress die Kompression schon "fleißig" vorbereitet und dann erst geprüft ob FBitmap <> nil bzw. die Höhe und Breite > 0 ist. Würde das Feld FBitmap gleich am Anfang der Prozedur abgefragt, so würde auch kein leeres Bild erzeugt werden.

Matze 26. Apr 2008 12:59

Re: TJpegImage - aus Stream geladene Grafik komprimieren
 
Zitat:

Zitat von bitsetter
Würde das Feld FBitmap gleich am Anfang der Prozedur abgefragt, so würde auch kein leeres Bild erzeugt werden.

Ah, da hat also jemand ein wenig rumgepfuscht. :stupid:
Schön wäre es natürlich gewesen, wenn es abgefragt und ggf. DIBNested oder GetBitmap aufgrufen werden würde. Naja, dann muss man eben selbst dran denken, so tragisch ist das ja nicht.

Grüße, Matze

Lossy eX 26. Apr 2008 16:53

Re: TJpegImage - aus Stream geladene Grafik komprimieren
 
Na ja. Nicht unbedingt. Also im Falle von TJPEGImage sicherlich nicht unsinnig. Aber mit JPEGs kann man auch verlustfreie Operationen durchführen. Also Rotieren oder in einem 16 Pixel Raster zuschneiden. Und der Witz dabei ist, dass man das Bild eben nicht neu kodieren muss. Entsprechend sind die Operationen schnell und verändern auch nicht ein einziges Bit der Pixel.

Mit dem TJPEGImage sind diese Operationen leider nicht möglich, da einige wichtige Strukturen nicht zugänglich sind die dafür aber leider unabdingbar sind. Obwohl die technisch dazu auch in der Lage ist. Entsprechend hast du aber schon recht. Eigentlich hätten sie es auch automatisiert aufrufen können. ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:42 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