jpegファイルの構造がどうなってるのかなと思ってちょっと調べたのでまとめ。
jpegファイルは大まかに[ヘッダ+画像データ+フッタ]でできている。
jpegファイルは必ずFFD8
ではじまる。
FFD8
以降はヘッダの部分でJFIF形式になっている。
JFIF形式はこんな感じで最初の2 byteがフィールドの種類(必ずFFで始まるので255種類)、次の2 byteがデータサイズ(最大0xFFFF=65535 byte)、残りがサイズ分のデータ、のセットが順々に並んでいる。
フィールド種類(2 byte) | サイズ(符号なし整数2 byte) | 中身(サイズ byte) |
---|---|---|
FFE0 | 0024 | ... |
FFD0 | 0012 | ... |
FFDB | 0022 | ... |
... | ... | ... |
FFDA | 0012 | ... |
最初は必ずFFE0の「これ以降はJFIF形式ですよ」という意味にフィールドで始まる。
FFDBやFFC4など同じフィールドが何度も出たり、必ず無いといけないものやなくてもいいものが混ざっている。
最後は必ずFFDA(sos)で終わる。これが「これから画像データ読みまっせ」という意味のフィールドだからだ。
各フィールドについては調べた感じ、次のサイトが詳しく解説されていた。 JPG ファイルフォーマット
このフィールドのうち、FFE1
(APP1)はデータ部分が"Exif\0\0"
の6byteで始まっていればExif形式のデータが入っている。
Exif形式は入っている情報が多く、画像の縦横サイズはもちろん、ピントの深度・カメラの回転方向・撮ったカメラの種類、gps情報まで入っている。flickrに出てくる情報もExifを元に表示しているものと思われる。
そのデータ量は例えばiPhoneで写真を撮ると、およそ12K byteにもなる。 これはバカに出来ないデータ量で、「jpegのメタ情報を削ってファイルサイズを減らそう!」という記事が多くあるのはこのためだ。
因みにiPhoneのsafariから撮った写真をhtmlフォームの(2016/08現在、最新のiOSでは勝手にExifを削除しなくなったようだ。)<input type='file'>
で送ると、gps等のかなりのデータが勝手に削除された状態で送信される。
また、Exif情報のうちのカメラの回転方向を読み取って勝手に回転してくれるブラウザもある。Chrome(39.0.2171.95)では回転せず、iPhoneのsafariやFirefox(34.0.5)では回転が確認できた。ブラウザ依存で動作が変わる厄介な仕様でもある。
うまく全てのブラウザで同じように表示させようとするなら、imagemagickのauto-orientで回転させてしまうのがよいが、オリジナルのExif情報を上書きしてしまう副作用も存在する。(もちろんそんなもんどうでもよいと言うならベストな選択だと思う。)
最後にExif情報だけをまるごと抜き取るスクリプトを書いてみた。 一応画像サイズを削りつつ画像は表示されるが、画像サイズを削減する目的であればimagemagickでstripするのがベターだと思われる。