Einzelnen Beitrag anzeigen

TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 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