目次
サンプル・プログラムの実行例
サンプル・プログラム
photomap.php | サンプル・プログラム本体 |
pahooGeoCode.php | 住所・緯度・経度に関わるクラス pahooGeoCode。 使い方は「PHPで住所・ランドマークから最寄り駅を求める」「PHPで住所・ランドマークから緯度・経度を求める」などを参照。include_path が通ったディレクトリに配置すること。 |
準備:GDライブラリ
準備:pahooGeoCode クラス
  37: class pahooGeoCode {
  38: var $items; //検索結果格納用
  39: var $error; //エラー・フラグ
  40: var $errmsg; //エラー・メッセージ
  41: var $hits; //検索ヒット件数
  42: var $webapi; //直前に呼び出したWebAPI URL
  43:
  44: //Google Cloud Platform APIキー
  45: //https://cloud.google.com/maps-platform/
  46: //※Google Maps APIを利用しないのなら登録不要
  47: var $GOOGLE_API_KEY_1 = '**************************'; //HTTPリファラ用
  48: var $GOOGLE_API_KEY_2 = '**************************'; //IP制限用
  49:
  50: //Yahoo! JAPAN Webサービス アプリケーションID
  51: //https://e.developer.yahoo.co.jp/register
  52: //※Yahoo! JAPAN Webサービスを利用しないのなら登録不要
  53: var $YAHOO_APPLICATION_ID = '*****************************';
クラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。
地図や住所検索として Google を利用するのであれば、Google Cloud Platform APIキー が必要で、その入手方法は「Google Cloud Platform - WebAPIの登録方法」を、Yahoo!JAPAN を利用するのであれば、Yahoo! JAPAN Webサービス アプリケーションIDが必要で、その入手方法は「Yahoo!JAPAN デベロッパーネットワーク - WebAPIの登録方法」を、それぞれ参照されたい。
準備:地図サービス(WebAPI)の選択
  34: //地図描画サービスの選択
  35: // 0:Google
  36: // 2:地理院地図・OSM
  37: define('MAPSERVICE', 2);
  38:
  39: //逆ジオコーディングサービスの選択
  40: // 0:Google
  41: // 1:Yahoo!JAPAN
  42: // 11:HeartRails Geo API
  43: // 21:簡易ジオコーディングサービス
  44: define('REVGEOSERVICE', 21);
逆ジオコーディングサービスは、Google、Yahoo!JAPAN、HeartRails Geo API、簡易ジオコーディングサービスから選べる。あらかじめ、定数 REVGEOSERVICE に値を設定すること。
解説:初期設定
  46: //マップの表示サイズ(単位:ピクセル)
  47: define('MAP_WIDTH', 600);
  48: define('MAP_HEIGHT', 400);
  49: //マップID
  50: define('MAPID', 'map_id');
  51: //初期値
  52: define('DEF_LATITUDE', 35.4658); //緯度
  53: define('DEF_LONGITUDE', 139.6223); //経度
  54: define('DEF_TYPE', 'roadmap'); //マップタイプ
  55: define('DEF_ZOOM', 13); //ズーム
解説:Exif情報から緯度・経度を取り出す
 320: /**
 321: * Exif情報から緯度・経度を取り出す
 322: * @param array $exif Exif情報
 323: * @return list(緯度,経度)/(FALSE,FALSE):取得失敗
 324: */
 325: function exif2location($exif) {
 326: $pat = "/([0-9]+)\/([0-9]+)/ui";
 327:
 328: //Exif情報に緯度・経度があるかどうか
 329: if (! isset($exif['GPSLatitude.0']) || ! isset($exif['GPSLongitude.0'])) {
 330: return array(FALSE, FALSE);
 331: }
 332:
 333: //緯度の計算
 334: $latitude = 0;
 335: for ($i = 0; $i < 5; $i++) {
 336: $key = 'GPSLatitude.' . (string)$i;
 337: if (isset($exif[$key])) {
 338: if (preg_match($pat, $exif[$key], $arr) > 0) {
 339: $latitude += (float)$arr[1] / (float)$arr[2] / pow(60, $i);
 340: }
 341: }
 342: }
 343: //北緯・南緯の計算
 344: if (isset($exif['GPSLatitudeRef'])) {
 345: if (! preg_match('/N/ui', $exif['GPSLatitudeRef']) > 0) {
 346: $latitude = 0 - $latitude;
 347: }
 348: }
 349:
 350: //経度の計算
 351: $longitude = 0;
 352: for ($i = 0; $i < 5; $i++) {
 353: $key = 'GPSLongitude.' . (string)$i;
 354: if (isset($exif[$key])) {
 355: if (preg_match($pat, $exif[$key], $arr) > 0) {
 356: $longitude += (float)$arr[1] / (float)$arr[2] / pow(60, $i);
 357: }
 358: }
 359: }
 360: //東経・西経の計算
 361: if (isset($exif['GPSLongitudeRef'])) {
 362: if (! preg_match('/E/ui', $exif['GPSLongitudeRef']) > 0) {
 363: $longitude = 0 - $longitude;
 364: }
 365: }
 366:
 367: return array($latitude, $longitude);
 368: }
取得したExif情報(配列)から、マッピングしやすいように緯度・経度情報を取り出すユーザー関数が exif2location である。
解説:画像情報の一部をTABLE化する
 454: /**
 455: * 画像情報の一部をTABLE化する
 456: * @param object $pgc pahooGeoCodeクラス
 457: * @param array $exif Exif情報
 458: * @param array $items 画像ファイル情報
 459: * @return string HTMLタグ
 460: */
 461: function makeInfoTable($pgc, $exif, $items) {
 462: $table = array(
 463: //画像形式 => 読み込み関数
 464: IMAGETYPE_BMP => 'BMP',
 465: IMAGETYPE_GIF => 'GIF',
 466: IMAGETYPE_JPEG => 'JPEG',
 467: IMAGETYPE_PNG => 'PNG',
 468: IMAGETYPE_WEBP => 'WEBP'
 469: );
 470:
 471: $html =<<< EOT
 472: <table class="exiflist">
 473:
 474: EOT;
 475:
 476: //撮影日時
 477: $dt = getExifData('DateTimeOriginal', $exif);
 478: if ($dt == FALSE) {
 479: $dt = '(不明)';
 480: } else {
 481: $dt = preg_replace('/([0-9]+)[\:\-\/]([0-9]+)[\:\-\/]([0-9]+) ([0-9\:\-\/]+)/ui', '$1-$2-$3 $4', $dt);
 482: }
 483:
 484: //緯度・軽度
 485: list($latitude, $longitude) = exif2location($exif);
 486: if (($latitude != FALSE) && ($longitude != FALSE)) {
 487: $latitudeRef = ($latitude >= 0) ? '北緯' : '南緯';
 488: $longitudeRef = ($longitude >= 0) ? '東経' : '西経';
 489: $latitudeStr = $latitudeRef . substr(deg2hexadec($latitude), 1);
 490: $longitudeStr = $longitudeRef . substr(deg2hexadec($longitude), 1);
 491: //住所
 492: $address = (($arr = $pgc->getAddress3($latitude, $longitude, REVGEOSERVICE)) == FALSE) ? '' : $arr['address'];
 493: } else {
 494: $latitudeStr = '(不明)';
 495: $latitude = '---';
 496: $longitudeStr = '(不明)';
 497: $longitude = '---';
 498: $address = '(不明)';
 499: }
 500:
 501: //画像形式
 502: $imagetype = '';
 503: if (isset($items['imagetype'])) {
 504: foreach ($table as $key=>$val) {
 505: if ($key == $items['imagetype']) {
 506: $imagetype = $val;
 507: break;
 508: }
 509: }
 510: }
 511: //画像幅
 512: $width = '';
 513: if (isset($items['width'])) {
 514: $width = $items['width'];
 515: }
 516: //画像高さ
 517: $height = '';
 518: if (isset($items['height'])) {
 519: $height = $items['height'];
 520: }
 521:
 522: $html .=<<< EOT
 523: <tr>
 524: <td>緯度</td>
 525: <td>{$latitudeStr}<br />({$latitude})</td>
 526: </tr>
 527: <tr>
 528: <td>経度</td>
 529: <td>{$longitudeStr}<br />({$longitude})</td>
 530: </tr>
 531: <tr>
 532: <td>住所</td>
 533: <td>{$address}</td>
 534: </tr>
 535: <tr>
 536: <td>撮影日時</td>
 537: <td>{$dt}</td>
 538: </tr>
 539: <tr>
 540: <td>画像形式</td>
 541: <td>{$imagetype}</td>
 542: </tr>
 543: <tr>
 544: <td>画像サイズ</td>
 545: <td>{$width}×{$height}ピクセル</td>
 546: </tr>
 547:
 548: EOT;
 549: $html .=<<< EOT
 550: </table>
 551:
 552: EOT;
 553: return $html;
 554: }
緯度・経度から住所を求める仕組みは、「PHPで緯度・経度から住所を求める」をご覧いただきたい。
解説:ファイルのドロップ
  73: <script>
  74: /**
  75: * ファイルのドロップ
  76: * @param evt イベント
  77: * @return なし
  78: */
  79: function handleFileSelect(evt) {
  80: evt.stopPropagation();
  81: evt.preventDefault();
  82:
  83: var files = evt.dataTransfer.files;
  84: var output = [];
  85:
  86: document.getElementById('upload').files = files;
  87: document.myform.submit();
  88: }
  89:
  90: function handleDragOver(evt) {
  91: evt.stopPropagation();
  92: evt.preventDefault();
  93: evt.dataTransfer.dropEffect = 'copy';
  94: }
  95:
  96: function PageLoad(evt) {
  97: var dropFrame = document.getElementById('DropFrame');
  98: dropFrame.addEventListener('dragover', handleDragOver, false);
  99: dropFrame.addEventListener('drop', handleFileSelect, false);
 100: }
 101: </script>
ファイルをドラッグする処理は、JavaScriptによって実現している。
ドラッグする場所はオブジェクトとして用意し、そのID名をあらかじめ変数 dropFrame に代入しておく。
関数 PageLoad は bodyタグをonLoadするときに実行すること。
参考サイト
- PHPでExif情報を表示する:ぱふぅ家のホームページ
- PHPで画像ファイルを読み込んでimgタグに埋め込む:ぱふぅ家のホームページ
- PHPでマップを利用して緯度・経度や住所を求める:ぱふぅ家のホームページ
- PHPで緯度・経度から住所を求める:ぱふぅ家のホームページ
- C++ で撮影場所をマッピング:ぱふぅ家のホームページ