Sortir foto berdasarkan data dari EXIF ​​+ PHP

Saya ingin berbagi pengalaman dalam menyortir foto menggunakan skrip dalam PHP
Ada saatnya ketika tidak ada banyak foto, tetapi serempak banyak.

Latar belakang


Suatu hari saya memutuskan untuk menyortir seluruh arsip foto digital saya, terakumulasi selama 20 tahun, dan menyadari bahwa sepanjang waktu saya telah mengumpulkan 112.000 foto pada 435 gigabytes.

Selain itu, beberapa di antaranya kurang lebih diurutkan, misalnya, foto dari kamera SLR, berdasarkan folder dengan nama dan tanggal, sedangkan bagian lain dari foto yang diimpor dari iphone / android tidak bernama dan disortir, seringkali hanya berupa folder raksasa 10 gigabyte, dengan beberapa ribu file di dalamnya, dan sangat disayangkan untuk menghapus dan mengatasinya.

Saya mulai mencari alat penyortiran otomatis dan menyadari bahwa semua layanan yang baik, seperti Picasa, sudah dibeli dan ditutup oleh Google, tentu saja Anda dapat mengunggah semuanya ke Google. Foto, bagaimanapun, ada masalah di sana, tidak semua dicari dan umumnya setengah dari fungsi hilang dari berada di Picasa, dan jika Anda masih khawatir foto Anda akan dikenali dan digunakan, mengunggah ke web bukanlah cara Anda sama sekali.

Akibatnya, diputuskan untuk menulis skrip kecil yang akan mengurutkan semuanya, pada awalnya saya memikirkan skrip shell, tetapi menyadari bahwa saya akan membutuhkannya, EXIF ​​memutuskan untuk kembali ke PHP lama yang bagus.

Tugas No. 1 - Perluas semua file berdasarkan tanggal


Pertama, saya pergi dengan cara paling sederhana, mengambil semua file, melihat tanggal pembuatan dan menyebar di sepanjang jalan bersarang:

$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); 

Ada beberapa masalah:

  • Beberapa file memiliki tanggal pembuatan yang salah
  • Jika Anda menyalin, file baru dibuat oleh tanggal saat ini.
  • File dapat memiliki duplikat dengan waktu pembuatan yang sama

Masalah nomor 2 - Dapatkan tanggal dari Exif


Diputuskan untuk mengambil tanggal dari EXIF, mengganti nama dan menyentuh file untuk mengatur tanggal dari exif, dan juga memeriksa file untuk duplikat menggunakan md5.

Pada prinsipnya, PHP sudah memiliki ekstensi exif di set perpustakaan, jadi tidak ada yang supernatural yang diramalkan

  $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()); 

Semuanya akan baik-baik saja, 500 gigabyte foto disortir dan dibersihkan dari duplikat dalam beberapa jam, tetapi kemudian saya ingat folder lama yang berisi nama daerah tempat pemotretan diadakan, dan berpikir, mengapa tidak mendapatkan nama kota dari geodata?

Tugas β„–3 - Negara, kota, dan wilayah dari geodata EXIF


Koordinat mudah ditemukan dalam file, mereka berada di Exif di GPSLongitude dan GPSLatitude, tetapi kita tidak boleh lupa bahwa mereka disimpan di sana dalam derajat, menit dan detik, jadi Anda perlu menggunakan fungsi untuk mengubah koordinat menjadi desimal.

 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); } 

Pertanyaan kedua, apa yang harus dilakukan dengan koordinat, bagaimana cara mendapatkan nama kota?
Geocoder dari Yandex datang untuk menyelamatkan, tetapi berhati-hatilah dengan batasan dan ketentuan penggunaan.

 $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)); 

Agar tidak membunuh Yandex dengan jutaan kueri, kami menyimpan data dalam MySql, membulatkan koordinat ke 3 tempat desimal, yaitu, 43,161 - 19,182 sudah cukup untuk menentukan kota, dan untuk 110.000 foto, saya hanya mendapatkan 1.500 geometri.

Tampilan foldernya kira-kira seperti ini:

  • D: \ photos \ photos_exif \ Year2019 \ 2019-09-September \ 2019-09-23-Bosnia dan Herzegovina, Republika Srpska, Foca \
  • D: \ photos \ photos_exif \ Year2019 \ 2019-08-Agustus \ 2019-08-25-Albania, wilayah Durres, Kruja \
  • D: \ photos \ photos_exif \ Year2018 \ 2018-10-Oktober \ 2018-10-06-Rusia, Wilayah Moskow, Balashikha \

Alih-alih sebuah kesimpulan


Bahkan, jika Anda mengambil produk ini, Anda dapat melakukannya selama berbulan-bulan, saya butuh waktu sehari untuk menulis naskah dan mengoptimalkan penyimpanan foto.

Dari rencana: menambahkan geotag ke foto yang ada, mengurutkan ulang arsip foto saat ini, menemukan duplikat di antara gambar yang terpotong.

Semua file proyek tersedia di GitHub

Jangan memukul saya dengan keras, ini adalah proyek open source pertama saya, jika ada sesuatu yang diposting atau ditulis secara tidak benar, katakan padaku, dan sekarang semuanya dipenjara karena lingkungan runtime Windows dengan pengkodean 1251.

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


All Articles