JPG画像のExifから緯度経度情報を読んでマップに張り付ける。
JPG画像のExifから緯度経度情報を読んでマップに張り付けてみました。
こんな感じ
http://www.moeten.info/flex/20081204_jpg2mapbyexif/bin-release/main.html
Exifっていろいろな情報があってとっても便利です。
PHPを使用して、Exif情報を取り出すだけなので結構簡単にできます。
//Exif情報を配列へ $cls = exif_read_data($fname, 'EXIF'); foreach ($cls as $key=>$sect) { if (is_array($sect) == FALSE) { $exif[$key] = $sect; } else { foreach($sect as $name=>$val)$exif[$key . '.' . $name] = $val; } }
読み込んだ情報をFlexが扱いやすいxml形式にて表示します。
http://www.moeten.info/flex/20081204_jpg2mapbyexif/index.php
#PHPやAIRでExif情報の書き込みができればもっと便利だろうなぁ。
すべてのソースコードはこちら
Flexのソースコードはこちら
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="creationCompleteHandler(event)" backgroundGradientColors="[0xffffff,0x999999]" viewSourceURL="srcview/index.html"> <mx:Script> <![CDATA[ import com.google.maps.MapEvent; import com.google.maps.LatLng; import com.google.maps.Map; import com.google.maps.InfoWindowOptions; import com.google.maps.styles.*; import com.google.maps.interfaces.IPolyline; import com.google.maps.overlays.*; import com.google.maps.controls.*; import com.google.maps.*; import com.google.maps.services.*; [Bindable]public var myXMLDATA:XMLList; //マップ作製 private var map:Map; private function creationCompleteHandler(e:Event):void{ makeMap(); } private function makeMap():void{ map = new Map(); map.key = "ABQIAAAAq9Z1Z3_S-AQpWPqQe5Gh1RRD4wMK23XJSE0pd0Xt9l-AeMpaYxRIezvnX8EKJ4gZ1xqmuo8WFOd9LA"; myUI.addChild( map ); map.language = "JP"; map.width = myUI.width; map.height = myUI.height; map.addEventListener( MapEvent.MAP_READY, onMapReady ); } private function onMapReady(e:Event):void{ //装飾追加 var zoomControl:ZoomControl = new ZoomControl() var z:ZoomControlOptions = new ZoomControlOptions(); map.addControl(zoomControl); var pos:PositionControl = new PositionControl(); map.addControl(pos); map.enableContinuousZoom(); map.setCenter( new LatLng(34.50655662164561,134.835205078125) , 7, MapType.NORMAL_MAP_TYPE ); htsFileList.send(); } /* //画像ファイルを選択 import flash.net.FileReference; private var myFileReferenceList:FileReferenceList; private function fileSelect():void{ myFileReferenceList = new FileReferenceList(); myFileReferenceList.browse( new Array( new FileFilter("Images (*.jpg,*.jpeg)", "*.jpg;*.jpeg") ) ); myFileReferenceList.addEventListener(Event.SELECT , selectHandler ); } private var urlRequest:URLRequest; private function selectHandler(e:Event):void{ var urlVariables:URLVariables = new URLVariables(); urlVariables.imgMaxWidth = 100; urlVariables.imgMaxHeight = 200; urlRequest = new URLRequest(); urlRequest.url = "http://moeten.info/flex/20081204_jpg2mapbyexif/?mode=fileupload"; urlRequest.method = URLRequestMethod.POST; urlRequest.data = urlVariables; for (var i:int = 0; i < myFileReferenceList.fileList.length ; i++ ){ var fileReference:FileReference = new FileReference(); fileReference = FileReference( myFileReferenceList.fileList[i] ); fileReference.addEventListener( DataEvent.UPLOAD_COMPLETE_DATA, onUploadCompleteData ); fileReference.upload( urlRequest ); } } private function onUploadCompleteData(e:Event):void{ } */ private var markerArr:Array = new Array(); private function onHtsFileListResultHandler(e:Event):void{ myXMLDATA = htsFileList.lastResult.item; for( var i:int = 0 ; i < myXMLDATA.length() ; i ++ ){ if( myXMLDATA[i].lat != "" && myXMLDATA[i].lng != "" ){ if(markerArr[myXMLDATA[i].id])return; var loader:Loader = new Loader(); loader.name = "" + i + "-" + myXMLDATA[i].id; loader.contentLoaderInfo.addEventListener(Event.COMPLETE , function(e:Event):void{ var myBitmap:Bitmap = Bitmap(LoaderInfo(e.currentTarget).content); myBitmap.width = 40; myBitmap.height = 40; myBitmap.filters = [gf]; var myI:int = int( String( LoaderInfo(e.currentTarget).loader.name ).split("-")[0]); var myId:int = int( String( LoaderInfo(e.currentTarget).loader.name ).split("-")[1]); var marker:Marker = new Marker( new LatLng( myXMLDATA[myI].lat , myXMLDATA[myI].lng ) , new MarkerOptions({ draggable :true, icon:myBitmap, iconAlignment: MarkerOptions.ALIGN_HORIZONTAL_CENTER, hasShadow:true }) ); markerArr[myId] = marker; map.addOverlay(marker); }); loader.load( new URLRequest( myXMLDATA[i].image ) ); } } } private function onItemSelected(e:Event):void{ map.panTo( new LatLng( dg.selectedItem.lat , dg.selectedItem.lng ) ); } ]]> </mx:Script> <!--############ ############--> <mx:GlowFilter id="gf" color="0xffffff" blurX="4" blurY="4" strength="10"/> <!--############ ############--> <mx:HTTPService id="htsFileList" url="http://www.moeten.info/flex/20081204_jpg2mapbyexif/index.php" resultFormat="e4x" result="onHtsFileListResultHandler(event)"/> <!--############ ############--> <mx:UIComponent id="myUI" width="507" height="533" x="10" y="66"/> <mx:DataGrid id="dg" x="525" y="66" width="310" height="533" dataProvider="{htsFileList.lastResult.item}" backgroundAlpha="0.5" itemClick="onItemSelected(event)"> <mx:columns> <mx:DataGridColumn headerText="画像"> <mx:itemRenderer> <mx:Component> <mx:Image width="50" height="50" source="{data.image}"/> </mx:Component> </mx:itemRenderer> </mx:DataGridColumn> <mx:DataGridColumn headerText="撮影日" dataField="date"/> <mx:DataGridColumn headerText="緯度" dataField="lat"/> <mx:DataGridColumn headerText="経度" dataField="lng"/> </mx:columns> </mx:DataGrid> <mx:Label x="10" y="10" text="Exif2Map" color="0x999999" fontSize="30"/> <mx:HRule x="10" y="52" width="825" height="8"/> </mx:Application>
<?php $CodeInternal = 'SJIS';//内部処理コード $CodeExport = 'SJIS';//出力コード mb_internal_encoding($CodeInternal); mb_regex_encoding($CodeInternal); function d() { echo '<pre style="background:#fff;color:#333;border:1px solid #ccc;margin:2px;padding:4px;font-family:monospace;font-size:12px">'; foreach (func_get_args() as $v) var_dump($v); echo '</pre>'; } function getexif($fname, &$exif) { //ファイルの存在チェック if (file_exists($fname) == FALSE) return (-1); //JPEG/TIFFの型チェック switch (exif_imagetype($fname)) { case IMAGETYPE_JPEG: case IMAGETYPE_TIFF_II: case IMAGETYPE_TIFF_MM: break; default: return (-2); } //Exif情報を配列へ if (($cls = exif_read_data($fname, 'EXIF')) == FALSE) return (-3); foreach ($cls as $key=>$sect) { if (is_array($sect) == FALSE) { $exif[$key] = $sect; } else { foreach($sect as $name=>$val) $exif[$key . '.' . $name] = $val; } } return 0; } //度分秒表記を角度に変換 function dms2degree( $pos_n , $pos_e ){ $posN_a = explode( "." , $pos_n ); $posE_a = explode( "." , $pos_e ); //$posN_a[2] = $posN_a[2] . "." .$posN_a[3]; //$posE_a[2] = $posE_a[2] . "." .$posE_a[3]; $posN = $posN_a[0] + $posN_a[1]/60 + $posN_a[2]/3600;//北緯 $posE = $posE_a[0] + $posE_a[1]/60 + $posE_a[2]/3600;//東経 $gps['lat'] = $posN; $gps['lng'] = $posE; return $gps; } //Exif情報を配列へ $xml = <<<EOD <result> EOD; $cnt = 0; $dir = dir( "image" ); while( $list = $dir->read() ){ if( $list != "." && $list != ".." ){ $fname = "image/{$list}"; if (($cls = exif_read_data($fname, 'EXIF')) == FALSE) return (-3); foreach ($cls as $key=>$sect) { if (is_array($sect) == FALSE) { $exif[$key] = $sect; } else { foreach($sect as $name=>$val){ $exif[$key . '.' . $name] = $val; } } } $date = $exif["DateTimeOriginal"]; $lat_a0 = explode( "/" , $exif['GPSLatitude.0'] ); $lat_a1 = explode( "/" , $exif['GPSLatitude.1'] ); $lat_a2 = explode( "/" , $exif['GPSLatitude.2'] ); $lat_a2[0] = $lat_a2[0]/100; $pos_n = "{$lat_a0[0]}.{$lat_a1[0]}.{$lat_a2[0]}"; $lng_a0 = explode( "/" , $exif['GPSLongitude.0'] ); $lng_a1 = explode( "/" , $exif['GPSLongitude.1'] ); $lng_a2 = explode( "/" , $exif['GPSLongitude.2'] ); $lng_a2[0] = $lng_a2[0]/100; $pos_e = "{$lng_a0[0]}.{$lng_a1[0]}.{$lng_a2[0]}"; $gps = dms2degree($pos_n,$pos_e); //d( $exif ); $xml .= <<<EOD <item> <id>{$cnt}</id> <image>http://www.moeten.info/flex/20081204_jpg2mapbyexif/image/{$list}</image> <lat>{$gps['lat']}</lat> <lng>{$gps['lng']}</lng> <date>{$date}</date> <timestamp>{$exif['FileDateTime']}</timestamp> </item> EOD; $cnt ++; } } $xml .= <<<EOD </result> EOD; header ("Content-Type: text/xml; charset=UTF-8"); echo $xml; exit; ?>