EXIF-Daten mit PHP aus Bildern auslesen

PHP stellt seit Version 4.2.0 eine eigene Funktion bereit, die die EXIF-header-Daten auslesen kann. Ich habe die Möglichkeit genutzt und in eine eigene Funktion implementiert.

Die Zeiten ändern sich.

Dieser Beitrag scheint älter als 9 Jahre zu sein – eine lange Zeit im Internet. Der Inhalt ist vielleicht veraltet.

Exif
Die digitale Welt greift weiter um sich. Dabei spielt die digitale Photographie eine große Rolle und immer mehr Nutzer präsentieren ihre Bilder im Netz. Für diese Form gibt es eine ganze Reihe von Lösungen. Immer mehr Software und Kameras unterstützen das EXIF-Format und schreiben eine ganze Reihe von Information in die Bilder.

Nur die wenigsten Möglichkeiten unterstützen das Auslesen und Darstellen der EXIF-Header Daten eines Bildes. Aber gerade beim Präsentieren von Bildern sind diese Information oft sinnvoll und nützlich, ob für die eigenen Zwecke oder um dem geneigten Lesern die Einstellungen der Kamera nahe zu legen und damit eventuell ähnliche Ergebnisse zu erreichen. Verwendung findet diese Funktion im PhotoBlog-Theme, welches ich auch selbst nutze.

PHP stellt seit Version 4.2.0 eine eigene Funktion bereit, die die EXIF-header-Daten auslesen kann. Ich habe die Möglichkeit genutzt und in eine eigene Funktion implementiert. Die Werte der Funktion exif_read_data werden in einem Array abgelegt und entsprechen nicht den üblichen Leseformen von Photographieinteressenten. Dazu muss ein wenig mehr machen. Einziger Nachteil, die Funktion kann lediglich JPG und TIFF auslesen. Will man das im Vorfeld sicher stellen, dann hilft die Funktion exif_imagetype.

Damit man das Rad nicht immer neu erfinden muss, kann die folgende Funktion gerne genutzt werden. Die Funktion liest nicht alle Werte aus - es gibt recht viele, und nicht alle hielt ich für relevant. Damit man aber mal einen Überblick über alle Inhalte bekommen kann, ist der folgende Syntax hilfreich.


$image = '/pfad/bild.jpg';
$exif = exif_read_data($image, 0 , true);

foreach ($exif as $key => $section) {
	foreach ($section as $name => $val) {
		echo "$key.$name: $val
\n"; } }

function fb_read_write_exif_data($post_ID) {

	$image = '/pfad/bild.jpg';
	
	if ($image != '') {
		error_reporting(0);
		
		$exif = exif_read_data($image, 0 , true);
		
		if(isset($exif["EXIF"]["DateTimeOriginal"])) {
			$fbdateoriginal = str_replace(":","-",substr($exif["EXIF"]["DateTimeOriginal"], 0, 10));
			$fbtimeoriginal = substr($exif["EXIF"]["DateTimeOriginal"], 10);
			print __('Datum:', 'photoblogfb') . " {$fbdateoriginal}";
			print __(' · Uhrzeit:', 'photoblogfb') . " {$fbtimeoriginal}";
			print "
\n"; } if(isset($exif["EXIF"]["FNumber"])) { list($num, $den) = explode("/",$exif["EXIF"]["FNumber"]); $fbaperture = "F/" . ($num/$den); print __('Blende:', 'photoblogfb') . " {$fbaperture}";; } if(isset($exif["EXIF"]["ExposureTime"])) { list($num, $den) = explode("/", $exif["EXIF"]["ExposureTime"]); if ($num > $den) { $fbexposure = "{$num}s"; print __(' · Belichtungsdauer:', 'photoblogfb') . " {$fbexposure}"; } else { $den = round($den/$num); $fbexposure = "1/{$den}s"; print __(' · Belichtungsdauer:', 'photoblogfb') . " {$fbexposure}"; } } if(isset($exif["EXIF"]["FocalLength"])) { list($num, $den) = explode("/", $exif["EXIF"]["FocalLength"]); $fbfocallength = ($num/$den) . "mm"; print __(' · Brennweite:', 'photoblogfb') . " {$fbfocallength}"; } if(isset($exif["EXIF"]["FocalLengthIn35mmFilm"])) { $fbfbfocallength35 = $exif["EXIF"]["FocalLengthIn35mmFilm"]; print __(', (KB-Format entsprechend:', 'photoblogfb') . " {$fbfbfocallength35}" . __('mm)'); } print "
\n"; if ( isset($exif["EXIF"]["ISOSpeedRatings"]) ) { print __('ISO:', 'photoblogfb') . " {$exif["EXIF"]["ISOSpeedRatings"]}"; } if (isset($exif["EXIF"]["WhiteBalance"]) ) { switch($exif["EXIF"]["WhiteBalance"]) { case 0: $fbwhitebalance = "Auto"; break; case 1: $fbwhitebalance = "Daylight"; break; case 2: $fbwhitebalance = "Fluorescent"; break; case 3: $fbwhitebalance = "Incandescent"; break; case 4: $fbwhitebalance = "Flash"; break; case 9: $fbwhitebalance = "Fine Weather"; break; case 10: $fbwhitebalance = "Cloudy"; break; case 11: $fbwhitebalance = "Shade"; break; default: $fbwhitebalance = ''; break; } print __(' · Weißabgleich:', 'photoblogfb') . " {$fbwhitebalance}"; } if (isset($exif["EXIF"]["Flash"]) ) { switch($exif["EXIF"]["Flash"]) { case 0: $fbexif_flash = 'Flash did not fire'; break; case 1: $fbexif_flash = 'Flash fired'; break; case 5: $fbexif_flash = 'Strobe return light not detected'; break; case 7: $fbexif_flash = 'Strobe return light detected'; break; case 9: $fbexif_flash = 'Flash fired, compulsory flash mode'; break; case 13: $fbexif_flash = 'Flash fired, compulsory flash mode, return light not detected'; break; case 15: $fbexif_flash = 'Flash fired, compulsory flash mode, return light detected'; break; case 16: $fbexif_flash = 'Flash did not fire, compulsory flash mode'; break; case 24: $fbexif_flash = 'Flash did not fire, auto mode'; break; case 25: $fbexif_flash = 'Flash fired, auto mode'; break; case 29: $fbexif_flash = 'Flash fired, auto mode, return light not detected'; break; case 31: $fbexif_flash = 'Flash fired, auto mode, return light detected'; break; case 32: $fbexif_flash = 'No flash function'; break; case 65: $fbexif_flash = 'Flash fired, red-eye reduction mode'; break; case 69: $fbexif_flash = 'Flash fired, red-eye reduction mode, return light not detected'; break; case 71: $fbexif_flash = 'Flash fired, red-eye reduction mode, return light detected'; break; case 73: $fbexif_flash = 'Flash fired, compulsory flash mode, red-eye reduction mode'; break; case 77: $fbexif_flash = 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected'; break; case 79: $fbexif_flash = 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected'; break; case 89: $fbexif_flash = 'Flash fired, auto mode, red-eye reduction mode'; break; case 93: $fbexif_flash = 'Flash fired, auto mode, return light not detected, red-eye reduction mode'; break; case 95: $fbexif_flash = 'Flash fired, auto mode, return light detected, red-eye reduction mode'; break; default: $fbexif_flash = ''; break; } print __(' · Blitz:', 'photoblogfb') . " {$fbexif_flash}"; } /** if(isset($exif["EXIF"]["Flash"])) { $fbflash = (bindec($exif["EXIF"]["Flash"]) ? "On" : "Off"); print __(' · Blitz:', 'photoblogfb') . " {$fbflash}"; } */ print "
\n"; if(isset($exif["IFD0"]["Make"]) && isset($exif["IFD0"]["Model"])) { $fbmake = ucwords(strtolower($exif["IFD0"]["Make"])); $fbmodel = ucwords($exif["IFD0"]["Model"]); print __('Kamera o. DIA-Scanner:', 'photoblogfb') . " {$fbmake}"; print __(',', 'photoblogfb') . " {$fbmodel}"; } /* Alle EXIF-Daten untereinander ausgeben */ /** foreach ($exif as $key => $section) { foreach ($section as $name => $val) { echo "$key.$name: $val
\n"; } } */ } }

23 Comments

  1. Problematisch wird es, wenn die Bilder vorher mit der GD Library in PHP bearbeitet wurden - dann gehen die EXIF-Information verloren.

  2. Ich habe versucht noch ein anderen Exif-Tag auslesen zu lassen, namentlich 'Software'. Erfolglos, aber. Ich habe es mit

    if (isset($exif["EXIF"]["Software"])) {
    print __(' · Software:') . " {$exif["EXIF"]["Software"]}";
    }

    versucht, aber, wie man so schön sagt, da kommt nüscht. Ich bin mir 99%ig sicher dass der Tag auch 'Software' heißt, hab ihn aus der Exif-pdf-Datei die du neulich verlinkt hast. Wie müsste ich den Code denn ändern damit es angezeigt wird? Danke im Voraus.
    Jakob

  3. Hey Frank, ist ein sehr interessantes Thema. Habe auch auf meinem neuen Blog (Online seit gestern früh) mal was dazu geschrieben und auf dein Beitrag verwiesen.

    Grüße dich auch gleich mal mit diesem Kommentar. Hast mir ja schon des öfteren aus der Patsche in Sachen WordPress geholfen. Und bin nun auch wieder aktiv unter den Bloggern 😉

    lg Engel

  4. Interessant wäre es, wenn man auch individuelle EXIF-Daten in dem Bild einfügen könnte. Wäre das möglich?

  5. Dazu müsste man die Exif-Daten des Bildes erweitern. Einige Tools können das, da weis ich aber keinen Tipp, da ich das Ziel nie hatte. Adobe Lightroom kann das eventuell, z.B. Bild mit Tags versehen. Das Auslesen dieser Daten im Theme müsste dann in der functions.php ergänzt werden.

  6. Code ist erstmal korrekt. Hast du mal alle Werte in der Schleife ausgeben lassen, vielleicht ist der Wert nicht vorhanden? Ansonsten prüfe ihn mit einem Desktoptool.

  7. Ich bin mir nicht ganz sicher was du mit "alle Werte" meinst. Alle möglichen Exif-Werte? Und: der Wert ist auf jeden Fall da, ich hab ihn mit drei verschiedenen Desktop-Tools gecheckt. Er wird auch nicht beim Upload 'fallengelassen' oder gelöscht, denn selbst wenn ich das Bild nochmal runterlade sind alle Exif-Daten, inkl. "Software" noch da.

  8. @Jakob: Im ersten Codeschnipsel habe ich eine Möglichkeit dargestellt, wie man alle enthaltenen Werte und Schlüssel darstellen kann. Damit kann man in jedem Fall erst einmal auf Vorhanden prüfen. Eventuell könnte dann noch ein Fehler im Code vorliegen.

  9. Ah natürlich, das war ja auch schon in der functions.php integriert, hab ich wohl übersehen. Habe es gerade ausprobiert, auch da wird 'software' nicht angezeigt. Was wirklich komisch ist, denn der Tag ist nunmal vorhanden, und auch "ausgefüllt".
    Dennoch fiel mir noch etwas anderes auf: bei bestimmten Tags schien es Fehler bzgl. UTF-8 zu geben. Manche Werte wurde als pure Abfolge von diesen "Rauten mit Fragezeichen" dargestellt; vornehmlich die die irgendwie manuell geändert werden konnten ("EXIF.MakerNote", "EXIF.UserComment", "Firmware Version").

  10. Und gerade sah ich noch etwas: m.E. hast du die möglichen Values beim Flash falschrum gesetzt; ich denke es sollte

    $fbflash = (bindec($exif["EXIF"]["Flash"]) ? "Off" : "On");

    heißen. Zumindest habe ich das bei meinen Bildern so gesehen. Bei denen die definitiv einen Blitz benutzten stand er auf 'Off', bei anderen Tagsüber-Bildern auf 'On'.

  11. Sollte eigentlich richtig sein. Entscheidend ist jedoch, was die Schleife ausgibt. Denn dort sieht man alle Schlüssel und Werte. Dementsprechend kann die Formatierung angepasst werden.
    Wer der Schlüssel nicht in der Schleife ausgegeben wird, dann ist er nicht zum Auslesen da. Es sei denn denn, er gehört nicht zu den EXIF-Daten. Im Beispiel lese ich ja EXIF- und IFD0-Daten aus.

  12. Wie kann ich jetzt festellen, ob das exif Array Daten hatt oder nicht. Wenn keine Exif Daten da sind dann soll eine Meldung erscheinen.

    Mfg Matthias

  13. Am besten mit einem Desktop-Tool, mal suchen, da gibt es Unmengen.

    Alternativ kannst du die index.php anpassen, Zeile 57:

    			} else {
    				echo 'Keine Datei vorhanden!';
    			}
    

    für die Prüfung, ob die Datei vorhanden ist und dann kann jede if-Abfrage (if($exif . . .) für EXIF-Daten mit einer else-Antwort versehen werden.

Comments are closed.