WinRT APIを使って画像ファイルの位置情報を編集する

WinRT APIには、画像ファイルの位置情報を取り出すAPIが用意されています。 位置情報を取り出すのはとても簡単で、imageFileをStorageFile型のオブジェクトとすると、         var imageProps = await imageFile.Properties.GetImagePropertiesAsync(); で、imagePropsのLatitude、Longitudeから緯度、経度を取得可能です。この二つのプロパティの型は、double?で、Nulable型になっています。画像ファイルに位置情報が付与されていない場合には、この二つの値はnullです。加えて、この二つのプロパティは、Readonlyで書き換えができません。Windows Phoneデバイスのカメラでは、位置情報を付与してJPEGファイルとして保存することができますが、多分、位置情報付きの画像ファイルはそれほど多くはないのではないかと思われます。位置情報が付与されているのであれば、既にストアから公開(http://apps.microsoft.com/windows/app/f7f0662c-ba9d-4bb3-a6d5-a1559c970aeb )されている、”どこの写真”アプリの様に、 と、写真を地図上に撮った位置にマップして表示する事ができたりするので、色々と便利なんですね。画像ファイルのデータをバイナリレベルで色々と弄れば位置情報を編集するのは可能なのですが、WinRT APIで変更する方法はないかな…と探していたところ、やり方がForum上で公開されているのを見つけました。情報元はこちら。 http://social.msdn.microsoft.com/Forums/nl/winappswithcsharp/thread/aaf0b373-b0e0-4d91-84d8-69e768a374d8 LatitudeとLongitudeを、そのまま保持しているのではなく、別の形式のデータから計算して取得しているので直接はかえられないみたいですね。内部の形式は、上のURLからたどって調べてもらうとして、以下に画像ファイルの位置情報を編集するコードの例を挙げておきますね。     class LocationHelper    {        public static async Task<ImageProperties> AddLocation(StorageFile imageFile, double latitude, double longitude)        {            int[] denomitor = new int[3] { 1, 1, 1000 };            string latitudeRef = “N”;            if (latitude < 0)            {                latitudeRef = “S”;                latitude *= -1;           …

0

Windows Phone 7.1 Locationの使い方

Location、Location…過去のブログのポストを見ていたら、まとまって説明しているものが無いので、改めて通して紹介します。D1-401のセミナーでも紹介したことだし。 地図やナビゲーション、自分の周辺に関わる何かを扱うアプリケーションでは、位置情報取得は必須です。Windows Phone 7.1にはSystem.Device.Locaiton名前空間に、GeoCoordinateWatcherクラスが用意されていて、デバイスの現在位置の取得が可能です。位置情報というとGPS?って思う人も沢山いらっしゃるでしょう。しかしこのクラス名にはGPSのジの字もありませんね。位置情報は、GPSで取得できるだけでなく、携帯基地局やWifiのルーター等、色々なソースから取得が可能です。純粋に位置情報を取得することを考えると、GPSは位置を取得するための単なる手段であることに気がつくでしょう。 Windows Phoneの位置情報取得機能は、GPSやその他の位置情報取得をひっくるめて位置情報を提供するように作られています。と、能書きはこれぐらいにして、早速使い方を説明していきます。 先ずは、プロジェクトの参照設定に、System.Deviceコンポーネントを追加します。 プログラムの適切な場所に、 using System.Device; を書いておきます。http://blogs.msdn.com/b/hirosho/archive/2011/10/11/windowsphone71sensorprogramingbasis.aspx で説明したセンサーと処理の流れは似ています。同期的な位置情報取得と非同期的な位置情報取得方法をTPOに合わせて選択可能です。 先ずは、同期的な処理から。 var watcher = new GeoCoordinateWatcher(GeoPosiitonAccuracy.Default);watcher.Start();var position = watcher.Position;watcher.Stop(); 基本はこれだけ。ただし、watcherのStartメソッドをコールしてから、位置情報が取れるまでは初期化や情報収集などで時間がかかる場合があるので、実際にはStatusプロパティがReadyになるまで待つ必要はあります。Positionは、Locationというプロパティが用意されていて、その中にLatitude(緯度)、Longitude(経度)が格納されています。他にもいくつかプロパティは用意されているのですが、まx、Altitudeという高度を示すプロパティだけあると、このポストでは行っておくことにします。 さて、非同期処理はといえば、センサーの時と同様、GeoCoordinateWatcherのインスタンスはクラスのメンバー変数として定義しておきます。 private GeoCoordinateWatcher watcher; 初期化フェーズの時に、インスタンスを作成し、位置情報が更新した時にコールされるハンドラーを登録します。 watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.Default);watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);watcher.PositionChanged += new EventHandler<GeoPositionChanged<GeoCoordinate>>(watcher_PositionChanged); そして、いよいよ位置情報が必要になるタイミングで、 watcher.Start(); をコールして、位置取得処理を開始します。すると、watcherは、”Initializing”→”Ready”に状態変更(watcher_StatusChangedがコールされ、引数でStatusが渡される)しつつ、”Ready”になって位置情報が取得できたら、watcher_PositionChangedがコールされます。ハンドラーのコードは以下のようになります。 private void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e){    Deployment.Current.Dispatcher.BeginInvoke(() =>    {        var timestamp = e.Position.Timestamp;        var location =…

0

TF Seminor 4/15 Windows Phone7 Deep Dive フォロー – その2

4/15に開催したDeep Diveセミナー、もう直ぐ資料公開(ってプロジェクターにつながらなかったので、お初なんですが・・・)の予定ですが、BingMapのセンター位置を変更するコードが間違っていたので、投稿しておきます。公開資料は修正しときます。 GeoCoordinateWatcherオブジェクトのPositionChangedイベントに登録したハンドラのコードは、これも別スレッドなので private delegate void UpdatePositionOnMapHandler(    GeoPositionChangedEventArgs<GeoCoordinate> e); void locationWatcher_PositionChanged(    object sender, GeoPositionChangedEventArgs<GeoCoordinate> e){    this.Dispatcher.BeginInvoke(        new UpdatePositionOnMapHandler(UpdatePositionOnMap),        new object[] { e });} として、UIのDispatcherキューに入れ、 private void UpdatePositionOnMap(    GeoPositionChangedEventArgs<GeoCoordinate> e){    var position = new GeoCoordinate(        e.Position.Location.Latitude,        e.Position.Location.Longitude);    map1.SetView(position, 10); } というコードを書けば、位置が更新されたときに、受け取った緯度、経度が中心に表示されるようになります。配布資料の様にCenterプロパティの更新では、表示は変わりません。 以上、参考になれば幸いです。

0