(「写真(の場所)はどこですか?」のつづき)
Perl で Exif を扱うには CPAN でも配布されている ExifTool [参考1]を使うと簡単、便利。これには Perl モジュール Image::ExifTool のほかにも、コマンドラインツール exiftool も含まれていて、プログラミングをしなくともちょいと使う事ができるらしい。
面白いのは、こんなふうにすると、 Exif 情報をバイナリでダンプして、しかもとても気の利いた HTML ページとして見られる:
$ exiftool -htmlDump DSCF5851.JPG > out.html; open out.html
モジュールを使うユーザとしてはここまで深いところは気にしなくてもいいけれど(そのためのモジュールだから)、書き込んだ値がどうも怪しい、といった時にはデバッグの助けにはなる。──とは言ってみたものの、 Exif の仕様に明るくなければ、たとえば書式が正しいのかどうか、とか、そういう判断できないので仕様書[参考2]も参照しないといけない。けども、仕様書は膨大なものなので、代わりに、主に必要なタグの種類とその書式の、リファレンス的なものがどこかに纏められていないかと思ったらば、これも ExifTool のドキュメントにあったりする。いたれりつくせり?
じぶんが作ろうとしているツールでは、 GPS に関する、 Exif の情報がほしい。そこで、リファレンスからその項目を参照してみることにする。 ExifTool Tag Names というタイトルのページにずらりと並んだタググループの、 GPS というところ。
ただ、読み出しだけなら、実際に取り出してみたら話も早いのかもしれない。でも、じぶんのデジカメで撮った画像はそもそも GPS 位置情報を持っていないので、つまりサンプルがない。そこでまず、書き込んでみる事にする。
Perl モジュールのドキュメントを見てみると、メソッド SetNewValue() に、タグと値のペアを渡して、そしてメソッド WriteInfo() でファイルに書き出すといった手順になるようだ。
そこで実際やってみるのだけれども、このとき、緯度・経度の値の書式はどのようにしたらよいのかと、はたと立ち止まった。モジュールのドキュメントでは、詳しい記載がなかった。
考えたのは、 Exif 規格では、分数で表された度分秒をカンマで区切って、 40/1,8/1,4094/100 みたいな値、というふうに定義されているので、それを真似て(もちろん、 degree 形式から変換して)入力させたらよかろうということだったのだけれも、それは無駄な事だった(そして、おそらく間違い)。
ExifTool のタグのページを見てみたら、こうあった(引用):
ExifTool is very flexible about the input format for lat/long coordinates, and will accept 3 floating point numbers (for degrees, minutes and seconds) separated by just about anything.
ということで、 degree のままでもいいみたい。──いや、 degree(s) でないと駄目のようだ。度、分、秒が、ちゃんと分けられていないといけない。 GPX であるような緯度・経度の値の表現、たとえば 40.144708 は、 40.144708 度 0 分 0 秒と見なされてしまうようだ。
また Exif の仕様のような書式、たとえば 40/1,8/1,4094/100 は、 40度 1分 8秒に見なされてしまう。これは、小数点を含んだ数字列以外の文字列は区切り文字となってしまうためだ(ちゃんと試して確かめた)。
なので、もしもとが GPX の形式であったらば、 degree 表記の 40.144708 は、 hms 表記の 40/8/40.94 のように変換しないといけなかった。区切り文字は、ドットと数字以外ならなんでもいいらしい。
そのほか注意する事と言うと、同ページにまた親切な事に、こうある(引用):
When adding GPS information to an image, it is important to set all of the following tags: GPSLatitude, GPSLatitudeRef, GPSLongitude, GPSLongitudeRef, GPSAltitude and GPSAltitudeRef.
GPS 情報を書き入れるときにはセットすべき重要なタグはこれら、ということが書かれていた。ただ、じぶんが Exif についてちょいと調べたときの、うろ覚えの情報によると、ほかにも GPSVersionID が必須だったような気がする。あと、 GPSMapDatum 。
やはりうろ覚えの情報では、 GPSVersionID は通常 2.0.0.0 とのこと。いつの、またいつまでの「通常」かはわからないけれど、現在ではこれを書いておいた方がよいかと思われる。それから測地系は、もしかしたら省略されていたら WGS-84 とみなされるのかもしれない。でも明示できるなら、しておいたほうがいいよね。
あとひっかかったのが、必須タグのうちのひとつ、 GPSAltitudeRef 。 Exif の仕様によると '0' なのだけれども、これを素直に書き入れようと思ったらエラーになった。
Can't convert GPS:GPSAltitudeRef (not in PrintConv)
タグについて参照しているそのページにも 0 か 1 って書いてあるのにナンダよと思いつつ、調べてみると、 FAQ のページにズバリ書いてあった。きっと、同じような「ナンダよ、」が、作者のもとにたくさん送りつけられているものと見える。
これの解決のやり方はいくつかある。 0 のかわりに 'Above Sea Level' という文字列で書き入れておけばとりあえず、いいようだ。 Exif の仕様では 0 でないといけないのだけれども、 'Above Sea Level' と書き込んで、それを冒頭のように HTML にダンプしてみたらば、ちゃんと 0 になって書き込まれているのが確認できた。
なるほどこの手際、宝探しの地図を持って、いざ宝箱をあけたら次の場所の地図が手に入る、そんなようなドキュメントのしたたかさも見ても、このツールの作者はただ者ではない。
さて、コマンド exiftool を用いても、いちいち HTML にダンプするのも手間なので、書き込んだ GPS に関するところだけをさらりと見てみる。
作ろうとするツールでは、 Perl でこういった Exif に入っている GPS 位置情報を画像ファイルから取り出し、もし値がなかったら、トラックログと照らし合わせておおよその位置を特定するようにする、という感じになる。
$ exiftool -GPS:all DSCF5851-exiftool.JPG GPS Version ID : 2.0.0.0 GPS Latitude Ref : North GPS Latitude : 40 deg 8' 40.94" GPS Longitude Ref : East GPS Longitude : 139 deg 58' 53.57" GPS Altitude Ref : Above Sea Level GPS Altitude : 0 metres GPS Map Datum : WGS-84 $
ところでこの例に見られるような、それらの値は、ひとが見て見やすい内容に工夫されて出力されている。つまり Exif の仕様の形では、ないのだね。じぶんはそこに気がつくまで、なんで違う勝手な値を書き込むんだと早合点して、あやうく深い泥沼に嵌るところだったのだ。──と言いたいけれど、ツール試作が完成したあとにこのことに気がついたので、じつは片足には泥がついていたりする。
ちなみに GPSPhotoLinker で、同じポイントを指定して、 Exif に書き込んだものを見てみた。精度の問題か、 1/100 秒ズレた。ここで言っている精度は、じぶんが書いた degree から hms に変換するルーチンのそれだ。じぶんのルーチンでは桁を切り捨てたけれど、これは四捨五入した値?
$ exiftool -GPS:all DSCF5851.JPG-GPSPhotoLinkered.jpg GPS Version ID : 2.0.0.0 GPS Latitude Ref : North GPS Latitude : 40 deg 8' 40.95" GPS Longitude Ref : East GPS Longitude : 139 deg 58' 53.58" GPS Altitude Ref : Above Sea Level GPS Altitude : 0 metres GPS Map Datum : WGS-84 $
基数変換したりするのも関係してか(というよりただ面倒だったのかもしれない... ) Exif での有効桁数もいまひとつ判然としなかったので、適当な桁で切り捨ててヨシとしてたのだけれども、まあ、 GPS に誤差はつきものだから、いいかしらん。
(「AppleScript で Perl に GUI をつける」につづく)
参考
[1] ExifTool by Phil Harvey
http://owl.phy.queensu.ca/~phil/exiftool/
[2] Exchangeable image file format for digital still cameras: Exif Version 2.2
http://www.exif.org/Exif2-2.PDF