AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi JPEG CompressionQuality ermitteln

JPEG CompressionQuality ermitteln

Ein Thema von e-gon · begonnen am 26. Nov 2008 · letzter Beitrag vom 26. Okt 2017
Antwort Antwort
Seite 1 von 3  1 23   
e-gon

Registriert seit: 7. Jul 2003
Ort: Stuttgart
156 Beiträge
 
Delphi 6 Enterprise
 
#1

JPEG CompressionQuality ermitteln

  Alt 26. Nov 2008, 20:23
Hallo,

kennt jemand eine Möglichkeit aus einer JPEG-Grafik die Komprimierungsrate zu ermitteln?

Quality := JPEG.CompressionQuality 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.
Aber vielleicht kennt jemand eine andere Möglichkeit die Komprimierung auszulesen?

Danke für Eure Antwort!

e-gon
  Mit Zitat antworten Zitat
e-gon

Registriert seit: 7. Jul 2003
Ort: Stuttgart
156 Beiträge
 
Delphi 6 Enterprise
 
#2

Re: JPEG CompressionQuality ermitteln

  Alt 26. Nov 2008, 21:05
Sorry, hat sich erledigt!
Ich habe vergessen JPEG zu initialisieren... http://www.delphipraxis.net/posting.php?mode=iframe
ouch!
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#3

AW: Re: JPEG CompressionQuality ermitteln

  Alt 16. Okt 2017, 15:42
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.

Ich habe vergessen JPEG zu initialisieren... http://www.delphipraxis.net/posting.php?mode=iframe
a) Wie geht dieses "initialisieren"? Ich würde auch gern die richtige CompressionQuality in Erfahrung bringen.
b) Der Link funktioniert leider nicht (mehr?), so dass ich das nicht nachvollziehen kann.
Alex Winzer
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.059 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: JPEG CompressionQuality ermitteln

  Alt 17. Okt 2017, 08:17
Hast du eine TJPEGImage-Instanz vorzuliegen?
Dann kannst du doch das über die Property auslesen:
http://docwiki.embarcadero.com/Libra...ressionQuality
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.059 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: JPEG CompressionQuality ermitteln

  Alt 17. Okt 2017, 08:39
Ach guck, das ist ja immer 90?! Das wird anscheinend wirklich gar nicht ausgelesen.
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#6

AW: JPEG CompressionQuality ermitteln

  Alt 17. Okt 2017, 09:03
Ach guck, das ist ja immer 90?! Das wird anscheinend wirklich gar nicht ausgelesen.
Ich wollte mir gerade die Mühe machen, mal ein paar Bilder mit unterschiedlichen Raten zu packen und Dich die CompressionQuality auslesen zu lassen
Das wird nicht ausgelesen, sondern beim Erstellen der Klasse in Create mittels FQuality := JPEGDefaults.CompressionQuality; gesetzt. Das wiederum ist eben 90. Wenn man mit der Suche nach FQuality forscht, stellt man schnell fest, dass diese nur gelesen wird.
Alex Winzer
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.059 Beiträge
 
Delphi 10.4 Sydney
 
#7

AW: JPEG CompressionQuality ermitteln

  Alt 17. Okt 2017, 12:14
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;

Geändert von TiGü (17. Okt 2017 um 12:17 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.059 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: JPEG CompressionQuality ermitteln

  Alt 17. Okt 2017, 12:44
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;
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#9

AW: JPEG CompressionQuality ermitteln

  Alt 25. Okt 2017, 09:15
Ich habe das - etwas unorthodox - für mich selbst jetzt so gelöst:
Delphi-Quellcode:
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;
Vermutlich lässt sich das sogar noch optimieren. Vielleicht findet über die Zeit jemand eine saubere(re) Lösung.
Alex Winzer
  Mit Zitat antworten Zitat
mensch72

Registriert seit: 6. Feb 2008
838 Beiträge
 
#10

AW: JPEG CompressionQuality ermitteln

  Alt 25. Okt 2017, 09:36
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.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:07 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