Exception Diary
2009.04.04 [Sat]
_ やっぱり単焦点レンズが好き
天気が良かったので散歩がてら今日も花を撮る。レンズは Ai AF NIKKOR 50mm F1.8D。軽く扱いやすく、好天だと抜群のキレ味を見せてくれる単焦点レンズはやっぱり良い。
前に、NikonにはD40やD60などの入門機で使える単焦点レンズがない、と書いたが、先月になってやっと、デジタル一眼専用の単焦点・標準レンズと言える AF-S DX NIKKOR 35mm F1.8G がリリースされた。私はすでにSIGMAの30mmを買ってしまったので(たぶん)買わない(と思う)けど、D40やD60のレンズキットだけを使っている人には絶対にお勧め。レンズ交換ができるデジタル一眼のよさをしみじみと味わえるはずだ。
モデル | : NIKON D90 |
撮影日時 | : 2009:04:04 13:51:56 |
焦点距離 | : 50mm |
F値 | : F2.5 |
露出時間 | : 1/2500sec. |
ISO感度 | : ISO200 |
露出補正 | : +0.0 |
モデル | : NIKON D90 |
撮影日時 | : 2009:04:04 14:00:55 |
焦点距離 | : 50mm |
F値 | : F3.2 |
露出時間 | : 1/3200sec. |
ISO感度 | : ISO200 |
露出補正 | : +0.0 |
モデル | : NIKON D90 |
撮影日時 | : 2009:04:04 14:28:46 |
焦点距離 | : 50mm |
F値 | : F5.6 |
露出時間 | : 1/800sec. |
ISO感度 | : ISO200 |
露出補正 | : +0.0 |
2009.04.09 [Thu]
_ 昼休みに桜を撮る
桜が満開。今年は例年になく長く桜が楽しめた。やはり、桜は絵になる。
モデル | : COOLPIX P5100 |
撮影日時 | : 2009:04:08 12:34:24 |
焦点距離 | : 26mm |
F値 | : F7.3 |
露出時間 | : 1/364sec. |
ISO感度 | : ISO200 |
露出補正 | : +0.0 |
モデル | : COOLPIX P5100 |
撮影日時 | : 2009:04:08 12:31:53 |
焦点距離 | : 7.5mm |
F値 | : F6.8 |
露出時間 | : 1/842sec. |
ISO感度 | : ISO200 |
露出補正 | : +0.0 |
モデル | : COOLPIX P5100 |
撮影日時 | : 2009:04:08 12:44:16 |
焦点距離 | : 7.5mm |
F値 | : F6.8 |
露出時間 | : 1/265sec. |
ISO感度 | : ISO200 |
露出補正 | : +0.0 |
2009.04.18 [Sat]
_ いっとくさんノ質問ニ関スル調査
(注:tdiary-contrib の exifparser には、下記の変更がすでに入っています。)
ちょっと時間が出来たので、いっとくさんから受けていた質問の調査をするため、exifparserを追いかけてみた。結論から言うと、やっぱり携帯(docomo F905i)を通してupしたという画像には、Exifの規約に合わない部分があることを見つけた。で、exifparserを修正して、おかしなデータは無視するようにする。これで、元画像と同じようにExifが表示できるようになった。
以下は追いかけた際のメモ。参考になるかも知れないのでこちらにも上げておく。
_ exifparser修正までの作業メモ
exifparserがExceptionを上げているところまでは分かっているので、view_exif のrescue節に、Exceptionのbacktraceを表示するようにしてみた。
rescue exp = ($!).to_s + "<br>" ($!).backtrace.each do |btinfo| exp += btinfo exp += "<br>" end return exp end
結果は以下の通り。scan.rbのextendを呼んでいる部分で、Moduleでなければいけない引数がnilだと言っている。
wrong argument type nil (expected Module) /usr/local/lib/site_ruby/1.8/exifparser/scan.rb:229:in `extend' /usr/local/lib/site_ruby/1.8/exifparser/scan.rb:229:in `scan_IFD' /usr/local/lib/site_ruby/1.8/exifparser/scan.rb:221:in `upto' /usr/local/lib/site_ruby/1.8/exifparser/scan.rb:221:in `scan_IFD' /usr/local/lib/site_ruby/1.8/exifparser/scan.rb:94:in `scan' /usr/local/lib/site_ruby/1.8/exifparser.rb:107:in `initialize' /usr/local/lib/site_ruby/1.8/exifparser.rb:105:in `open' /usr/local/lib/site_ruby/1.8/exifparser.rb:105:in `initialize' (plugin/recent_image.rb):341:in `new' (plugin/recent_image.rb):341:in `view_exif' (TDiary::Plugin#eval_src):51:in `eval_src'
extend というメソッドを呼んでいるのは、exifparser/scan.rb の229行目、←の部分。
def scan_IFD(tagTable, ifdname) num_dirs = decode_ushort(fin_read_n(2)) 1.upto(num_dirs) { curpos_tag = @fin.pos tag = parseTagID(fin_read_n(2)) tagclass = Tag.find(tag.hex, tagTable) unit, formatter = Tag::Format::Unit[decode_ushort(fin_read_n(2))] count = decode_ulong(fin_read_n(4)) tagdata = fin_read_n(4) obj = tagclass.new(tag, ifdname, count) obj.extend formatter, @byteOrder_module ←(※)ココ obj.pos = curpos_tag if unit * count > 4 curpos = @fin.pos begin @fin.pos = @tiffHeader0 + decode_ulong(tagdata) obj.dataPos = @fin.pos obj.data = fin_read_n(unit*count) ensure @fin.pos = curpos end else
Object.extend は、引数で指定したモジュールのインスタンスメソッドを self の特異メソッドとして追加する場合に使う。従って、formatter、@byteOrder_module は両方ともModuleでないといけないのに、どちらかnilだってことか。なるほど。
まず、@byteOrder_module を決めているところのコードはscan.rbの以下の部分。
# # get byte order # case tiff_header[0,2] when "MM" @byteOrder_module = Utils::Decode::Motorola when "II" @byteOrder_module = Utils::Decode::Intel else raise RuntimeError, "Unknown byte order" end self.extend @byteOrder_module @result[:offset_IFD0] = decode_ulong(tiff_header[4..-1])
データがMotorola形式(Big Endien)かIntel形式(Little Endien)かを表すコードがtiffヘッダに入っていて、それを読み取って決めているところらしい。ここに問題があるなら、RuntimeErrorがraiseされることになるから、現象と合わない。よって、formatter の方がnilでありそうだ、ということが分かる。
では、formatterはどこで代入されるのか? 以下の行に注目。
unit, formatter = Tag::Format::Unit[decode_ushort(fin_read_n(2))]
Tag::Format::Unit のコードは以下の通り。
# # maps number to size of one unit and the # corresponding formatter (defined below) module. # module Format Unit = { 1 => [1, ::Exif::Tag::Formatter::UByte], 2 => [1, ::Exif::Tag::Formatter::Ascii], 3 => [2, ::Exif::Tag::Formatter::UShort], 4 => [4, ::Exif::Tag::Formatter::ULong], 5 => [8, ::Exif::Tag::Formatter::URational], #6 => [1, ::Exif::Tag::Formatter::SByte], 7 => [1, ::Exif::Tag::Formatter::Undefined], 8 => [2, ::Exif::Tag::Formatter::SShort], 9 => [4, ::Exif::Tag::Formatter::SLong], 10 => [8, ::Exif::Tag::Formatter::SRational], #11 => [4, Exif::Formatter::SFloat], #12 => [8, Exif::Formatter::DFloat] } end
なるほど、decode_ushort(fin_read_n(2)) が 1,2,3,4,5,7,8,9,10のいずれかでないといけないところが、いずれにも当てはまらない値だ、ということか。
では、実際にはいくつになってしまっているのだろう。formatterがnilなら、Exceptionを上げるよう、scan_IFDにデバッグ・コードを追加してみる。
tagclass = Tag.find(tag.hex, tagTable) ifd = decode_ushort(fin_read_n(2)) unit, formatter = Tag::Format::Unit[ifd] if formatter == nil raise Exception.new(%Q[scan_IFD formatter = nil: ifd = #{sprintf("%04x", ifd)}]) end count = decode_ulong(fin_read_n(4))
以下の通りの結果になった。
500 Internal Server Error scan_IFD formatter = nil: ifd = 0000 (Exception) /usr/local/lib/site_ruby/1.8/exifparser/scan.rb:228:in `scan_IFD' ...
ここで、jpegファイルの構造の仕様をネットで探して読んでみる。Tag::Format::Unit は、InformationDirectory(IFD)のデータ・タイプを見て、マッチするデコーダModuleを返すHash tableになっているようだ、ということが分かった。要はこのデータ・タイプが0になっているのが悪い、と。だんだん分かってきた。
次に、実際にjpegデータを16進ダンプして見てみる。ビンゴ。最初のIFD(IFD0)の5番目のタグのtypeが確かに0x0000になっている。Tagそのものも0x0001になっていて、Exifタグのリストに見当たらない。これで、データがおかしいことが決定。
で、どうするか。不正なタグを読み飛ばすよう、scan.rb に1行追加。
unit, formatter = Tag::Format::Unit[decode_ushort(fin_read_n(2))] count = decode_ulong(fin_read_n(4)) tagdata = fin_read_n(4) next if formatter == nil # <- ココを追加 obj = tagclass.new(tag, ifdname, count)
これで成功。
GR DIGITAL 2 , 5.9mm, F2.4, 1/30sec., ISO100, -0.3EV
元画像と同じようにExifが表示されるようになった。Image GalleryのViewerモードでもOK。
2009.04.26 [Sun]
_ 東大和南公園にて
レンズはいずれも AF Nikkor 50mm F1.8D。東大和南公園には、第二次大戦中に米軍機の機銃掃射を浴びた変電所が史跡として残されている。「旧日立航空機立川工場変電所」(リンク先はwikipedia)というのが正式名称で、1993年までは実際に変電所として使用されていたらしい。
最後の四十雀の写真は声のするほうにカメラを向け、連写したなかの一枚を等倍にトリミングしたもの。ズームレンズを持ってきていなかったので苦肉の策だが、何とか見られる写真になっているのではなかろうか。
モデル | : NIKON D90 |
撮影日時 | : 2009:04:11 10:59:47 |
焦点距離 | : 50mm |
F値 | : F11 |
露出時間 | : 1/125sec. |
ISO感度 | : ISO200 |
露出補正 | : +0.0 |
モデル | : NIKON D90 |
撮影日時 | : 2009:04:11 11:07:06 |
焦点距離 | : 50mm |
F値 | : F6.3 |
露出時間 | : 1/1000sec. |
ISO感度 | : ISO200 |
露出補正 | : +0.0 |
モデル | : NIKON D90 |
撮影日時 | : 2009:04:11 11:12:04 |
焦点距離 | : 50mm |
F値 | : F8.0 |
露出時間 | : 1/640sec. |
ISO感度 | : ISO200 |
露出補正 | : +0.0 |
モデル | : NIKON D90 |
撮影日時 | : 2009:04:11 11:13:42 |
焦点距離 | : 50mm |
F値 | : F11 |
露出時間 | : 1/200sec. |
ISO感度 | : ISO200 |
露出補正 | : +0.0 |
モデル | : NIKON D90 |
撮影日時 | : 2009:04:11 11:28:02 |
焦点距離 | : 50mm |
F値 | : F9.0 |
露出時間 | : 1/400sec. |
ISO感度 | : ISO200 |
露出補正 | : +0.0 |
モデル | : NIKON D90 |
撮影日時 | : 2009:04:11 11:36:16 |
焦点距離 | : 50mm |
F値 | : F4.0 |
露出時間 | : 1/1250sec. |
ISO感度 | : ISO200 |
露出補正 | : +0.0 |
_ いっとく [この度は、個人的なトラブルにご対応いただきありがとうございます。 無事、Exifが表示されるようになりました。これで..]