目次
サンプル・プログラムの実行例
サンプル・プログラム
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)の選択
逆ジオコーディングサービスは、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++ で撮影場所をマッピング:ぱふぅ家のホームページ