Sortieren Sie Fotos nach Daten aus EXIF ​​+ PHP

Ich möchte meine Erfahrungen beim Sortieren von Fotos mithilfe eines Skripts in PHP teilen
Es kommt ein Moment, in dem es nicht viele Fotos gibt, aber katastrophal viele.

Hintergrund


Eines Tages beschloss ich, mein gesamtes Archiv digitaler Fotos zu sortieren, das sich ĂĽber 20 Jahre angesammelt hatte, und stellte fest, dass ich in all dieser Zeit 112.000 Fotos mit 435 Gigabyte angesammelt hatte.

Darüber hinaus sind einige von ihnen mehr oder weniger sortiert, z. B. Fotos von einer DSLR-Kamera, nach Ordnern mit Namen und Datum, und der andere Teil der Fotos, die von iPhone / Android importiert wurden, wird nicht benannt und sortiert. Oft handelt es sich nur um einen riesigen Ordner 10 Gigabyte mit ein paar tausend Dateien im Inneren, und es ist schade, sie zu löschen und zu sortieren.

Ich suchte nach automatischen Sortierwerkzeugen und stellte fest, dass alle guten Dienste wie Picasa bereits von Google gekauft und geschlossen wurden. Natürlich können Sie alles auf Google hochladen. Fotos gibt es jedoch Probleme, nicht alle werden durchsucht und im Allgemeinen fehlt die Hälfte der Funktionen In Picasa zu sein und wenn Sie immer noch befürchten, dass Ihre Fotos erkannt und verwendet werden, ist das Hochladen ins Internet überhaupt nicht Ihr Weg.

Aus diesem Grund wurde beschlossen, ein kleines Skript zu schreiben, das alles sortiert. Zuerst dachte ich über ein Shell-Skript nach, aber als EXIF ​​erkannte, dass ich es brauchen würde, beschloss ich, zum guten alten PHP zurückzukehren.

Aufgabe Nr. 1 - Erweitern Sie alle Dateien nach Datum


Zuerst ging ich den einfachsten Weg, nahm alle Dateien, sah das Erstellungsdatum und verteilte mich auf den verschachtelten Pfaden:

$file_list = $files->getDirContents($config['photos.unsorted']); foreach ($file_list as $key => $value) { moveImageFile($value); } function moveImageFile($filename) { $dt= new DateTime(); $dt->setTimestamp(filectime($filename)); $start_path = $this->config['photos']; $year = $start_path."\Year".$dt->format('Y'); if (!is_dir($year)) mkdir($year); $month = $year."\\".$dt->format('Ym-F'); if (!is_dir($month)) mkdir($month); $path = $month."\\".$dt->format('Ym-d'); if (!is_dir($path)) mkdir($path); } $full_path = getUniqueFilename($filename, $path, $dt, 0); copy($filename, $full_path); 

Es gab mehrere Probleme:

  • Einige Dateien hatten ein falsches Erstellungsdatum
  • Wenn Sie kopieren, wird bis zum aktuellen Datum eine neue Datei erstellt.
  • Dateien können Duplikate mit derselben Erstellungszeit haben

Problem Nummer 2 - Holen Sie sich das Datum von Exif


Es wurde beschlossen, das Datum aus EXIF ​​zu übernehmen, umzubenennen und nach Dateien zu suchen, um das Datum aus exif festzulegen, und Dateien mit md5 auf Duplikate zu überprüfen.

Im Prinzip hat PHP bereits eine Exif-Erweiterung im Bibliotheksset, sodass nichts ĂśbernatĂĽrliches vorgesehen war

  $dt = DateTime::createFromFormat('Y:m:d H:i:s', $exif['DateTime']); $start_path = $this->config['photos.exif']; $is_exif = true; if (md5_file($filename) == md5_file($full_path)) return false; rename($filename, $full_path); touch($full_path, $dt->getTimestamp()); 

Alles wäre in Ordnung, 500 Gigabyte Fotos wurden in ein paar Stunden sortiert und von Duplikaten befreit, aber dann erinnerte ich mich an die alten Ordner, die den Namen der Region enthielten, in der das Fotoshooting stattfand, und dachte, warum nicht die Namen von Städten aus Geodaten abrufen?

Aufgabe №3 - Länder, Städte und Regionen aus EXIF-Geodaten


Die Koordinaten sind in den Dateien leicht zu finden, sie befinden sich in Exif in GPSLongitude und GPSLatitude, aber wir dĂĽrfen nicht vergessen, dass sie dort in Grad, Minuten und Sekunden gespeichert sind. Daher mĂĽssen Sie die Funktionen verwenden, um Koordinaten in Dezimalzahlen umzuwandeln.

 function getGps($exifCoord, $hemi) { $degrees = count($exifCoord) > 0 ? $this->gps2Num($exifCoord[0]) : 0; $minutes = count($exifCoord) > 1 ? $this->gps2Num($exifCoord[1]) : 0; $seconds = count($exifCoord) > 2 ? $this->gps2Num($exifCoord[2]) : 0; $flip = ($hemi == 'W' or $hemi == 'S') ? -1 : 1; return $flip * ($degrees + $minutes / 60 + $seconds / 3600); } 

Die zweite Frage, was mit den Koordinaten zu tun ist, wie man den Namen der Stadt bekommt?
Geocoder von Yandex kommt zur Rettung, aber seien Sie vorsichtig mit den Grenzen und Nutzungsbedingungen.

 $url = "https://geocode-maps.yandex.ru/1.x/"; $apikey = require('../config/apikey.php'); $json = array( 'geocode' => $lon.",".$lat, 'kind' => 'locality', 'apikey' => $apikey, 'results' =>'1', 'skip' => '0', 'format' => 'json' ); $response = file_get_contents($url."?".http_build_query($json)); 

Um Yandex nicht mit Millionen von Abfragen zu töten, werden Daten in MySql zwischengespeichert, wobei die Koordinaten auf 3 Dezimalstellen gerundet werden, dh 43.161 - 19.182 reichen aus, um die Stadt zu bestimmen, und daher habe ich für 110.000 Fotos nur 1.500 Geometrien erhalten.

Das Erscheinungsbild der Ordner sieht ungefähr so ​​aus:

  • D: \ photos \ photos_exif \ Year2019 \ 2019-09-September \ 2019-09-23-Bosnien und Herzegowina, Republika Srpska, Foca \
  • D: \ photos \ photos_exif \ Year2019 \ 2019-08-August \ 2019-08-25-Albanien, Region Durres, Kruja \
  • D: \ photos \ photos_exif \ Year2018 \ 2018-10-October \ 2018-10-06-Russland, Region Moskau, Balashikha \

Anstelle einer Schlussfolgerung


Wenn Sie dieses Produkt verwenden, können Sie es monatelang ausführen. Ich habe einen Tag gebraucht, um ein Skript zu schreiben und die Speicherung von Fotos zu optimieren.

Aus den Plänen: Hinzufügen von Geotags zu vorhandenen Fotos, erneutes Sortieren des aktuellen Fotoarchivs und Auffinden von Duplikaten unter den abgeschnittenen Bildern.

Alle Projektdateien sind auf GitHub verfĂĽgbar

Schlagen Sie mich nicht hart, dies ist mein erstes vollständig Open-Source-Projekt. Wenn etwas falsch gepostet oder geschrieben wurde, sagen Sie es mir, und ja, jetzt ist alles für die Windows-Laufzeit mit der Codierung 1251 eingesperrt.

Source: https://habr.com/ru/post/de470009/


All Articles