fpexif: XMP daten manipulieren

Rund um die LCL und andere Komponenten
Benutzeravatar
h-elsner
Lazarusforum e. V.
Beiträge: 259
Registriert: Di 24. Jul 2012, 15:42
OS, Lazarus, FPC: LINUX Mint21.1, Win10, Lazarus 2.2.4, FPC3.2.2
CPU-Target: X86-64; arm 32bit
Wohnort: Illertissen
Kontaktdaten:

fpexif: XMP daten manipulieren

Beitrag von h-elsner »

Ich bin begeisterter, aber ziemlich unbedarfter Nutzen der Komponente fpexif. Mit den normalen EXIF tags komme ich gut zurecht. Nun würde ich aber gerne die XMP Daten manipulieren. Die Länge des Datenblocks verändert sich dabei.
So wie ich das sehe, werden die XMP-daten nur kopiert und zurückgeschrieben. Ich habe leider keinen Ansatz gefunden, diese zu veränderen.
Geht das überhaupt? Kann man die Länge des Datenblockes vor dem Zurückschreiben irgendwie neu setzen? Ich denke mal es wird nicht so einfach gehen, da irgendwie in dem JPG herumzueditieren.

Gruß HE

wp_xyz
Beiträge: 4889
Registriert: Fr 8. Apr 2011, 09:01

Re: fpexif: XMP daten manipulieren

Beitrag von wp_xyz »

Ist schon eine Zeit lang her, dass ich das geschrieben habe... Wenn ich mich recht erinnere (und mir jetzt den Source-Code anschaue), war das eigentliche Interesse im Lesen und Schreiben der EXIF-Werte und vielleicht noch von IPTC. Aber XMP kam eigentlich erst später rein, als sich ein User (du?) beschwert hat, dass meine Routinen das XMP-Segment aus der JPEG-Datei entfernen. Daher wird nun dieser Block gelesen und 1:1 in die Ziel-Datei zurückgeschrieben. Einen tiefergehenden Support gibt es zur Zeit nicht.

Wenn dir das wichtig ist und du dich in die Materie einarbeiten willst, kannst du mir natürlich einen Patch schicken, dann baue ich das ein.

Benutzeravatar
h-elsner
Lazarusforum e. V.
Beiträge: 259
Registriert: Di 24. Jul 2012, 15:42
OS, Lazarus, FPC: LINUX Mint21.1, Win10, Lazarus 2.2.4, FPC3.2.2
CPU-Target: X86-64; arm 32bit
Wohnort: Illertissen
Kontaktdaten:

Re: fpexif: XMP daten manipulieren

Beitrag von h-elsner »

Danke für die Info, so habe ich mir schon gedacht. Und ja, das war ich. Damals hat mich das Segment auch nicht weiter interessiert, es sollte nur übernommen werden. Danke für den Update der Komponente damals.
Mal sehen, ob ich herausfinden kann, wie das ganze Funktioniert. Wenn ich Fragen habe, melde ich mich.

Gruß HE

Benutzeravatar
h-elsner
Lazarusforum e. V.
Beiträge: 259
Registriert: Di 24. Jul 2012, 15:42
OS, Lazarus, FPC: LINUX Mint21.1, Win10, Lazarus 2.2.4, FPC3.2.2
CPU-Target: X86-64; arm 32bit
Wohnort: Illertissen
Kontaktdaten:

Re: fpexif: XMP daten manipulieren

Beitrag von h-elsner »

An den Sourcen der Komponente von fpexif traue ich mich nicht herumzuspielen, weill ich nicht alles verstehe, was da gemacht wird. Aber ich kann nun die XMP-Daten auslesen. da einiges von fpexif geklaut/kopiert ist, wäre es wahrscheinlich nicht so schwer, das irgendwie zu integrieren. Die XMP-Daten stehen in einer TStringList zur weiteren Bearbeitung.

Code: Alles auswählen

procedure ReadXMP(const fn: string; var XMPlines: TStringList);
var
  strInput: TFileStream;
  strXMP: TMemoryStream;
  p, n: int64;
  marker: byte;
  size: word;
  s: string;

begin
  XMPlines.Clear;
  XMPlines.TextLineBreakStyle:=tlbsLF;             {#10 as line ending}
  strXMP:=TMemoryStream.Create;
  strInput:=TFileStream.Create(fn, fmOpenRead or fmShareDenyNone);
  s:='';
  try
    strInput.Position:=0;
    p:=0;
    if not ((ReadByte(strInput) = M_ID) and (ReadByte(strInput) = M_SOI)) then
      exit;
    while p<strInput.Size do begin
      repeat
        marker:=ReadByte(strInput);
      until marker<M_ID;
      size:=BEtoN(ReadWord(strInput))-2;               // Size of the pure XMP data
      p:=strInput.Position;
      case marker of
      
        M_EXIF:
          begin
            SetLength(s, Length(XMP_SIGNATURE));
            strInput.Read(s[1], Length(XMP_SIGNATURE));
            strInput.Position:=p;                      // Go back to begin of XMP data
            if s = XMP_SIGNATURE then begin            // Check if segment is XMP data
              n:=strXMP.CopyFrom(strInput, size);
              strXMP.Position:=0;
              if n=size then
                XMPlines.LoadFromStream(strXMP, true);
              break;                                   // Done, get out of here
            end
             
            else 
            begin
              strInput.Position:=p+size;               // Skip EXIF segment
            end;
          end;
        M_EOI, M_SOS:
          break;
      end;
    end;
  finally
    strInput.Free;
    strXMP.Free;
  end;
end;
Das Zurückschreiben schaue ich mir jetzt an.

Edit:
XMPlines.TextLineBreakStyle:=tlbsLF; eingefügt.


Gruß HE
Zuletzt geändert von h-elsner am So 6. Mär 2022, 20:00, insgesamt 1-mal geändert.

wp_xyz
Beiträge: 4889
Registriert: Fr 8. Apr 2011, 09:01

Re: fpexif: XMP daten manipulieren

Beitrag von wp_xyz »

Ja, so ähnlich würde ich es auch machen. Allerdings würde ich die XMP-Daten in einen XMLDocument-Baum einlesen, damit hätte man schon alle "Tags" (heißt das hier auch so?) säuberlich getrennt, könnte die gewünschten editieren und am Ende alles über einen Stream wieder in die JPEG-Dateistruktur zurückschreiben.

Hast du vielleicht ein paar Bilder mit XMP-Daten? Ich könnte mir das demnächst mal anschauen.

Benutzeravatar
h-elsner
Lazarusforum e. V.
Beiträge: 259
Registriert: Di 24. Jul 2012, 15:42
OS, Lazarus, FPC: LINUX Mint21.1, Win10, Lazarus 2.2.4, FPC3.2.2
CPU-Target: X86-64; arm 32bit
Wohnort: Illertissen
Kontaktdaten:

Re: fpexif: XMP daten manipulieren

Beitrag von h-elsner »

Hier sind ein paar kleine Bilder:
XMP_bilder.zip
(1.18 MiB) 58-mal heruntergeladen
Gruß HE

Benutzeravatar
h-elsner
Lazarusforum e. V.
Beiträge: 259
Registriert: Di 24. Jul 2012, 15:42
OS, Lazarus, FPC: LINUX Mint21.1, Win10, Lazarus 2.2.4, FPC3.2.2
CPU-Target: X86-64; arm 32bit
Wohnort: Illertissen
Kontaktdaten:

Re: fpexif: XMP daten manipulieren

Beitrag von h-elsner »

wp_xyz hat geschrieben:
So 6. Mär 2022, 16:38
Allerdings würde ich die XMP-Daten in einen XMLDocument-Baum einlesen, damit hätte man schon alle "Tags" (heißt das hier auch so?) säuberlich getrennt, könnte die gewünschten editieren und am Ende alles über einen Stream wieder in die JPEG-Dateistruktur zurückschreiben.
Ja sicher, das wäre die beste Lösung. Aber das Bearbeiten der XMP-Daten ist das kleinste Problem.
In dem Zusammenhang sehe ich aber, dass die Übergabe der XMP-Daten als MemoryStream wesentlich flexibler ist, als eine StringList zu benutzen.
Da kann jeder machen, was er will.
Beim Zurückschreiben die Länge anfügen und fertig.
Ich habe es mal so gemacht:

Code: Alles auswählen

sz: word;
	...
                  sz:=Xstream.Size and $FFFF;
                  Xstream.Position:=0;
                  Xstream.WriteWord(NtoBE(sz+2));
	...
Gruß HE

Benutzeravatar
h-elsner
Lazarusforum e. V.
Beiträge: 259
Registriert: Di 24. Jul 2012, 15:42
OS, Lazarus, FPC: LINUX Mint21.1, Win10, Lazarus 2.2.4, FPC3.2.2
CPU-Target: X86-64; arm 32bit
Wohnort: Illertissen
Kontaktdaten:

Re: fpexif: XMP daten manipulieren

Beitrag von h-elsner »

Ich habe doch mal in fpexif, fpemetadata.pas gebastelt und eine function HasXMP eingeführt.
fpemetadata_HasXMP.zip
(6.3 KiB) 43-mal heruntergeladen
Die Änderungen sind gekennzeichnet. Diese Kennzeichnung kann dann weg.
Allerdings bin ich daran gescheitert, einen XMP-Stream als Property einzurichten. Ich verstehe das ganze Konstrukt noch nicht.

Gruß HE

wp_xyz
Beiträge: 4889
Registriert: Fr 8. Apr 2011, 09:01

Re: fpexif: XMP daten manipulieren

Beitrag von wp_xyz »

Ich habe gerade meine Version von gestern hochgeladen. Es gibt da eine Klasse TXMPData (genauso wie TExifData und TIptcData), die sich um die XMP-Metadaten kümmert. Sie prüft die XMP-Kennung am Beginn des JPEG-Segments und liest dann den gesamten Block als String ins Objektfeld FData ein. Dieses ist von außen nicht direkt sichtbar, sondern kann nur mit Hilfe ein Streams (LoadFromStream, SaveToStream) ausgelesen bzw. zurückgeschrieben werden, so dass mir noch etwas Kontrolle bleibt, was mit den Daten geschieht. Beim Einlesen wird gleichzeitig ein XMLDocument erzeugt, die Nodes und ihre Attribute werden ausgelesen und in eine Stringliste als Name=Value Paare gespeichert. XMPData hat, darauf aufbauend, Properties TagByIndex[Index] und TagByName[TagNaName], um Werte auszulesen. Schreib-Unterstützung plane ich nicht, weil ich dann genau Buch führen müsste, wo die Werte herkommen (Attribut? Text-Wert welches XML-Nodes?).

Im Beispielprogramm "metadataviewer" sieht man die Anwendung, suche in der Haupt-Unit nach "XMPData".

Zurückschreiben kann man die XMP-Daten noch nicht. Was mich noch verwirrt, ist dass am Ende des XML-Bereichs Unmengen von Leerzeichen eingefügt sind. Ist denn die Länge konstant?

Benutzeravatar
h-elsner
Lazarusforum e. V.
Beiträge: 259
Registriert: Di 24. Jul 2012, 15:42
OS, Lazarus, FPC: LINUX Mint21.1, Win10, Lazarus 2.2.4, FPC3.2.2
CPU-Target: X86-64; arm 32bit
Wohnort: Illertissen
Kontaktdaten:

Re: fpexif: XMP daten manipulieren

Beitrag von h-elsner »

Was die Entwickler der jeweiligen FW der Kameras so machen zu verstehen, habe ich schon lange aufgegeben. Vielleicht schreiben sie feste Blöcke und wollen sich Raum für spätere Änderungen reservieren oder was auch immer. Vernünftige Änderungen komme aber nie.
Auslöser für meinen Wunsch XMP-daten zu bearbeiten war die tatsache, dass die radiometrische Software für die Bilder der Wärmebildkamera nur mit der neuen Firmware funktioniert, die alte Firmware aber bessere Videosyncronisation zwischen Wärmebild- und Restlichtkamera hat.

Nun wollte ich nur zum Spaß (habe keine WB-Kamera - zu teuer) mal sehen, ob man die Daten aus der alten FW nicht so anpassen kann, dass das Auswerteprogramm sie doch akzeptiert. Das Auswerteprogramm von denen hat auch so seine Macken. Es funktioniert nicht mit jeder Lokalisierung. Deutsch (Deutschland) geht nicht, Deutsch (Schweiz) oder Englisch geht. Alles Pfusch aus meiner Sicht, aber eben auch geistige Nahrung für Rentner :P .

Vielen dank für deine Mühe - ich schaue mir mal deine Version gleich mal an.

Gruß HE

Benutzeravatar
h-elsner
Lazarusforum e. V.
Beiträge: 259
Registriert: Di 24. Jul 2012, 15:42
OS, Lazarus, FPC: LINUX Mint21.1, Win10, Lazarus 2.2.4, FPC3.2.2
CPU-Target: X86-64; arm 32bit
Wohnort: Illertissen
Kontaktdaten:

Re: fpexif: XMP daten manipulieren

Beitrag von h-elsner »

Wunderhübsch, das funktioniert wie gewünscht.
Danke!

Gruß HE

wp_xyz
Beiträge: 4889
Registriert: Fr 8. Apr 2011, 09:01

Re: fpexif: XMP daten manipulieren

Beitrag von wp_xyz »

Jetzt ist auch das Zurückschreiben möglich.

An dem "metadataviewer"-Demoprojekt kannst du sehen, wie ich mir das vorstelle: Wenn das Flag mdkXMP gesetzt ist, werden die XMP-Metadaten, so wie in der vorigen Nachricht beschrieben in das XMPData-Objekt eingelesen, über ein XMLDocument auseinandergepflückt, so dass sie über die Tag*-Properties ausgelesen werden können. Diese Tags lasse ich aber der Vereinfachung halber read-only.

Um XMP-Daten zu bearbeiten, schreibst du sie über das Stream-Interface (LoadFromStream) in einen Stream, der wiederum von einem Memo oder SynEdit eingelesen wird. In dem Memo kannst du sie verändern, wobei es natürlich ich deiner Verantwortung liegt, dass die XMP/XML-Struktur gültig bleibt. (Ich hab's nicht getestet, aber ich könnte mir vorstellen, dass, wenn ein Programm XMP auswertet und dort einen Fehler findet, auch der Rest der Datei nicht gelesen werden kann.) Zum Übertragen ins XMPData-Objekt schreibst du das Memo/SynEdit in einen Stream und liest diesen vom XMPData-Objekt wieder ein. Dabei wird auch das XMLDocument erneuert, so dass man die geänderten XMP-Daten auch über die Tag*-Properties abfragen kann.

[EDIT]
Über die Rolle von mdkXMP muss ich noch nachdenken. Ich will damit eigentlich verhindern, dass die ganze Datei nicht mehr gelesen werden kann, falls in der XMP-Struktur ein dämlicher XML-Fehler ist. Aber möglicherweise gehe ich da zu weit: Jetzt, wenn mdkXMP in der Menge MetadataKinds NICHT enthalten ist, wird das XMP-Segment total ignoriert, so wie in der alten Version. Aber vielleicht wäre es besser zumindest den String einzulesen, so dass man es wie oben beschrieben, noch editieren kann. In diesem fall würde das Fehlen von mdkXMP in MetadataKinds lediglich die Auswertung der XML-Struktur unterbinden - eigentlich die einzige Stelle, in der die XMP-Routinen in der Praxis abstürzen können.

Benutzeravatar
h-elsner
Lazarusforum e. V.
Beiträge: 259
Registriert: Di 24. Jul 2012, 15:42
OS, Lazarus, FPC: LINUX Mint21.1, Win10, Lazarus 2.2.4, FPC3.2.2
CPU-Target: X86-64; arm 32bit
Wohnort: Illertissen
Kontaktdaten:

Re: fpexif: XMP daten manipulieren

Beitrag von h-elsner »

Hervorragend. Danke! Ich hatte gestern noch mit deiner Version Patch8201 experimentiert. Auslesen in den Stream, Bearbeiten und Zurückschreiben in einen TMemoryStream haben wunderbar funktioniert.
Eine Stringlist hängt allerdings hinten noch ein Zeilenende an, welches man entfernen muss.
Also Stringlist mit TextLineBreakStyle:=tlbsLF; und Stream Size:=Size-1; . Dann hat man genau das, was man braucht.

Jetzt teste ich das Hochladen und melde mich wieder.

Gruß HE

Benutzeravatar
h-elsner
Lazarusforum e. V.
Beiträge: 259
Registriert: Di 24. Jul 2012, 15:42
OS, Lazarus, FPC: LINUX Mint21.1, Win10, Lazarus 2.2.4, FPC3.2.2
CPU-Target: X86-64; arm 32bit
Wohnort: Illertissen
Kontaktdaten:

Re: fpexif: XMP daten manipulieren

Beitrag von h-elsner »

Hmm, ich kann es nicht kompilieren. Lazarus stable und trunk. Folgende Meldung:
fpemetadata.pas(130,45) Fatal: Cannot find fpeXMPReadWrite used by fpeMetadata. Check search path of package fpexif_pkg, try a clean rebuild, check implementation

Code: Alles auswählen

Compile package fpexif_pkg 0.1: Exit code 1, Errors: 1, Hints: 2
Hint: Start of reading config file C:\fpcupdeluxe\Lazarus_stable\fpc\bin\x86_64-win64\fpc.cfg
Hint: End of reading config file C:\fpcupdeluxe\Lazarus_stable\fpc\bin\x86_64-win64\fpc.cfg
Verbose: Free Pascal Compiler version 3.2.2-rrelease_3_2_2-0-g0d122c4953 [2021/12/19] for x86_64
Verbose: Copyright (c) 1993-2021 by Florian Klaempfl and others
Verbose: Target OS: Win64 for x64
Verbose: Compiling fpexif_pkg.pas
Verbose: Compiling fpemetadata.pas
fpemetadata.pas(130,45) Fatal: Cannot find fpeXMPReadWrite used by fpeMetadata. Check search path of package fpexif_pkg, try a clean rebuild, check implementation uses sections..
Verbose: Compilation aborted
Verbose: C:\fpcupdeluxe\Lazarus_stable\fpc\bin\x86_64-win64\ppcx64.exe returned an error exitcode

Edit: Die Datei fpeXMPReadWrite.pas fehlt im Snapshot, wenn ich ihn downloade.

Gruß HE

wp_xyz
Beiträge: 4889
Registriert: Fr 8. Apr 2011, 09:01

Re: fpexif: XMP daten manipulieren

Beitrag von wp_xyz »

Sorry. Sollte nun funktionieren.

Antworten