Exif- und IPTC-Metadaten mit PHP: So geht's
Die Bearbeitung von Metadaten von Fotos mit PHP ist insgesamt sehr schlecht dokumentiert. Wir haben uns auf die Suche gemacht.

Die in Fotos enthalten Metadaten bieten für Webseiten-Besucher interessante Informationen. Viele Web-Entwickler nutzen also diese Daten, um z.B. den Zeitpunkt einer Aufnahme oder Infos zu Blende und Zeit zu bestimmen. Das lässt sich mit PHP noch relativ einfach bewerkstelligen. Schwieriger wird es...
Die in Fotos enthalten Metadaten bieten für Webseiten-Besucher interessante Informationen. Viele Web-Entwickler nutzen also diese Daten, um z.B. den Zeitpunkt einer Aufnahme oder Infos zu Blende und Zeit zu bestimmen. Das lässt sich mit PHP noch relativ einfach bewerkstelligen. Schwieriger wird es, Daten in die Bilder hineinzuschreiben, etwa Schlüsselwörter oder einen Copyright-Hinweis. Das dafür nötige Vorgehen, ist leider in den PHP-Manuals und überhaupt im Web ausgesprochen schlecht dokumentiert.
Wer flugs in die Perl-Welt wechseln möchte, findet mit dem Exiftool eine starke, funktionsreiche Bibliothek, die ausnahmsweise auch gut dokumentiert ist, Perl-Befehle lassen sich auch in PHP aufrufen und deren Ergebnisse weiterverarbeiten. Ein kleines Augenmerk muss man auf die deutschen Umlaute legen.
Wer nicht die ganze Bandbreite des Exiftools benötigt und seinen Webauftritt mit weniger Aufwand auf dem Server betreiben will, kann auch in der PHP-Welt bleiben. Denn es gibt auch hier eine Reihe an Hilfen, deren Dokumentation aber stark zu Wünschen übrig lässt. Die Meta-Tags aus Bildern auszulesen, funktioniert noch ganz ordentlich, aber beim Zurückschreiben, wird es kritisch, denn die Daten müssen in binäre Formate mit bestimmten ASCII-Trennzeichen gewandelt werden.
Dazu findet sich im PHP-Manual noch eine Beschreibung, aber nur für eine Art von Tag, z.B. ein Keyword. Wer aber mehrere Keywords setzen (oder einfach aus der bestehenden Datei übernehmen will) und noch eine Überschrift oder Ähnliches hinzufügen möchte, scheitert mit den gängigen Beschreibungen. Wir haben uns also auf die Suche nach einer Lösung gemacht.
Beginnen wir eine kurze Bestandaufnahme: PHP kennt ein paar Befehle um Exif-Daten auszulesen, z.B. exif_read_data oder exif_thumbnail. Exif zu schreiben, ist nicht vorgesehen, aber auch selten wirklich nötig, da diese Daten ja bereits von der Kamera angelegt werden. Im PHP-Manual findet sich in den Kommentaren zu exif_thumbnail eine Beschreibung, dennoch Exif-Daten zu schreiben, wir gehen an dieser Stelle aber nicht weiter darauf ein.
Dann gibt es in der GD-Bibliothek (zur Bildbearbeitung mit PHP) ein paar Funktionen für das Lesen und Bearbeiten von IPTC-Daten, also Überschriften, Schlüsselwörter, Kategorien oder Urheberhinweise. Das ist für den Web-Entwickler interessanter: getimagesize liefert neben der Bildgröße auch die IPTC-Daten aus, und mit iptcembed lassen sich neue Daten schreiben (aber wie gesagt nur binär!) Für diese beide Kommandos muss der Entwickler die GD-Bibliothek übrigens nicht eigens aktivieren, sie funktionieren auch so.
XMP-Metadaten sind in PHP nicht vorgesehen.
Exif lesen
Die von der Kamera erfassten Standarddaten auszulesen ist relativ trivial:
$exifdaten = exif_read_data("./DSC_3088.jpg");
var_dump($exifdaten);
exif_read_data schmeißt alles in ein mächtiges Array, das sich in seine gewünschten Einzelteile zerlegen lässt.

Auch das extrahieren der Thumbnails ist nicht schwer. Im folgenden Beispiel übergeben wir es gleich der Webseite:
$kleinbild = exif_thumbnail("./DSC_3088.jpg", $width, $height, $type);
if ($kleinbild!==false) {
header("Content-type: . image_type_to_mime_type($type)");
echo "<img src='data:image/gif;base64,".base64_encode($kleinbild)."'>";
} else echo "Kein Thumbnail verfügbar";
Die Parameter width und height liefern die Abmessungen und type eben den Typ des Thumbnails (jpeg oder tiff). Die header-Angabe entfällt, falls exif_read_data zuvor ausgeführt wurde.

IPTC auslesen
Beim Auslesen der IPTC-Daten wird es schon etwas trickreicher. Das funktioniert über die Funktion getimagesize, genauer gesagt über den Zusatzparameter $info.
$size = getimagesize($bildname, $infos);
if (isset($infos["APP13"])) {
$iptc_orig = iptcparse($infos["APP13"]);
var_dump($iptc_orig);
} else echo "Keine IPTC-Daten ";
Zwei Besonderheiten fallen auf: Der Parameter APP13, der den entsprechenden Abschnitt der IPTC-Daten angibt (Abgesehen davon gibt es noch APP1, der nicht weiter von Interesse ist). Zweitens ist es notwendig, mit iptcparse den binären Datenstrom in ein Array zu wandeln. Leider gibt es keine Umkehrung von iptcparse, die also neue Stichwörter, in ein passendes binäres Format verwandeln würde. Hier ist Handarbeit erforderlich.

Binäre IPTC-Einträge erzeugen
Für das Einfügen von binären IPTC-Daten gibt es den bereits erwähnten Befehl iptcembed. Zuvor müssen wir aber wie ebenfalls bereits erwähnt die neuen Tags in ein binäres Format wandeln. Dessen Aufbau hat eine festgelegte Reihenfolge an ASCII-Zeichen:
chr(0x1c) . chr(2) . chr(25) . chr($lang >> 8) . chr($lang & 0xff) . $ein_neues_Keyword
$lang steht dabei für die Länge des einzugebenden Keywords. Die Zeichen für 2 und 25 geben den entsprechenden Abschnitt der IPTC-Daten an. 2#025 steht für Keywords, 2#105 für die Headline, 2#116 für die Copyright-Angabe usw. Eine Übersicht finden Sie in den Spezifikationen für IPTC.
Ein wichtiger Abschnitt legt zudem den Zeichensatz fest (siehe auch Nachtrag am Ende des Artikels): 1#090. Geben Sie unbedingt UTF-8 vor, damit die deutschen Umlaute richtig eingesetzt werden (was leider nicht heißt, dass alle Programme sie auch richtig auslesen). UTF-8 wird mit der Zeichenfolge ESC % G codiert (siehe dazu auch Wikipedia):
$ein_neues_Keyword = chr(0x1b) . chr(0x25) . chr(0x47);
Die so gewonnen einzelnen binären Abschnitte lassen sich mit Punkt verknüpft aneinanderreihen und mit iptcembed in das Bild einschreiben.
Achtung: Wenn bereits IPTC-Daten im Bild vorhanden waren, müssen Sie diese zuvor auslesen, neu kodieren und in den neuen binären Code einfügen, sonst gehen sie verloren. Der IPTC-Header wird jedes Mal komplett neu geschrieben.
IPTC schreiben
Nun kommen wir endlich zum Kern der Sache, dem Schreiben der Meta-Tags in das Bild. Die Funktion iptcembed benötigt hierfür drei Parameter: Den soeben mühsam erzeugten, neuen, binären IPTC-Inhalt, den Namen der neu zu erzeugenden Datei und einen Modus.
$bild_mit_tags_neu = iptcembed($binaeretags, $bildname, $modus);
Dabei stehen drei Modi zur Verfügung
- 0 Das neue Bild wird nur in die Variable ($bild_mit_tags_neu) eingefügt
- 1 es wird in die Variable eingefügt und dem Web-Client übergeben
- 2 es wird nur dem Web-Client übergeben
Meist ist 0 die richtige Wahl. Das neue Bild mit unseren richtig binär- und UTF-8-fomatierten IPTC-Tags speichern wir nun noch im Dateisystem ab:
$datei1 = fopen($bildname_neu, "w");
fwrite($datei1, $bild_mit_tags_neu);
fclose($datei1);
Zur Kontrolle lesen Sie die Tags am besten, wie oben beschrieben, noch einmal aus. Das ganze Verfahren lässt sich natürlich am besten in einer Schleife IPTC-Abschnitt für -Abschnitt abarbeiten.
Das vollständige PHP-Skript finden Sie in der folgenden Zip-Datei:
Anhang: Deutsche Umlaute mit UTF-8
Entwickler kennen das leidige Problem der deutschen Umlaute aus vielen Anwendungsbereichen, z.B. E-Mail. Man speichert ein Zeichen im Unicode (UTF-8) und in der Darstellung eines Tools erscheint eine ISO 8859-1-Interpretation: ä ö ü tauchen plötzlich verwegen als ä ö ü auf. Das lässt sich leider nicht ganz vermeiden, denn man kann den anderen Entwicklern ärgerlicherweise nicht vorschreiben, was sie tun und (unter-)lassen sollen. Man kann den Schaden nur insofern etwas begrenzen, also dass man selbst sauber arbeitet und alles erstmal richtig anlegt.
Achten Sie darauf, dass alle Ihre Tools mit Unicode arbeiten, also der Webserver, PHP, MySQL und auch Ihr Editor bzw. Ihre Entwicklungsumgebung. Und setzen Sie bei Metatags in Bildern den Zeichenkode-Zeiger im Abschnitt 1#090 auf ESC % G, wie im Text beschrieben. Dann wird Ihre eigene Webseite keine Fehler auswerfen, aber Problem, wie die bei Xnview (siehe Bilder) lassen sich eben doch nicht vermeiden.

