スマホなどで撮影した写真などのExifにはGPSデータが含まれています。このGPSデータは、色々なことに利用することが出来ます。
今回はPHPを利用して、画像ファイルから位置情報を緯度経度に変換する方法について紹介します。
Contents
exif_read_data()関数の利用
画像ファイルのExifデータを取得するには、exif_read_data()という関数を利用します。
この関数を利用すると、画像に関する様々な情報を得ることが出来ます。
実際にexif_read_data()関数を使用して取得した内容を出力すると下記のような情報を得ることが出来ます。
exif_read_data()を取得するPHPスクリプト
// 画像ファイルのパス $img = './photo.jpg'; // Exifを取得し、[$exif]に代入する $exif = @exif_read_data( $img ); echo '<pre>'; // 取得したデータを出力する var_dump( $exif ); echo '</pre>' ;
exif_read_data()で取得できる内容
exif_read_data()関数を使用すると配列で画像の情報を取得することができるのが分かります。
{ ["FileName"]=> string(9) "photo.jpg" ["FileDateTime"]=> int(1550307176) ["FileSize"]=> int(70074) ["FileType"]=> int(2) ["MimeType"]=> string(10) "image/jpeg" ["SectionsFound"]=> string(44) "ANY_TAG, IFD0, THUMBNAIL, EXIF, GPS, INTEROP" ["COMPUTED"]=> array(7) { ["html"]=> string(24) "width="624" height="468"" ["Height"]=> int(468) ["Width"]=> int(624) ["IsColor"]=> int(1) ["ByteOrderMotorola"]=> int(1) ["Thumbnail.FileType"]=> int(2) ["Thumbnail.MimeType"]=> string(10) "image/jpeg" } ["Make"]=> string(3) "HTC" ["Model"]=> string(5) "X04HT" ["Orientation"]=> int(1) ["XResolution"]=> string(4) "72/1" ["YResolution"]=> string(4) "72/1" ["ResolutionUnit"]=> int(2) ["Software"]=> string(13) "6_00_32008_00" ["DateTime"]=> string(19) "2009:03:20 12:34:00" ["YCbCrPositioning"]=> int(1) ["Exif_IFD_Pointer"]=> int(246) ["GPS_IFD_Pointer"]=> int(570) ["THUMBNAIL"]=> array(6) { ["Compression"]=> int(6) ["XResolution"]=> string(4) "72/1" ["YResolution"]=> string(4) "72/1" ["ResolutionUnit"]=> int(2) ["JPEGInterchangeFormat"]=> int(988) ["JPEGInterchangeFormatLength"]=> int(6876) } ["ISOSpeedRatings"]=> int(0) ["ExposureBiasValue"]=> string(3) "0/1" ["ExifVersion"]=> string(4) "0220" ["DateTimeOriginal"]=> string(19) "2009:03:20 12:34:00" ["DateTimeDigitized"]=> string(19) "2009:03:20 12:34:00" ["ComponentsConfiguration"]=> string(4) "" ["Flash"]=> int(0) ["FlashPixVersion"]=> string(4) "0100" ["ColorSpace"]=> int(1) ["ExifImageWidth"]=> int(2048) ["ExifImageLength"]=> int(1536) ["InteroperabilityOffset"]=> int(540) ["FileSource"]=> string(1) "" ["SceneType"]=> string(1) "" ["WhiteBalance"]=> int(0) ["GPSVersion"]=> string(4) "" ["GPSLatitudeRef"]=> string(1) "N" ["GPSLatitude"]=> array(3) { [0]=> string(4) "35/1" [1]=> string(4) "37/1" [2]=> string(8) "1356/100" } ["GPSLongitudeRef"]=> string(1) "E" ["GPSLongitude"]=> array(3) { [0]=> string(5) "139/1" [1]=> string(4) "46/1" [2]=> string(8) "4058/100" } ["GPSAltitudeRef"]=> string(1) "" ["GPSAltitude"]=> string(3) "0/1" ["GPSTimeStamp"]=> array(3) { [0]=> string(3) "3/1" [1]=> string(4) "33/1" [2]=> string(4) "58/1" } ["GPSMapDatum"]=> string(6) "WGS-84" ["GPSProcessingMode"]=> string(18) "ASCIIHYBRID-FIX" ["GPSDateStamp"]=> string(11) "2009:03:20 " ["InterOperabilityIndex"]=> string(3) "R98" ["InterOperabilityVersion"]=> string(4) "0100" }
緯度経度を求めるために利用する要素
画像情報の要素から緯度経度を求めるために必要な要素は次の4つです。
GPSLatitudeRef、GPSLatitude、GPSLongitudeRef、GPSLongitude。
それぞれ次のような意味があります。
要素 | 意味 |
---|---|
GPSLatitudeRef | 北緯 or 南緯。Nなら北緯。Sなら南緯 |
GPSLatitude | 60進数の緯度。第1〜3要素まで、順に「度」「分」「秒」を表す。 |
GPSLongitudeRef | 東経 or 西経。Eなら東経。Wなら西経 |
GPSLongitude | 60進数の経度。第1〜3要素まで、順に「度」「分」「秒」を表す。 |
50進数を10進数に変換する
exif_read_data() では GPSLatitude, GPSLongitude の値はGoogleMaps等で使われる10進数ではなく、度分秒が分数の値で配列に格納されて返されます。
これを10進数形式に変換するには、度分秒それぞれの値を数値に変換した後、下記の式で求めることが出来ます。
更に、GPSLatitudeRef (北緯 or 南緯), GPSLongitudeRef (東経 or 西経) ヘッダの値を見て、南緯/西経の場合は負の値にします。
これをPHPスクリプトで求めると下記のようなスクリプトで、緯度経度を求めることが出来ます。
緯度経度に変換するPHPスクリプト
$exif = exif_read_data($filename); $lon = getGps($exif["GPSLongitude"], $exif['GPSLongitudeRef']); $lat = getGps($exif["GPSLatitude"], $exif['GPSLatitudeRef']); var_dump($lat, $lon); function getGps($exifCoord, $hemi) { $degrees = count($exifCoord) > 0 ? gps2Num($exifCoord[0]) : 0; $minutes = count($exifCoord) > 1 ? gps2Num($exifCoord[1]) : 0; $seconds = count($exifCoord) > 2 ? gps2Num($exifCoord[2]) : 0; $flip = ($hemi == 'W' or $hemi == 'S') ? -1 : 1; return $flip * ($degrees + $minutes / 60 + $seconds / 3600); } function gps2Num($coordPart) { $parts = explode('/', $coordPart); if (count($parts) <= 0) return 0; if (count($parts) == 1) return $parts[0]; return floatval($parts[0]) / floatval($parts[1]); }
まとめ
画像をEXIF情報を利用して、緯度経度を求める機会というのは意外とあると思います。Google Maps APIと合わせて利用したり意外と利用機会というのはあるのではないでしょうか。
そのような際、ぜひ、参考になると幸いです。
[参考]PHP extract GPS EXIF data
[参考]画像ファイルのEXIFタグから撮影日時と位置情報を取得する際のTips