Exif Orientation のうんちく
はじめに
画像を表示する際に意図せぬ回転して困る事で有名な Exif Orientation に関するうんちくです。(2021年12月5日作成記事)
Exif Orientation とは
カメラで撮影して保存する JPEG に関する主な規格として、DCF と Exif があります。
そのうち Exif の Orientation 情報は、カメラの向き等によって画像が本来意図するものと違う回転/鏡像で JPEG ファイルに保存される事を示すメタデータとしての値フィールドです。
図のように横長のカメラを縦にして撮影した場合、本来の映像を横に倒した画像が JPEG に保存される事になります。これを表示する際に元に戻すのが一般的な使われ方です。
画像ビューアによって Orientation が無視される事もあるので、世の中の画像アップローダは Orientation 補正して画像を保存する事が多いでしょう。
また多くの画像ライブラリは画像を読み込む際に自動では Orientation 補正をしないので、縦と横で違いが出るフィルタを実装する場合や、画像認識をする場合に、やはり回転補正する必要があります。
Exif Orientation 仕様
Exif Orientation の仕様はこちらに含まれます。なお Exif 2.3 当初誤記があって 2012年12月の改訂で修正されたようです。
尚、現時点(2021年12月5日)での最新は 2.32 ですが、ドラフトだけ PDF 公開されていて、正式版は売り物です。(ちなみに ¥24,574)
- https://www.cipa.jp/std/documents/j/DC-X008-2019-J.pdf (ドラフト版)
- https://www.jeita.or.jp/cgi-bin/standard/search.cgi ここで Exif で検索すると正式版が見つかります。立ち読みはできるようです。
Exif バイナリ形式 (おまけ)
Exif バイナリ形式での Orientation フィールドの入れ方はこちらです。
タグ名称 | タグ番号 | タイプ | カウント |
---|---|---|---|
画像方向 Orientation | 274(0x0112) | SHORT(=2byte) | 1 |
Exif のバイナリ形式は TIFF のサブセットで、その TIFF の画像フォーマットの仕様は Adobe のサイトにあります。
ですが、まずは以下のエントリを参照すると良いでしょう。噛み砕いた説明で分かりやすいです。
- Exif データにアクセスするコードを自作してみる
サンプル画像
サンプル画像は ImageMagick で以下のように作成しました。文字を入れると鏡写しにすぐ気付けるのでお勧めです。
% convert -size 100x75 -font .New-York-Italic -pointsize 64 \
-fill white -stroke black -strokewidth 1 -gravity center \
\( \( xc:red -annotate 0 R \) \( xc:green1 -annotate 0 G \) +append \) \
\( \( xc:blue -annotate 0 B \) \( xc:yellow -annotate 0 Y \) +append \) \
-append -depth 1 RGBY.png
Orientation の値
回転だけなら 4 種類あれば良いのですが、鏡像反転も対応するので 1〜8 の 8 種類の値を持ちます。
そのため、インカメラのように左右鏡像反転した方が直感的なケースも対応できます。
1 origin の番号体系にも注意が必要です。おそらく 0 は Exif 内に Orientation フィールド不在な場合と区別しにくいので、特別扱いしたものと思われます。(ただ、処理的には Orientation 無しと 0 と 1 は全部同じなので、区別する必要があったかというと微妙)
回転と鏡像反転 (前提知識)
実は画像の90度単位での回転は、鏡像反転処理だけで実現できます。
例えば、90度回転は上下反転と斜め反転の組み合わせで可能です。
元画像 | 上下反転 | 更に斜め反転 |
---|---|---|
つまり、同じ鏡像反転を2回実行すると元に戻りますが、違う種類の鏡像反転を適用すると、回転するのです。
上下+斜め => 90度回転 | 上下+左右 = 180度回転 | 左右+斜め = 270度回転 |
---|---|---|
そんな訳で、Orientation の全ては、上下/左右/斜めの鏡像反転の組み合わせで実現できますし、それら3つのフラグと相互変換もできます。
さて、具体的な画像の変換を紹介します。
変換表
JPEG ファイル内の実画像
Orientation 適用前の JPEG 実画像と、Orientation を適用した時の比較です。
Orientation の番号は回転の順には並んでいません。画像の反転をベースに考えているようです。
Orientaton | JPEG 実画像(Orientation無視表示) | Orientation適用表示 | 操作 |
---|---|---|---|
1 | 無し | ||
2 | 左右反転 | ||
3 | 上下左右反転 = 180度回転 | ||
4 | 上下反転 | ||
5 | 斜め反転 | ||
6 | 2 + 斜め反転 = 270回転 | ||
7 | 3 + 斜め反転 | ||
8 | 4 + 斜め反転 = 90度回転 |
早見表
2つに分けます。
実画像の配置
Orientation 操作すると になる、元画像を以下に並べます。
1 | 2 | 3 | 4 |
---|---|---|---|
5 | 6 | 7 | 8 |
変換操作
実際に Orientation 適用の実装をする場合、こちらの表が便利だと思います。
元が で、Orientation 操作した後の画像テーブルです。
1 | 2 | 3 | 4 |
---|---|---|---|
5 | 6 | 7 | 8 |
一つ目の早見表との違いは、6 と 8 が入れ替わっているだけです。
Orientation と鏡像反転フラグ
画像のテーブルを見ると分かりますが、Orientation 操作は左右反転、上下反転、斜め反転の3つの鏡像反転で表現できます。
Orientation から 1 を引いてビットで分解すると、その反転のフラグに近いデータが出てきます。
1 | 2 | 3 | 4 |
---|---|---|---|
そのまま | 左右反転 | 上下左右反転 | 上下反転 |
5 | 6 | 7 | 8 |
1の斜め反転 | 2の斜め反転 | 3の斜め反転 | 4の斜め反転 |
つまり、Orientation から 1 を引くと、ビットで処理できます。
3 と 4 の意味が逆なら、もっと素直なビット処理になるのが少し残念ですが、仕方なく頑張ると、以下のようなコードで相互変換可能です。
- Orientation から反転ビットを取り出す処理
function fromOrientation(orientation) {
const o = orientation - 1;
const reverse = (o & 1)? true: false;
const vertical = (o & 2)? true: false;
const horizontal = reverse !== vertical; // xor
const diagonal = (o & 4)? true: false;
return [horizontal, vertical, diagonal];
}
- 反転ビットから Orientation 値に戻る処理
function toOrientation(horizontal, vertical, diagonal) {
const reverse = horizontal !== vertical; // xor
const o = (reverse? 1: 0) + (vertical? 2: 0) + (diagonal? 4: 0);
return o + 1; // orientation;
}
Orientation 値と反転フラグの関係が実感できるデモを作りました。任意の画像をドロップして試せます。
Author And Source
この問題について(Exif Orientation のうんちく), 我々は、より多くの情報をここで見つけました https://qiita.com/yoya/items/4e14f696e1afd5a54403著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .