![]() |
JPEG CompressionQuality ermitteln
Hallo,
kennt jemand eine Möglichkeit aus einer JPEG-Grafik die Komprimierungsrate zu ermitteln?
Delphi-Quellcode:
geht leider nicht. Quality ist immer 0. Das liegt wahrscheinlich daran, dass die Komprimierung eines JPEGs nicht direkt in der Datei abgelegt wird sondern nur indirekt in die Huffman-Tabelle steht und die eher bescheidene JPEG-Unit nicht in der Lage ist die Qualität zu ermitteln.
Quality := JPEG.CompressionQuality
Aber vielleicht kennt jemand eine andere Möglichkeit die Komprimierung auszulesen? Danke für Eure Antwort! e-gon |
Re: JPEG CompressionQuality ermitteln
Sorry, hat sich erledigt!
Ich habe vergessen JPEG zu initialisieren... ![]() ouch! |
AW: Re: JPEG CompressionQuality ermitteln
Auch wenn das schon etwas älter ist. Ich wärme es auf, weil ich auch gern die Lösung wüsste und es einer der ersten Funde ist, wenn man in der DP und auch bei google sucht. Es wäre daher toll, wenn dann in genau diesem Beitrag eine/die Lösung stünde.
Zitat:
b) Der Link funktioniert leider nicht (mehr?), so dass ich das nicht nachvollziehen kann. |
AW: JPEG CompressionQuality ermitteln
Hast du eine TJPEGImage-Instanz vorzuliegen?
Dann kannst du doch das über die Property auslesen: ![]() |
AW: JPEG CompressionQuality ermitteln
Ach guck, das ist ja immer 90?! Das wird anscheinend wirklich gar nicht ausgelesen.
|
AW: JPEG CompressionQuality ermitteln
Zitat:
Das wird nicht ausgelesen, sondern beim Erstellen der Klasse in Create mittels
Delphi-Quellcode:
gesetzt. Das wiederum ist eben 90. Wenn man mit der Suche nach FQuality forscht, stellt man schnell fest, dass diese nur gelesen wird. :roll:
FQuality := JPEGDefaults.CompressionQuality;
|
AW: JPEG CompressionQuality ermitteln
Schade, ich dachte man kann es über WIC und die Metadaten auslesen, aber in meiner Beispieldatei (mit Smartphone gemacht und Paint.NET bearbeitet) gibt es kein Compression-Feld.
Programme wie IrfanView geben ja das richtige aus...hm...grübel! Kannst ja mal trotzdem versuchen.
Delphi-Quellcode:
uses
Winapi.Windows, Winapi.Wincodec, Winapi.ActiveX; ... function GetJpegCompression(const AJpegFilename: string): USHORT; var HR: HRESULT; ImagingFactory: IWICImagingFactory; Decoder: IWICBitmapDecoder; Frame: IWICBitmapFrameDecode; MetaDataReader: IWICMetadataQueryReader; MetaDataPathName: PWideChar; Value: PROPVARIANT; IFDReader: IWICMetadataQueryReader; Compression: USHORT; procedure DebugShowAllPropertyNames(const AMetaDataQueryReader: IWICMetadataQueryReader); var iValue: Longint; Enumerator: IEnumString; MetaDataPathName: PWideChar; begin // Spaßeshalber alle Metadaten auflisten iValue := 0; HR := AMetaDataQueryReader.GetEnumerator(Enumerator); if Succeeded(HR) then begin while Enumerator.Next(1, MetaDataPathName, @iValue) = S_OK do begin OutputDebugString(MetaDataPathName); end; end; end; begin Result := 0; HR := CoCreateInstance(CLSID_WICImagingFactory, nil, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IUnknown, ImagingFactory); if Succeeded(HR) then begin HR := ImagingFactory.CreateDecoderFromFilename(PChar(AJpegFilename), TGUID.Empty, GENERIC_READ, WICDecodeMetadataCacheOnDemand, Decoder); if Succeeded(HR) then begin HR := Decoder.GetFrame(0, Frame); if Succeeded(HR) then begin HR := Frame.GetMetadataQueryReader(MetaDataReader); if Succeeded(HR) then begin // https://msdn.microsoft.com/en-us/library/windows/desktop/ee719904(v=vs.85).aspx#_jpeg_metada MetaDataPathName := '/app1/ifd'; PropVariantInit(Value); HR := MetaDataReader.GetMetadataByName(MetaDataPathName, Value); if Succeeded(HR) then begin if Value.vt = VT_UNKNOWN then begin HR := IUnknown(Value.ppunkVal).QueryInterface(IID_IWICMetadataQueryReader, IFDReader); PropVariantClear(Value); if Succeeded(HR) then begin DebugShowAllPropertyNames(IFDReader); PropVariantInit(Value); // das sollte eigentlich Compression sein -> bei mir leider nicht vorhanden MetaDataPathName := '/{ushort=259}'; HR := IFDReader.GetMetadataByName(MetaDataPathName, Value); if Succeeded(HR) then begin if Value.vt = VT_UI2 then begin HR := PropVariantToUInt16(Value, Compression); if Succeeded(HR) then begin Result := Compression; end; end; end; end; end; end; end; end; end; end; end; |
AW: JPEG CompressionQuality ermitteln
Schade, mit GDI+ komm ich auch nicht ran.
Delphi-Quellcode:
function GdipCheck(const AResult: GPSTATUS): Boolean;
begin Result := AResult = GPSTATUS.Ok; end; function GdiPlusGetJpegCompression(const AJpegFilename: string): USHORT; var token: ULONG; Input: TGdiplusStartupInput; Output: TGdiplusStartupOutput; status: GPSTATUS; image: GpImage; size: UINT; propertyItemID:PROPID; propertyItem: TPropertyItem; begin Result := 0; FillChar(Input, SizeOf(Input), 0); Input.GdiplusVersion := 1; FillChar(Output, SizeOf(Output), 0); GdiplusStartup(token, @Input, @Output); try status := GdipCreateBitmapFromFile(PChar(AJpegFilename), image); if GdipCheck(status) then begin propertyItemID := PropertyTagJPEGQuality; // PropertyTagCompression status := GdipGetPropertyItemSize(image, propertyItemID, size); if GdipCheck(status) then begin ZeroMemory(@propertyItem, SizeOf(propertyItem)); status := GdipGetPropertyItem(nil, propertyItemID, size, @propertyItem); if GdipCheck(status) then begin Result := PWORD(propertyItem.value)^; end; end; end; finally GdiplusShutdown(token); end; end; |
AW: JPEG CompressionQuality ermitteln
Ich habe das - etwas unorthodox - für mich selbst jetzt so gelöst:
Delphi-Quellcode:
Vermutlich lässt sich das sogar noch optimieren. Vielleicht findet über die Zeit jemand eine saubere(re) Lösung.
Function CalcCompressionQuality(Const JPG: TJPEGImage;
Const MustFit: Boolean = False): TJPEGQualityRange; Var aMS : TMemoryStream; aBMP : TBitmap; aJPG : TJPEGImage; aSize : Int64; lQ, hQ : Integer; Piv, oldPiv : Integer; // Ausgangswert = 0 Begin aMS:= TMemoryStream.Create; // TMemoryStream erzeugen aBMP:= TBitmap.Create; // TBitmap erzeugen aJPG:= TJPEGImage.Create; // TJPEGImage erzeugen Try JPG.SaveToStream(aMS); // in Stream ablegen aSize:= aMS.Size; // Originalgröße ermitteln aBMP.Assign(JPG); // Bild ins TBitmap kopieren lQ:= Low(Result); // untere Grenze hQ:= High(Result); // obere Grenze Piv:= (hQ - lQ) Div 2; // in der Mitte anfangen Repeat aMS.Clear; // Stream leeren aJPG.CompressionQuality:= Piv; // Kompressionsrate setzen aJPG.Assign(aBMP); // Bitmap kopieren/komprimieren aJPG.SaveToStream(aMS); // JPG in Stream kopieren oldPiv:= Piv; // altes Pivot-Element merken If (aMS.Size > aSize) Then // Ergebnis ist zu groß Begin hQ:= Piv; // obere Grenze = aktueller Wert Piv:= Piv - ((hQ - lQ) Div 2); // neuen Wert berechnen End Else Begin // Ergebnis kleiner oder gleich lQ:= Piv; // untere Grenze = aktueller Wert Piv:= Piv + ((hQ - lQ) Div 2); // neuen Wert berechnen End; Until (Piv = oldPiv); // noch näher geht es nicht If (MustFit) And // auf keinen Fall größer !!! (aMS.Size > aSize) Then // immer noch zu groß Result:= Pred(Piv) // => eine Nummer kleiner Else Result:= Piv; // aMS.Size = aSize => exakten Wert übergeben Finally aMS.Free; // TMemoryStream freigeben aBMP.Free; // TBitmap freigeben aJPG.Free; // TJPEGImage freigeben End; End; |
AW: JPEG CompressionQuality ermitteln
Die Kompressionsrate eines JPG errechnet sich doch mathematisch rückwärts ganz simpel aus der JPG-Dateigröße im Verhältnis zum Speicherbedarf des RGB-PixelArrays:
x = (JPGfileSize*100%) / (Width*Height*3) Wer es auf die meist 32Bit(ARGB) Speichergröße von Bitmaps im PC beziehen will rechnet eben mit "x4" x = (JPGfileSize*100%) / (Width*Height*4) JPGheader und JPGmetadaten sind genau wie "BitmapInfoHeader" hier zu vernachlässigen, weil es rückwärts eh stets nur eine Näherung ist. |
AW: JPEG CompressionQuality ermitteln
CompressionQuality <> Kompressionsrate
|
AW: JPEG CompressionQuality ermitteln
Zitat:
Und ist Zitat:
Delphi-Quellcode:
?
CompressionQuality
Zitat:
Zitat:
Delphi-Quellcode:
und damit die Dateigröße?
1
|
AW: JPEG CompressionQuality ermitteln
Zitat:
Mich interessiert nicht die Kompressionsrate der Datei(größe). |
AW: JPEG CompressionQuality ermitteln
würdest du mir bitte deine "CompressionQuality" definieren?
Für mich bestimmt sich nunmal die "CompressionQuality" aus dem relativen Größenerhältnis von max. unkomprimierten Bilddaten und der Größe der komprimierten Bilddaten. Wenn du Richtung Bildqualität bzw. Informationsverlust denkst, dann entscheidet da mehr die Kompressionssoftware und deren Algos&Vorfilter. Ein AdobePhotoshop kann Bilder ohne groß auffälligen & fürs menschliche Auge sichtbaren Qualitätsverlust viel "kleiner" packen. Wenn man ein 1GB Bild mit Delphi und Photoshop mit welchem "Kompressions-Wert" auch immer auf eine vergleichbare Dateigröße von 100MB also "1:10" komprimiert, wird warum auch immer die optische/gefühlte Bildqualität im durch Photoshop erzeugtem Bild höher sein... das rückwärts ohne org. Daten aus der Jpeg Datei zu bestimmen, also die bessere "CompressionQuality" im Sinne resultierend besserer Bildqualität zu ermitteln ist aus meiner Sicht nicht möglich. Nach meiner Methode des "relativen Größenvergleichs" wären beide Dateien gleich gut komprimiert und hätten für meine Software die selbe "CompressionQuality". |
AW: JPEG CompressionQuality ermitteln
CompressionQuality besagt, wie verlustbehaftet die Komprimierung ist. Bei 100% wird ohne Verlust komprimiert, bei kleineren Werten steigt der Verlust, d. h. die Bildqualität nimmt ab oder anders ausgedrückt: Das dekomprimierte Bild stimmt nicht mit dem Bild vor der Komprimierung überein. (Auch wenn die Bilder für das menschliche Auge gleich aussehen.)
![]() |
AW: JPEG CompressionQuality ermitteln
Zitat:
CompressionQuality ist nicht irgend ein Wert, sondern gemeint ist der von
Delphi-Quellcode:
, was dem geneigten Leser aber klar wird. Und da ich das Thema nicht erstellt habe, kann ich dessen Titel nicht beeinflussen.
Vcl.Imaging.jpeg.TJPEGImage.CompressionQuality
[EDIT]Bedeutet 100 wirklich, dass es ohne Verlust komprimiert wird? Ich denke, dass zumindest die JPEG-Version von Delphi immer verlustbehaftet ist. Ich probiere das zur Not auch aus.[/EDIT] Zitat:
Ab jetzt befasse ich mich damit, wie man das ganze noch mit GDI+ realisiert. Damit tue ich mich im Moment noch schwer, weil es im Internet nur extrem wenige Quellen zu Delphi und GDI+ gibt... |
AW: JPEG CompressionQuality ermitteln
Zitat:
Mithilfe der ersten Unit wird ein hilfreicher Wrapper (Klassen basiert) über die flachen GDI+-Funktionen gestülpt. Alle Methoden sind protected oder public, so dass man auch selber den Wrapper erweitern und mit hilfreichen Ableitungen arbeiten kann. Er ähnelt der Klassen basierten C++ API und von daher ist die MSDN ein guter Anlaufpunkt für Informationen. Auch als Delpi-Programmierer sollte man andere native Sprachen zumindest lesen können. Der C++-Beispielcode ist in der Regel gut zu verstehen. ![]() |
AW: JPEG CompressionQuality ermitteln
So wie mir bekannt ist kannst du diese nur zuweisen..
Ich habe meinen eigenen Wrapper..
Delphi-Quellcode:
QualityModeInvalid = -1;
QualityModeDefault = 0; QualityModeLow = 1; // Best performance QualityModeHigh = 2; // Best rendering Quality
Delphi-Quellcode:
so könnte das aussehen.
function GDIP_SaveImageToFile(filename: WideString; image: Cardinal; Quality: Integer
): GPSTATUS; stdcall; var rSplit: TSplitStrArray; encoderCLSID: TGUID; ext: string; IntI: Integer; format: string; EncoderParameters: PEncoderParameters; SaveQuality: Integer; listSize: UINT; begin ext := ExtractFileExt(filename); rSplit := Split(IMAGETYPES, ';'); for IntI := 0 to High(rSplit) do begin if rSplit[IntI] = ext then begin case IntI of 0: format := 'image/jpeg'; 1: format := 'image/png'; 2: format := 'image/bmp'; 3: format := 'image/gif'; 4: format := 'image/tiff'; 5: format := 'image/x-icon'; 6: format := 'image/x-emf'; 7: format := 'image/x-wmf'; else begin result := UnknownImageFormat; exit; end; end; break; end; end; SkinEngine.GetEncoderClsid(format, encoderCLSID); GdipGetEncoderParameterListSize(Image, @encoderCLSID, listSize); getmem(EncoderParameters, listSize); GdipGetEncoderParameterList(Image, @encoderClsid, listSize, EncoderParameters); SaveQuality := max(min(Quality, 100), 0); if (SaveQuality = 0) then SaveQuality := 100; EncoderParameters.Count := 1; EncoderParameters.Parameter[0].Guid := EncoderQuality; EncoderParameters.Parameter[0].NumberOfValues := 1; EncoderParameters.Parameter[0].Type_ := 4; EncoderParameters.Parameter[0].Value := @SaveQuality; Result := GdipSaveImageToFile(image, PWideChar(filename), @encoderCLSID, EncoderParameters); freemem(EncoderParameters, listSize); end; gruss |
AW: JPEG CompressionQuality ermitteln
Zitat:
Zitat:
![]() Ich stufe mich selbst aber als Laien - also nix Delpi-Programmierer - ein und versuche trotzdem halbwegs zu verstehen, was ich tue. Und da stolpere ich über so Sachen wie ISTREAM & Co. die scheinbar so gar nichts mit dem mir bekannnten
Delphi-Quellcode:
gemeinsam haben. Und ich sehe auch am übersetzten Code von EWeiss, dass es offenbar doch nicht einfacher geht, wie ich es erhofft hatte. Mit GDI+ werden es scheinbar zwangsläufig mehr als die 20 Zeilen...
T(Memory)Stream
P.S. Gibt es eine Funktion, mit der man TStatus in String übersetzen lassen kann? Ich kann das auch selbst. Aber wenn es das gibt, muss ich mir nicht die Arbeit machen. |
AW: JPEG CompressionQuality ermitteln
Zitat:
Beim Result musste sehen wie du es brauchst. Komprimierte Größe im Verhältnis zu unkomprimierte Größe oder andersrum. Ggf. hauste da noch ne * 100 dazu. Wie du magst.
Delphi-Quellcode:
function GetCompressRatio(const AJpegFilename: string): Double;
var Status: Winapi.GDIPAPI.TStatus; Image: Winapi.GDIPOBJ.TGPImage; OriginalStream, CompressStream: System.Classes.TMemoryStream; OriginalStreamAdapter, CompressStreamAdapter: Winapi.ActiveX.IStream; ImageFormat, EncoderCLSID: TGUID; EncoderParams: Winapi.GDIPAPI.TEncoderParameters; SaveQuality: Vcl.Imaging.jpeg.TJPEGQualityRange; // Integer geht natürlich auch! begin Result := 0; OriginalStream := TMemoryStream.Create; CompressStream := TMemoryStream.Create; // mit soOwned räumt der TStreamAdapter den TMemoryStream auf OriginalStreamAdapter := TStreamAdapter.Create(OriginalStream, soOwned); CompressStreamAdapter := TStreamAdapter.Create(CompressStream, soOwned); Image := Winapi.GDIPOBJ.TGPImage.Create(AJpegFilename); try if Assigned(Image) and (Image.GetWidth > 0) and (Image.GetHeight > 0) then begin Status := Image.GetRawFormat(ImageFormat); if (Status = TStatus.Ok) and (ImageFormat = ImageFormatJPEG) then begin if Winapi.GDIPUTIL.GetEncoderClsid('image/jpeg', EncoderCLSID) > -1 then begin // Bild OHNE Komprimierung im Stream speichern Status := Image.Save(OriginalStreamAdapter, EncoderCLSID); OutputDebugString(PWideChar(Winapi.GDIPUTIL.GetStatus(Status))); SaveQuality := 50; // oder was du magst für die Kompressionsrate FillChar(EncoderParams, SizeOf(EncoderParams), 0); EncoderParams.Count := 1; EncoderParams.Parameter[0].Guid := EncoderQuality; EncoderParams.Parameter[0].NumberOfValues := 1; EncoderParams.Parameter[0].Type_ := EncoderParameterValueTypeLong; EncoderParams.Parameter[0].Value := @SaveQuality; // Bild MIT Komprimierung im Stream speichern Status := Image.Save(CompressStreamAdapter, EncoderCLSID, @EncoderParams); OutputDebugString(PWideChar(Winapi.GDIPUTIL.GetStatus(Status))); Result := CompressStream.Size / OriginalStream.Size; end; end else OutputDebugString(PWideChar(Winapi.GDIPUTIL.GetStatus(Status))); end; finally Image.Free; end; end; |
AW: JPEG CompressionQuality ermitteln
Wenn du mit TStatus GPStatus meinst jo..
Delphi-Quellcode:
Status =(
Ok, GenericError, InvalidParameter, OutOfMemory, ObjectBusy, InsufficientBuffer, NotImplemented, Win32Error, WrongState, Aborted, FileNotFound, ValueOverflow, AccessDenied, UnknownImageFormat, FontFamilyNotFound, FontStyleNotFound, NotTrueTypeFont, UnsupportedGdiplusVersion, GdiplusNotInitialized, PropertyNotFound, PropertyNotSupported ); TStatus = Status;
Delphi-Quellcode:
gruss
cStatus : Array[TStatus] of String =(
'Ok', 'GenericError', 'InvalidParameter', 'OutOfMemory', 'ObjectBusy', 'InsufficientBuffer', 'NotImplemented', 'Win32Error', 'WrongState', 'Aborted', 'FileNotFound', 'ValueOverflow', 'AccessDenied', 'UnknownImageFormat', 'FontFamilyNotFound', 'FontStyleNotFound', 'NotTrueTypeFont', 'UnsupportedGdiplusVersion', 'GdiplusNotInitialized', 'PropertyNotFound', 'PropertyNotSupported' ); |
AW: JPEG CompressionQuality ermitteln
Danke Euch allen für die tatkräftige Hilfe!
Zitat:
Delphi-Quellcode:
,
Winapi.GDIPAPI
Delphi-Quellcode:
noch
Winapi.GDIPOBJ
Delphi-Quellcode:
?
Winapi.GDIPUTIL
Ich habe das jetzt mal umgestellt und es klappt (jedenfalls bei mir) tatsächlich:
Delphi-Quellcode:
Eine Frage habe ich trotzdem noch: Wohin verschwindet
Function CalcCompressionQuality(Const Image: GPIMAGE;
Const MustFit: Boolean = False): TJPEGQualityRange; Var aMS : TMemoryStream; aFormat, aEncoder : TGUID; aSA : Winapi.ActiveX.IStream; aSize : Int64; lQ, hQ, Piv, oldPiv : Integer; aEncParams : Winapi.GDIPAPI.TEncoderParameters; Begin Result:= 100; // im Zeifel: beste Qualität! If (GdipGetImageRawFormat(Image, @aFormat) = Status.Ok) And (aFormat = ImageFormatJPEG) And // nur bei JPEG ausführen (GetEncoderClsid('image/jpeg', aEncoder) > -1) Then Begin aMS:= TMemoryStream.Create; // TMemoryStream erzeugen aSA:= TStreamAdapter.Create(aMS, soOwned); // aMS wird selbst aufgeräumt If (GdipSaveImageToStream(Image, aSA, @aEncoder, nil) = Status.Ok) Then Begin aSize:= aMS.Size; // Originalgröße ermitteln lQ:= Low( Result); // untere Grenze hQ:= High(Result); // obere Grenze Piv:= (hQ - lQ) Div 2; // in der Mitte anfangen Repeat aMS.Clear; // Stream leeren FillChar(aEncParams, SizeOf(aEncParams), 0); aEncParams.Count:= 1; With aEncParams.Parameter[0] Do Begin Guid:= EncoderQuality; // um diese Einstellung geht es NumberOfValues:= 1; Type_:= EncoderParameterValueTypeLong; Value:= @Piv // CompressionQuality setzen End; oldPiv:= Piv; // altes Pivot-Element merken If (GdipSaveImageToStream(Image, aSA, @aEncoder, @aEncParams) = Status.Ok) Then Begin If (aMS.Size > aSize) Then // Ergebnis ist zu groß Begin hQ:= Piv; // obere Grenze = aktueller Wert Piv:= Piv - ((hQ - lQ) Div 2); // neuen Wert berechnen End Else Begin // Ergebnis kleiner oder gleich lQ:= Piv; // untere Grenze = aktueller Wert Piv:= Piv + ((hQ - lQ) Div 2); // neuen Wert berechnen End; End Else Break; // bei Fehlern abbrechen Until (Piv = oldPiv); // noch näher geht es nicht aSA:= nil; // sicherheitshalber (http://www.delphipraxis.net/1384246-post23.html) If (MustFit) And // auf keinen Fall größer !!! (aMS.Size > aSize) Then // immer noch zu groß Result:= Pred(Piv) // => eine Nummer kleiner Else Result:= Piv; // aMS.Size = aSize => exakten Wert übergeben End; End; End;
Delphi-Quellcode:
?
Winapi.ActiveX.IStream
Dieser Stream kümmert sich um den ihm zugewiesenen
Delphi-Quellcode:
, so dass ich den nicht freigeben darf/muss. Aber trotz fehlender Freigabe von
TMemoryStream
Delphi-Quellcode:
bringt mir mein Programm bei
Winapi.ActiveX.IStream
Delphi-Quellcode:
am Ende keine Meldung.
ReportMemoryLeaksOnShutdown:= True;
Das wäre mir wichtig, weil mein Programm genauso lang läuft wieder Rechner und damit am Tag im Maximum mehrere hundert Bilder verarbeiten muss. Dass es am Ende des Programms automatisch aufgeräumt wird, reicht mir also leider nicht, wenn mir zwischendurch die Puste/der Speicher aus geht.
Delphi-Quellcode:
ruft auch nur
Winapi.GDIPOBJ.TGPImage.Free
Delphi-Quellcode:
auf...
GdipDisposeImage();
|
AW: JPEG CompressionQuality ermitteln
Zitat:
Der Aufruf ist einfach. bsp.
Delphi-Quellcode:
var
Result: GPStatus; .... Result := GdipSaveImageToFile(img, FullName, @encoderCLSID, nil); lblStatus.Caption := 'Status = ' + (cStatus[Result]); Zitat:
Ein IStream := nil sollte ausreichen. GdipDisposeImage gibt den Speicher frei vom geladenen GDI+ Image. Auch das ist vollkommen ausreichend. gruss |
AW: JPEG CompressionQuality ermitteln
Zitat:
Zitat:
:shock: Öh...das ist jetzt schon bissel fremdschämen mit euch. :oops: In meinen Beispielcode habe ich dreimal folgende Zeile verwendet:
Delphi-Quellcode:
OutputDebugString(PWideChar(Winapi.GDIPUTIL.GetStatus(Status)));
Ich will das Wichtigste nochmal herausstellen:
Delphi-Quellcode:
Winapi.GDIPUTIL.GetStatus(Status);
Ich will ja jetzt nicht kritisch gucken, aber die Unit Winapi.GDIPUTIL ist gerade mal knapp 389 Zeilen lang. Das hättest du durch leichtes durch scrollen aber auch selber finden können. |
AW: JPEG CompressionQuality ermitteln
Zitat:
Auch einfach mal in TStreamAdapter.Destroy einen Haltepunkt setzen und den Call Stack nachvollziehen. |
AW: JPEG CompressionQuality ermitteln
Zitat:
Und selbst ohne diese: JPEG betreibt sog. 4:2:2 Color Subsampling. Das heisst, das Bild wird zunächst von RGB zu YCrCb umgewandelt, und die C-Komponenten nachher in Breite und Höhe halbiert. (Das geht ganz gut, da das Menschliche Auge Farbunterschiede eh nicht so gut auflösen kann wie Helligkeitsunterschiede.) Der Standard lässt prinzipiell auch anderes Subsampling zu (4:4:4, 4:1:1, etc.), aber als Standardwert wird praktisch überall 4:2:2 verwendet. Zumindest dort, wo man es nicht genau wüsste dass man etwas anderes nutzt. D.h. Rundungsfehler treten eh schon bei der Farbraumumwandlung auf, und dann eben noch "Fehler" durch das vierteln der Farbinformation. Noch bevor überhaupt transformiert wird oder der "CompressionQuality"-Wert in den Ablauf einfließt. (Ja, ich habe schon mal einen JPEG Kompressor komplett zu Fuß gebaut.) |
AW: JPEG CompressionQuality ermitteln
Zitat:
gruss |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:41 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz