WPF で Google Map & GeoTag その 4
WPF で Google Maps API & GeoTag を扱うシリーズその 4。
前回から住所情報の IPTC 書き込み (撮影場所、撮影国・都市・町) を継続していたところ、なんとか成功。サンプルと XnView では正しく読めている。しかし ViewNX で読み込むと文字化けして読めない。さすがにこれは解決したいので調査は継続する。
今回のテーマはBitmapMetadata を使用した、緯度・経度の正しい読み書きである。
GPSLatitudeRef、GPSLongitudeRef
前回までのサンプルでは緯度・経度の保存が不完全だった。
緯度・経度の座標は書き込まれるけれど GPSLatitudeRef
と GPSLongitudeRef
の書き込みは失敗。そのため座標としては中途半端な状態になっていた。これらは北緯・南緯と東経・西経を表しており、緯度・経度の符号を決める為に必須となる。
過去記事のサンプルプログラムは本件の問題を修正したものに差し替えたので、既にダウンロードされた方は再ダウンロードして下さい。
これまで BitmapMetadata
用のクエリ文字列を以下のように定義していた。
/// <summary>
/// EXIF の GPS 情報における「緯度の進行方向 ( "N" または "S" )」を示すパス文字列。
/// </summary>
private const string ExifPathGpsLatitudeDirection = "/app1/ifd/gps/subifd:{char=1}";
/// <summary>
/// EXIF の GPS 情報における「経度の進行方向 ( "E" または "W" )」を示すパス文字列。
/// </summary>
private const string ExifPathGpsLongitudeDirection = "/app1/ifd/gps/subifd:{char=3}";
これは BitmapMetadata.GetQuery
なら問題ないが SetQuery
に失敗する。SetQuery
は不正なクエリ文字列が指定された場合に例外を送出するはず。しかし実際はなぜか空振りするだけなので正常に処理されたと勘違いしていた。
正しいクエリ文字列
以下の資料を見ると、GPSLatitudeRef、GPSLongitudeRef の型は ASCII が 2 つとなっている。
- Garbage in, garbage out
- TIFF Tag Reference, GPS Tags
これまでのクエリ文字列ではデータ型を char で指定していたが、これでは ASCII が 1 つ分となりデータ量が半分になってしまう。そのためクエリ文字列のサイズを修正。
/// <summary>
/// EXIF の GPS 情報における「緯度の進行方向 ( "N" または "S" )」を示すパス文字列。
/// </summary>
private const string ExifPathGpsLatitudeDirection = "/app1/ifd/gps/subifd:{short=1}";
/// <summary>
/// EXIF の GPS 情報における「経度の進行方向 ( "E" または "W" )」を示すパス文字列。
/// </summary>
private const string ExifPathGpsLongitudeDirection = "/app1/ifd/gps/subifd:{short=3}";
データ型を char
から short
に変更。例えば北緯を表す "N" を書き込んだ場合、"N" の文字コードと終端 NULL 文字が埋め込まれ、正しいデータとして保存されるようになる。データ型が char
でも BitmapMetadata.GetQuery
に成功するのは読み込み量が半分でも NULL を除く文字コード部分は取得可能なためだろう。
最後に今回の調査を行う上で役に立ったプログラムを紹介。