2011 06 13

JPEG

デジタルカメラで撮った写真の画像ファイルは、カーソルを当てるといろんな情報が表示されるのだが、それを PhotoShop Elements で加工して保存すると、元々見えていた情報が見えなくなる。 これまで、気付いてはいたのだが気にしてなかったこのことに、ふと疑問がわいたのが昨日のこと。

何が違うんだろうといろいろ調べたところ、デジタルカメラが作るのは Exif の jpeg ファイルで、PhotoShop が出力するのは JFIF の jpeg ファイルとのこと。 JFIF の方が jpeg の基本形式で、Exif は拡張データとして JFIF に埋め込まれる形になっているらしい。

で、せっかくだから、基本形式の JFIF のデータフォーマットについて調べてみた。

SOI 画像ファイルであることを示すマーク。 ファイルの先頭2バイトに、固定値 0xFFD8 が設定される。
マーカー 0xFF?? の2バイト。 データセットの開始を意味する。
データサイズ 2バイト。 文字通りの意味だが、自分自身のサイズも含むため、正味のデータサイズは2引いた値となる。
データ データサイズ - 2 バイト連続する、何らかのデータ。
マーカー 〜 データ のセットの繰り返し。
画像データ マーカー 0xFFDA の後、画像データがファイル末尾まで続く。 画像データ本体にデータサイズは設定されない。

こんなフォーマットになっている。

JFIF 形式の場合、最初のマーカー 0xFFE0 は特殊扱いとなっていて、マーカーのデータは固定値 「JFIF」 から始まることになっている。 これで JFIF 形式であることを判定するのだな。

データサイズに、なぜ自分自身の2バイトを含めるのかも謎だが、もっと判らないのは画像の解像度。 幅と高さの情報は、どこかのマーカーに含まれるはずなのだが、jpeg の仕様書を見ても今一つはっきりしない。 この辺りは厳密に決まっている訳ではなくて、デファクトスタンダード扱いらしい。

ということで、解像度を 400x300 とか 1024x768 とかに設定した画像を用意し、マーカーの内容を全部表示するスクリプトを作って、それぞれの画像に対して動かしてみた。 その結果、どうやら先頭が 0x08 のデータ領域に、この 0x08 に続いて2バイトで高さ、続く2バイトで幅をもつらしい。 先頭の 8 の意味は判らないが、少なくとも手元にあった PhotoShop が出力した画像ではそうだった。 バージョンが変わると使えなくなるのかな。

せっかくだから、調査のために作った全てのマークの内容を表示するスクリプトをちょっと加工して、指定された画像ファイルの縦横サイズを返すものを作ってみた。

module JFIF def getSize( filename ) size = {} File.open( filename, 'rb' ) do | f | raise 'not JPEG' unless hs( f.read( 2 ) ) == 'ffd8' app0 = getMark( f ) raise 'not JFIF' unless app0[ :mark ] == 'ffe0' && app0[ :data ][ 0 .. 3 ] == 'JFIF' until ( mark = getMark( f ) )[ :mark ] == 'ffda' # start of image data if mark[ :data ][ 0 ] == 8 size[ :h ] = hi( mark[ :data ][ 1 .. 2 ] ) size[ :w ] = hi( mark[ :data ][ 3 .. 4 ] ) break end end end size end def getMark( fh ) mark = {} mark[ :mark ] = hs( fh.read( 2 ) ) mark[ :len ] = hi( fh.read( 2 ) ) mark[ :data ] = fh.read( mark[ :len ] - 2 ) mark end private :getMark def hs( bs ) bs.unpack('H*').join() end private :hs def hi( bs ) hs( bs ).hex end private :hi end

元がダンプだった名残とはいえ、バイト列を数値にするのに、バイト毎に文字列化して連結して数値化するのはどうなんだろう。 もっと効率的なやり方が有ると思うのだが。

+

障害者虐待防止法案が検討されているのだそうだ。

わざわざ障碍者と限定しなくても虐待は駄目な訳だが、児童とか女性とか障碍者とか、なんでこうわざわざ限定するんだろう。 それぞれ対策が違うからか。 虐待全般にあてるリソースが足りないからか。 扇情的な看板を掲げた方が、法案その他いろいろ通りやすいからか。

理由は色々あるんだろうけど、こうして枠を設定したとき、その枠からギリギリ漏れた人が最弱になるのは、どうにかしてほしいものだな。

あと、障碍者に対する虐待を防ぐのも大切だろうけど、障碍者が起こす虐待を防ぐことにも力を入れてほしいものだな。 責任能力がどうとか言ってないでさ。 殺人とかではなくもうちょっと低レベルな、例えば痴漢とか、犯人が知的障害者だった場合は、 「そうだから許してやれ」 と、泣き寝入りを強要されてそうなイメージなんだけど。