AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi JPG-Datei drehen und speichern -> Verlust der Exif-Daten

JPG-Datei drehen und speichern -> Verlust der Exif-Daten

Ein Thema von axelf98 · begonnen am 3. Sep 2005 · letzter Beitrag vom 22. Aug 2021
Antwort Antwort
Seite 8 von 8   « Erste     678
Willie1

Registriert seit: 28. Mai 2008
618 Beiträge
 
Delphi 10.1 Berlin Starter
 
#71

AW: JPG-Datei drehen und speichern -> Verlust der Exif-Daten

  Alt 20. Jul 2020, 17:08
Hallo Bennik,
den Umstieg auf die neue GDI+ Bibliothek kann ich mit meinen Augen nicht leisten. Die Variablennamen sind alle anders, dass schaffe ich nicht! Ich muss beim alten GDI+ bleiben.

PGPPropertyItem erkennt mein Compiler nicht, obwohl ich GDIPlus und GDPlusHeelpers eingebunden habe.

Dein Programm müsste ich wieder zurück anpassen.
Gut hören kann ich schlecht, schlecht sehen kann ich gut - Ersteres stimmt nicht, das zweite schon.

Geändert von Willie1 (20. Jul 2020 um 17:26 Uhr)
  Mit Zitat antworten Zitat
Benmik

Registriert seit: 11. Apr 2009
532 Beiträge
 
Delphi 11 Alexandria
 
#72

AW: JPG-Datei drehen und speichern -> Verlust der Exif-Daten

  Alt 20. Jul 2020, 20:59
Das tut mir leid, dass du so Probleme mit deinen Augen hast. Du musst ja auch keineswegs umsteigen. Die GDI+-Bibliothek bleibt ja gleich, es ist nur der Delphi-Wrapper, der bei Mitov etwas moderner und bequemer ist.

PGPPropertyItem erkennt mein Compiler nicht...
Das liegt an der fehlenden Einbindung von IGDIPlus.pas von Mitov. Den Link hatte ich ja angegeben.

Kennst du das Tastenkürzel STRG + SHIFT + E für das Refaktorisieren von Bezeichnern aller Art? Damit erleichtert man sich die Arbeit. Aber wie gesagt, wenn du bei der "alten" Art bleibst, verlierst du nichts an Funktionalität oder Geschwindigkeit.
  Mit Zitat antworten Zitat
Willie1

Registriert seit: 28. Mai 2008
618 Beiträge
 
Delphi 10.1 Berlin Starter
 
#73

AW: JPG-Datei drehen und speichern -> Verlust der Exif-Daten

  Alt 21. Jul 2020, 16:39
Ich werde mich einarbeiten.
Da ich meine Bilder grundsätzlich nicht drehe und inzwischen fast alle Programme das Drehen nach dem Or.-Tag ausführen, vermisse ich das richtige Drehen nicht.
Ich werde es mit RotateFlip machen. Nur zur Anzeige reicht das.
W.
  Mit Zitat antworten Zitat
Benmik

Registriert seit: 11. Apr 2009
532 Beiträge
 
Delphi 11 Alexandria
 
#74

AW: JPG-Datei drehen und speichern -> Verlust der Exif-Daten

  Alt 31. Jul 2020, 18:36
Ich habe die Prozedur zum Drehen von JPG an zwei Stellen verbessert.

Zum einen ist es das Auslesen des EXIF-Datums, das jetzt ordentlich geschieht.

Zum anderen habe ich bemerkt, dass der Code bei 64-Bit-Apps nicht funktionierte. Das war mir zunächst ein Rätsel, da es keinerlei Fehlermeldung gab, die DLL ganz offensichtlich korrekt angesteuert und auch die Datei verlustfrei neu gespeichert wurde; nur gedreht wurde sie nicht! Erst als ich auf die Idee kam, bei EncoderTransformValue den Typ von Integer zu NativeInt zu ändern, ging es plötzlich. (Das erinnert mich an Sir Rufo: Kaum macht man's richtig, schon funktioniert's!)
Delphi-Quellcode:
uses ... IGDIPlus;

procedure DreheMitIGDIPlus;
Var i:integer;
  Orientation: UInt32;
  EXIFDatum:TDateTime;
  DatListe:TStringDynArray;
  IGDPImage: IGPImage;
  PPropOItem,PPropDItem: PGPPropertyItem;
  PropBufferSize,DateBufferSize: Cardinal;
  DreheXGrad: TIGPEncoderValue;
  EncoderParams: TIGPEncoderParameters;
  EncoderTransformValue:NativeInt; // NICHT integer, sonst keine Funktion bei 64-Bit-Apps!
  TempDatname:string;
  EncoderCLSID: TGUID;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------
  procedure Initialisiere;
  begin
    PropBufferSize := 0;
    PPropOItem := nil;
    EncoderParams.Count := 1;
    EncoderParams.Parameter[0].Guid := EncoderTransformation;
    EncoderParams.Parameter[0].DataType := EncoderParameterValueTypeLong;
    EncoderParams.Parameter[0].NumberOfValues := 1;
    GetEncoderClsid('image/jpeg', EncoderCLSID);
  end;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------
  function BufferGesetzt:Boolean;
  begin
    If (PropBufferSize > 0) and (DateBufferSize > 0)
      then exit(True);
    PropBufferSize := IGDPImage.GetPropertyItemSize(GPPropertyTagOrientation);
    If PropBufferSize > 0
      then GetMem(PPropOItem, PropBufferSize);
    DateBufferSize := IGDPImage.GetPropertyItemSize(GPPropertyTagDateTime);
    If DateBufferSize > 0
      then GetMem(PPropDItem, DateBufferSize);
    Result := (PropBufferSize > 0) and (DateBufferSize > 0);
  end;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------
  function BestimmeRotation(var DreheXGrad:TIGPEncoderValue):Boolean;
  var Orientation: UInt32;
  begin
    IGDPImage.GetPropertyItem(GPPropertyTagOrientation, PropBufferSize, PPropOItem);
    Orientation := PUInt32(PPropOItem.value)^;
    Case Orientation of
      3: DreheXGrad := EncoderValueTransformRotate180;
      6: DreheXGrad := EncoderValueTransformRotate90;
      8: DreheXGrad := EncoderValueTransformRotate270;
      else DreheXGrad := TIGPEncoderValue(100); // zum Testen "else DreheXGrad := EncoderValueTransformRotate90;" , wenn man keine Hochkant-Bilder hat
    end;
    Result := (DreheXGrad in [EncoderValueTransformRotate90..EncoderValueTransformRotate270]);
  end;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------
  function BestimmeEXIFDatum:TDateTime;
  var i:Cardinal; DateOrig: array of Byte; TxtEXIFDatum:string;
  begin
    IGDPImage.GetPropertyItem(GPPropertyTagDateTime, DateBufferSize, PPropDItem);
    SetLength(DateOrig,DateBufferSize);
    Move(PPropDItem.Value,DateOrig[1],DateBufferSize);
    // DateBufferSize ist immer deutlich größer als die 19 Bytes des Datumeintrags. Die Byteanzahl vor dem Eintrag ist nicht konstant.
    i := 0;
    While i < (DateBufferSize - PPropDItem.Length) do begin
      // Format des Datumseintrags ist JJJJ:MM:TT HH:MM:SS - die 4 Doppelpunkte stehen in normiertem Abstand zueinander
      If (DateOrig[i] = $3A) and (DateOrig[i + 3] = $3A) and (DateOrig[i + 9] = $3A) and (DateOrig[i + 12] = $3A)
        then break;
      Inc(i);
    end;
    TxtEXIFDatum := Copy(TEncoding.ASCII.GetString(DateOrig),i - 3,19);
    Try
      Result :=
        EncodeDate(StrToInt(Copy(TxtEXIFDatum, 1, 4)),StrToInt(Copy(TxtEXIFDatum, 6, 2)),StrToInt(Copy(TxtEXIFDatum, 9, 2))) +
        EncodeTime(StrToInt(Copy(TxtEXIFDatum, 12, 2)),StrToInt(Copy(TxtEXIFDatum, 15, 2)),StrToInt(Copy(TxtEXIFDatum, 18, 2)), 0);
    Except
      Result := 0;
    End;
  end;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------
  function SpeichereJPG:Boolean;
  begin
    Result := False;
    TempDatname := TPath.ChangeExtension(DatListe[i],'$$$');
    If TFile.Exists(TempDatname)
      then exit;
    IGDPImage.Save(WideString(TempDatname),EncoderCLSID,@EncoderParams);
    IGDPImage := nil;
    If TFile.Exists(TempDatname) then begin
      Result := DeleteFile(DatListe[i]);
      If Result
        then Result := RenameFile(TempDatname,DatListe[i])
        else DeleteFile(TempDatname);
    end;
  end;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------
  function SetzeDatumAufEXIF(Datname:string;EXIFDatum:TDateTime):Boolean;
  begin
    Result := True;
    Try
      TFile.SetCreationTime(Datname,EXIFDatum);
      TFile.SetLastWriteTime(Datname,EXIFDatum);
    Except
      Result := False;
    End;
  end;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------
  procedure RäumeAuf;
  begin
    FreeMem(PPropOItem);
    FreeMem(PPropDItem);
    IGDPImage := nil;
  end;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------
begin
  Initialisiere;
  Try
    DatListe := TDirectory.GetFiles(Verz,'*.jpg');
    For i := 0 to High(Datliste) do begin // zum Testen auf "0 to 0" setzen
      IGDPImage := TIGPImage.Create(DatListe[i]);
      If not BufferGesetzt
        then exit;
      EXIFDatum := BestimmeEXIFDatum;
      If BestimmeRotation(DreheXGrad) then begin
        EncoderTransformValue := Ord(DreheXGrad);
        EncoderParams.Parameter[0].Value := @EncoderTransformValue;
        Orientation := 1; // zum Testen z.B. auf 3 setzen, wenn man keine Hochkant-Bilder hat
        PPropOItem.Value := @Orientation;
        IGDPImage.SetPropertyItem(PPropOItem^);
        If not SpeichereJPG
          then exit;
        SetzeDatumAufEXIF(DatListe[i],EXIFDatum);
      end;
      IGDPImage := nil;
    end;
  Finally
    RäumeAuf;
  end;
end;
  Mit Zitat antworten Zitat
MartinK

Registriert seit: 21. Jun 2009
Ort: Germering (Germany)
89 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#75

AW: JPG-Datei drehen und speichern -> Verlust der Exif-Daten

  Alt 20. Aug 2021, 17:29
Da sind einige sehr wertvolle Infos für mich in diesem Thread.

Ich bräuchte noch mindestens ein weiteres Feature und tue mich leider mit dem interpretieren der IGDIPlus.pas leider schwer.

Ich möchte vor dem speichern mit "IGDPImage.Save" gerne noch die Kompressionsrate/Qualität angeben.
Hat hierzu jemand weiter Infos oder kann mir einen Tipp geben?
Martin Kuhn
  Mit Zitat antworten Zitat
Benmik

Registriert seit: 11. Apr 2009
532 Beiträge
 
Delphi 11 Alexandria
 
#76

AW: JPG-Datei drehen und speichern -> Verlust der Exif-Daten

  Alt 22. Aug 2021, 01:01
Hilft dir das hier weiter?
  Mit Zitat antworten Zitat
MartinK

Registriert seit: 21. Jun 2009
Ort: Germering (Germany)
89 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#77

AW: JPG-Datei drehen und speichern -> Verlust der Exif-Daten

  Alt 22. Aug 2021, 10:47
Herzlichen Dank Benmik. Das hilft mir schon um einiges weiter.
Ein Problem gelöst .... nächstes aufgetaucht

Die Encoder Parameter sind nur ein Array von 0..0

TIGPEncoderParameters = packed record
Count : UINT; // Number of parameters in this structure
Parameter : array[0..0] of TIGPEncoderParameter; // Parameter values
end;

Wenn ich jetzt mehrere Parameter in einem Rutsch definieren will, also zB "Orientierung" und "SaveQuality" geht das entsprechend nicht.
Oder irre ich mich da?

Finde es auch seltsam das es extra so etwas gibt wie ...
EncoderParameters.Count := 1;
Martin Kuhn
  Mit Zitat antworten Zitat
MartinK

Registriert seit: 21. Jun 2009
Ort: Germering (Germany)
89 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#78

AW: JPG-Datei drehen und speichern -> Verlust der Exif-Daten

  Alt 22. Aug 2021, 11:08
und falls sich noch jemand anders ausser mir ebenfalls schwertut die selbstverfasste Wiki des Autors in den Weiten des WWW zu finden

http://www.mitov.com/wiki/index.php?...IPlus.IGPImage
Martin Kuhn
  Mit Zitat antworten Zitat
Benmik

Registriert seit: 11. Apr 2009
532 Beiträge
 
Delphi 11 Alexandria
 
#79

AW: JPG-Datei drehen und speichern -> Verlust der Exif-Daten

  Alt 22. Aug 2021, 21:18
Leider bin ich zurzeit nur beschränkt aktionsfähig; Internet z.B. nur über Handy, daher kann ich nur eingeschränkt Auskunft geben.

Denke daran, dass Mitov und Konsorten nur Wrapper für GDIPlus sind; bei Fragen kannst du also auch bei MSN nachschauen. Ich hatte damals dermaßen viele Wege ausprobiert, dass ich selbst erst nachschauen musste, für welche Variante ich mich eigentlich entschieden hatte. Wie ich jetzt sehe, ist es GdiPlus von Erik van Bilsen geworden (2009), allerdings modifiziert; ich habe dieses furchtbare GdiCheck, das bei der geringsten Kleinigkeit eine Exception ausgelöst hat, durch die Rückgabe des Status ersetzt (wie im Original von Microsoft). Warum Eric und nicht mehr Mitov, weiß ich nicht mehr.

Bei van Bilsen sehe ich, dass Add eine Menge von Überladungen hat; bei einer kann als Parameter auch ein Array von Parametern übergeben werden; das Argument ist dann ein Pointer auf das erste Arrayitem. Das müsste bei Mitov genauso sein.
  Mit Zitat antworten Zitat
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 19:35 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