Exiftranによる画像回転とexiv2による訂正

概要

画像のトリミングと回転などコマンドで一括にを書いているときに、exifに埋め込まれたサムネイルを作り直したり、メタデータの値を修正したり確認したりする必要が生じました。

Exiftranでexifを考慮した画像の回転はできますし、別の画像処理ソフトでトリミングなどの加工したあとでExiftranを使ってやるとexifを自動で整えることができます。

ただ、exifを正しく設定しないカメラ、スキャナや画像処理ソフトの間違いを細かく訂正するにはexiv2も必要です。

Exiftran

manで調べると、jpg画像を劣化させることなく回転させるもので、同目的のjpegtranに比べて、自動で orientation tag を元に回転させることができ、必要に応じて orientation や dimension(画像サイズ)を更新し、さらに埋め込みのサムネイルも同時に回転させるとあります。

トリミングをしなくてよいなら、Exiftranだけで前回の目的は一発で達せられます。

orientation tag に従ってフォルダ内の全jpg画像を自動回転する

exiftran -ai *.jpg

ファイルが一つのときは別の名前のファイルにすることができる

exiftran -o outputfile.jpg -a inputfile.jpg

フォルダ内の全jpg画像にexifのサムネイルを追加(更新)する

exiftran -gi *.jpg

元のファイルを直接書き換える(inplace)オプションなのでfor...などがいらない。もちろん-oで出力を指定するのと組み合わせてfor...を使うこともできる。バックアップファイルを作る選択肢もある。

自動でOrientationに従う回転(-a)したときも、回転角を指定して回転したときも、Orientationはクリア(値は1:top-left)される。Orientationの記述がない場合は追加されないが、この場合の値は1が仮定されるので問題ない。また、exifのdimension(画像サイズ)が実際と異なる場合には修正される。

回転は本来のデータの向きに対して実行されるので、本来画像がどちらを向いていたのか正しく把握していないと混乱する。スキャナで向きを指定した時とか、カメラを水平に構えた時など、間違ったOrientationが記録されたときは、注意する必要がある。

下に一覧にしたが exiftran でexif情報を表示するのは、

exiftran -d 対象ファイル名

だが、Pixel X Dimension, Pixel Y Dimension の値は、exiftran以外のソフトでは変更されずに生成時のままになっていることがある。また、ここで -d はdumpの意味だが、他のソフトでは delete の意味であることが多いので注意。

Exiftranのマニュアルから

man Exiftran で表示される英語のマニュアルは平易・簡潔で読みやすい。

usage: exiftran [ options ] file
基本はごく普通のコマンド
exiftran -i [transform options] [others options] file1 file2 ... fileN
入力ファイルを直接書き換える(-iで処理する)場合は複数の入力ファイルを並べて指定できる
exiftran -o outputfile [transform options] [other options] inputfile
出力ファイルを指定するときは入力ファイルはひとつだけにする
exiftran -d file1 file2 ... fileN > exifinfo
データのダンプの場合はまとめて複数を指定でき、出力先はリダイレクトで指定する
transform options:
-aorientation tag に従って自動回転
-9時計回りに90度回転
-1時計回りに180度回転
-2時計回りに270度回転
-f上下反転(flip)
-F左右反転
-t左上\右下に沿って反転(transverse)
-T左下/右上に沿って反転
-ntthumbnailを回転しない
-niimageを回転しない
-noorientation tag を更新しない
-npdon't pare lost edges 8の倍数に切り詰めない
other options:
-hこのhelpを表示して終了
-dexif data の出力(dump)
-c <text>コメントタグをtextに新規作成または更新
-g(re)generate thumbnail 「サムネイルを作り直す」
-o <file>出力ファイル名の指定
-iinplace(元のファイルを書き換える)
-bバックアップファイル(backup)を作る(-iの時)
-pタイムスタンプを元のまま(Preserve)とする(-iの時)

もう一つ必要

exiftranだけでは、変更前にOrientationやthumbnailがどうなっているかが、はっきりしないことがある。

ファイルマネージャや画像閲覧のソフトではサムネイルを独自に生成することが多く、exifのthumbnailを使わないのが普通。これを確認できるよいソフトが見つからなかった。

Orientationについてもファイルマネージャや画像閲覧のソフトて自動で回転表示をするものもあるので、実際のデータがどうなっているかがわからない。特に、exifを正しく設定しないカメラ、スキャナや画像処理ソフトで乱れているものについては、大抵の場合は無視されるのだが、不具合を生じることもある。調査する道具が必要。

exiv2

Exif の他、IPTC, XMPのメタデータや画像コメントも読み書きするプログラムとあります。カメラメーカーのメーカーノートと呼ばれる独自のタグもある程度は読み取ることができ、以前頼りにしたことがあります。

man exiv2 で表示されるマニュアルは長く、読みにくいので、よく使いそうな例だけ示します。

exiv2のexifデータ概略表示

-psオプションでファイル名だけを指定すると、概略を表示します。exif以外にもファイル名や、実際の縦横のピクセル数も一緒に表示するので助かります。実はこの-psはデフォルトで、省略可能です

exiv2 -ps ファイル名

このようになります。

adachi@ebook:xjpg$ exiv2 crroEPSON002.jpg 
File name       : crroEPSON002.jpg
File size       : 5155072 Bytes
MIME type       : image/jpeg
Image size      : 3412 x 2415  ⇦実際のピクセル数
Camera make     : SEIKO EPSON CORP.
Camera model    : EP-881A Series
Image timestamp : 
             ……省略……
Image quality   : 
Exif Resolution : 2480 x 3507  ⇦exif上のピクセル数
White balance   : 
Thumbnail       : image/jpeg, 13237 Bytes
Copyright       : 
Exif comment    : 

上の例はexifを書き換えない処理ソフトで、トリミングをして90度回転をしたのでピクセル数が異なっています。Orientationは残念ながら-psオプションでは表示されません。-paか-peで表示されます。

exiv2のgrepオプション

-paや-peオプションで多数の項目が表示されますが、次のようにすれば必要なものだけが表示されます。

adachi@ebook:xjpg$ exiv2 -g Dimension -g Orien DSC_5650.JPG 
Exif.Image.Orientation                       Short       1  top, left
Exif.Photo.PixelXDimension                   Long        1  5568
Exif.Photo.PixelYDimension                   Long        1  3712

-g は grep の意味で、続く文字列が含まれるものが出てきます。

残念ながら今度は-psで出てきた実際のピクセル数を出す方法がありません。

exiv2によるサムネイルの抽出

exifの中に入っているthumbnailは規格によれば、160x120の小さいものです。

exiv2 -ep ファイル名.jpg

ファイル名-preview1.jpg ができます。

adachi@ebook:xjpg$ exiv2 -ep DSC_5650.JPG
adachi@ebook:xjpg$ ls -l DSC_5650*
-rw-rw-r-- 1 adachi adachi   17216  7月  1 02:19 DSC_5650-preview1.jpg
-rw-rw-r-- 1 adachi adachi 2927963  7月  1 00:27 DSC_5650.JPG

実際には256x188のものでした。このthumbnailはカメラが撮影のときに作ったものです。exiftranに作らせると160x117になりました。

adachi@ebook:xjpg$ exiv2 -pp DSC_5650.JPG
Preview 1: image/jpeg, 256x188 pixels, 17216 bytes
adachi@ebook:xjpg$ exiv2 -pp DSC_5650wt.JPG
Preview 1: image/jpeg, 160x117 pixels, 8456 bytes

-ep の代わりに -et でも同じサムネイルが、ファイル名-thumb.jpg でできます。しかし、exiftranの回転操作で埋め込まれたサムネイルも回転した場合、-et だと .tif 形式になることがあります。

exiv2による値のセット

-Mオプションはexifの値をファイルにセットします。

exiv2 -M"set Exifの項目名 値"  ファイル名

例えば Orientation の値を 1 にセットするには次のようにします。

adachi@ebook:xjpg$ exiv2 -g Orientation  DSC_5523.jpg 
Exif.Image.Orientation                       Short       1  right, top
adachi@ebook:xjpg$ exiv2 -M"set Exif.Image.Orientation 1"  DSC_5523.jpg 
adachi@ebook:xjpg$ exiv2 -g Orientation  DSC_5523.jpg 
Exif.Image.Orientation                       Short       1  top, left

前後の操作はOrientationの値が変化したことを確かめただけで、本体は-Mのある行だけです。

-mを使うとテキストファィルからたくさんの値をまとめてセットできます。

exiv2による値の消去

全部のメタデータを消去

exiv2 -da ファイル名

サムネイルだけを消去

exiv2 -dt ファイル名

ある項目だけを消去というのは、見当たりません。現在の全部の設定値をテキストファイルに書き出して、編集して、全消去したファイルに書き戻すという手順になるのだと思います。

あるいは-Mなどを使って、値を当たり障りのないものに書き換えるという手もあります。たとえばOrientationならば1にすると消去したのと同等な意味になります。

exiv2のマニュアルから

もう少し拾っておきます。

基本形は、

exiv2 [options] [action] file ...

この...が意味するところは、対象となるファイルを列記できる、つまり *.jpg も使えるということ。

[action]については以下の表によるが、[options]の記述で明確になっている場合は省略可能とある。実際、ほとんどの場合使わない。せっかく作ったので置いておく。

action 説明
pr | printメタデータの出力。これがデフォルトのaction
ex | extractメタデータの抽出。*.exv, *.xmp, *.jpg(image files)
in | insert*.exv, *.xmp, *.jpg からのメタデータの挿入
rm | deleteメタデータの削除
ad | adjustexifタイムスタンプの書き換え
mo | modifyメタデータの変更。追加と削除も
mv, fi, fc

actionをほぼ必要としないので、次のオプションが大切。

Option 長い書き方 説明
-u unknownタグ(名前のないタグ)を含める。(実は-psと同じデータが出る)
-d tgt --delete tgtで指定した種類のタグを削除する。
-e tgt --extract Extract target(s) for the 'extract' action.
-g key --grep 指定した文字列を含むキーのみを表示する。-gを複数書くことで or の働きをする。
-K key --key 指定したキーを表示する。-bの完全一致版。-K Exif.Photo.DateTimeOriginal などと指定する。複数指定可
-m file --modify どのキーにどの値を設定するかのコマンドを入れたファイルを指定して、一度に追加や書き換えを行う
-M cmd --Modify コマンドを直接書いて追加や更新を行う
-p mode プリントモード。exifの一覧の出し方を選択する。
s:概要(デフォルト) a:Exif,IPTC,XMP e:Exif t:Exifタグの翻訳 p:可能なプレビュー一覧
-P flg exifの一覧でタグなどの出し方を事細かに指定する。
k:キー n:タグ名 y:タイプ c:要素数 s:バイト数 v:値 t:解釈値

cmd, flg, tgt は次のように指定する

cmd  set | add | del key [[type] value]
     setは既存のタグからkeyに合致するものをvalueに書き換える。または追加する。
     addはタグを追加する。タグの重複を妨げない。
     delはkeyのみ指定。存在するタグを消去する。
     typeを指定しなければ、それぞれのkeyにより仮定されたものを使う。
     valueは残りの行の終わりまでと解釈されるが、'value'または"value"とクォーテーションマークで括ってもよい
flg  E | I | X | x | g | k | l | n | y | c | s | v | t | h
     Exif, IPTC, XMP, num, grp, key, label, name, type, count, size, vanilla, translated, hex
     ここでvanilla は「普通の」つまりtranslateしないplaneな値
tgt  a | c | e | i | p | t | x | C | X | XX | -
     all, comment, exif, iptc, preview, thumb, xmp, ICC Profile, SideCar, RawXMP, stdin/out

画像の向き(Orientation)について

Exif.Image.Orientation は画像のデータをそのままに、どの向きで表示すべきかを示すタグである。

JPEGのデータの規格に後付に決められたものなので、ハードもソフトも考慮するものとしないものがある。

exifの値は1〜8の数値で、exiv2は translated と指定すると top,left などと表示する。戻す操作との一覧を次に示す。戻す操作はさまざまあるので一例を示した。正しい向きをどの様に変化させた図かというのと混同すると混乱するので注意。

translated 意味 戻す操作(例)
1 top, left 上辺を左から右へ そのまま
2 top, right 上辺を右から左へ 左右反転
3 bottom, right 下辺を右から左へ 180度回転
4 bottom, left 下辺を左から右へ 上下反転
5 left, top 左辺を上から下へ 左右反転、時計まわりに270度回転
6 right, top 右辺を上から下へ 時計まわりに90度回転
7 right, bottom 右辺を下から上へ 左右反転、時計まわりに90度回転
8 left, bottom 左辺を下から上へ 時計まわりに270度回転

top,leftの意味するところ

画像のデータはファイルの中ではひとつながりになった情報の列になっている。これで二次元の画像を復元するとすれば、文字の列がページを埋めていくように、紙の1辺の端から1行を埋めていき、1行が埋まったら2行目に進むという手順を踏むはず。

最初の1行が上下左右のどの辺から始まるかと、行内でどちら側から埋めていくかの2つの情報で図の向きを指定することができます。

上辺の左から右へ埋めていく例

辺の選択肢は top, bottom, left, right のどれかで、辺が topかbottom なら 開始点はleftかright、 辺がleftかright なら 開始点はtopかbottom とそれぞれ2択なので、全部で8通りあるわけです。

Orientationの値を考慮して表示する例を示します。A, B, C の例は皆赤い矢印の向きにデータが並んでいるものとします。

A top, left の例。指定がなければこれです。
上から始めて左から右に描いていきます。
文字NRが正しく並んでいる。左上に右向きの矢印がある
B Aと同じデータを right, top で表示した例です。
データの保存順はそのままにして、表示を回転することができます。
NRが時計回りに90度回転されて配置、右上に下向きの矢印がある
C right, top で正しい向きに表示される例です。
このデータはAと同じではありません。
NRという文字をAのように正しい向きで表示するには、
right, top の指定に従ってデータを配置すればよいことがわかります。
文字NRが正しく並んでいるが、右上に下向きの矢印がある

Orientation全部

ここでも画像データは赤矢印の向きに保存されているとします。表の左「Orientation指定なしの画像」は指定をつけなかった場合やOrientationを処理しないソフトウェアによる表示の様子です。

表の右「Orientationの値を指定した画像」はOrientationを処理した場合の表示です。

top,rightなどの処理がうまく働くことと、回転や反転で正しい向きにする操作を確認できます。

Orientation
指定なしの画像
translated
意味
(正しい向きにする操作例)
Orientation
の値を指定した画像
1 top, left
上辺を左から右へ
(そのまま)
2 top, right
上辺を右から左へ
(左右反転)
3 bottom, right
下辺を右から左へ
(180度回転)
4 bottom, left
下辺を左から右へ
(上下反転)
5 left, top
左辺を上から下へ
(左右反転後、時計
まわりに270度回転)
6 right, top
右辺を上から下へ
(時計まわりに90度回転)
7 right, bottom
右辺を下から上へ
(左右反転後、時計
まわりに90度回転)
8 left, bottom
左辺を下から上へ
(時計まわりに270度回転)

ひょっとしたら「書かれたNRの文字の上部(つまりはRの丸い方)にNからRの向きに矢印をかけばtranslated表記になっている!」と思いませんでしたか。残念ながら6,8が違います。

一般的なデジタルカメラで縦位置の写真を撮ると、右手を下に構えると6のright,top、右手を上に構えると8のleft,bottomになります。逆さまにして写した場合、3のbottom,rightになるのが筋ですが、そうならないカメラもあります。

スマートフォンでは撮影したスマートフォンで閲覧するならすべて1のtop,leftでよいと思いますが、横長の位置で撮ると6や8が付き、縦長に持って表示すると回転して縮小表示されるという腑に落ちない状態になる場合もあります。機種によっては予約値(1〜8以外は勝手に使ってはいけない)のはずの0を入れるものもあるようです。

Orientationの調査方法

カメラやスキャナのデータの他、加工ソフトで処理したものの現状を確認するために用いた方法です。

Orientation関係だけに興味がある場合は、次のが有効です。

adachi@ebook:imgorg$ exiv2 -g Orien -g Dimension DSC_1873.JPG 
Exif.Image.Orientation                       Short       1  top, left
Exif.Photo.PixelXDimension                   Short       1  5568
Exif.Photo.PixelYDimension                   Short       1  3712

これは exiv2 -pa で設定されている出力から3つのキーについての値を抽出したものです。3項目の"1"は多分shortの値がひとつ分という要素数なので、Orientationのplaneな値ではないです。

そこで、-P を使って項目を入れ替えます。-Pkvt はkey,vanilla,translated です。

adachi@ebook:imgorg$ exiv2 -Pkvt -g Orient -g Dimension DSC_1873.JPG
Exif.Image.Orientation                        1  top, left
Exif.Photo.PixelXDimension                    5568  5568
Exif.Photo.PixelYDimension                    3712  3712
adachi@ebook:imgorg$ exiv2 -Pkvt -g Orient -g Dimension DSC_1874.JPG
Exif.Image.Orientation                        8  left, bottom
Exif.Photo.PixelXDimension                    5568  5568
Exif.Photo.PixelYDimension                    3712  3712
adachi@ebook:imgorg$ exiv2 -Pkvt -g Orient -g Dimension DSC_1875.JPG
Exif.Image.Orientation                        6  right, top
Exif.Photo.PixelXDimension                    5568  5568
Exif.Photo.PixelYDimension                    3712  3712
adachi@ebook:imgorg$ exiv2 -Pkvt -g Orient -g Dimension DSC_1877.JPG
Exif.Image.Orientation                        1  top, left
Exif.Photo.PixelXDimension                    5568  5568
Exif.Photo.PixelYDimension                    3712  3712

1,8,6,3と並ぶはずが、最後は1に戻っています。このカメラは逆さに構えたときも3にはなりません。XDimension,YDimensionの値が同じなので、カメラを横位置で構えてもデータのスキャンの向きには影響はなく、Exif.Image.Orientationだけで済ませていることがわかります。

そして当然ながら、カメラでは2,4,5,7の反転を伴う状況は生まれません。

3のbottom, right になるカメラもあります。

adachi@ebook:imgorg$ exiv2 -Pkvt -g Orient -g Dimension P5030004.JPG 
Exif.Image.Orientation                        3  bottom, right
Exif.Photo.PixelXDimension                    4608  4608
Exif.Photo.PixelYDimension                    3456  3456

このスマートフォンは撮影時の構え方によってXDimension,YDimensionの値が入れ替わっています。この場合Orientationの値は1でいいのですが、なんと0になっています。

adachi@ebook:imgorg$ exiv2 -Pkvt -g Orient -g Dimension IMG_20200503_140545.jpg 
Exif.Image.Orientation                        0  (0)
Exif.Photo.PixelXDimension                    2336  2336
Exif.Photo.PixelYDimension                    4160  4160
Exif.Thumbnail.Orientation                    0  (0)
adachi@ebook:imgorg$ exiv2 -Pkvt -g Orient -g Dimension IMG_20200503_140607.jpg 
Exif.Image.Orientation                        0  (0)
Exif.Photo.PixelXDimension                    4160  4160
Exif.Photo.PixelYDimension                    2336  2336
Exif.Thumbnail.Orientation                    0  (0)

図形の回転と反転

まずは回転と反転の操作を整理して名前をつけておきます。ここでの操作は元に戻す操作ではなく、元の画像がどのように変換されるかに注目しています。

「なにもしない」という「操作」も加えています。名前は数学の習慣で"e"としています。

変換名 e σ1 σ2 σ3 τ1 τ2 τ3 τ4
変換操作 なし
変換結果
exiftran -9 -1 -2 -F -T -f -t

σ(シグマ)は書き方から回転をイメージしています。添字の1,2,3は90度回転を何回行うかということです。4で元に戻るので3までしかありません。

τ(タウ)はシグマの次の文字であることと、文字の形が鏡映の雰囲気を醸していることからこれにしました。添字の1,2,3,4は反転する軸を縦線から始めて時計回りに45度ずらすたびに+1しています。5以上は同じ反転の繰り返しになります。

変換の組み合わせ

図形の回転と反転(鏡映)には連続して行うと他の操作と同等の効果が得られるということがあります。exif-Orientationの元に戻す操作も異なる組み合わせ(と順序)で書かれている場合があります。

ここでは変換の組み合わせを一覧にしておきます。

⇩x2\x1⇨ e σ1 σ2 σ3 τ1 τ2 τ3 τ4
e e σ1 σ2 σ3 τ1 τ2 τ3 τ4
σ1 σ1 σ2 σ3 e τ2 τ3 τ4 τ1
σ2 σ2 σ3 e σ1 τ3 τ4 τ1 τ2
σ3 σ3 e σ1 σ2 τ4 τ1 τ2 τ3
τ1 τ1 τ4 τ3 τ2 e σ3 σ2 σ1
τ2 τ2 τ1 τ4 τ3 σ1 e σ3 σ2
τ3 τ3 τ2 τ1 τ4 σ2 σ1 e σ3
τ4 τ4 τ3 τ2 τ1 σ3 σ2 σ1 e

表の上に並べた変換(x1⇨)を先に行い、左に並べた変換(⇩x2)を後にすると、交点の操作と同等になるように書いてあります。適用する操作の順番で結果が違いますから注意が必要です。式で表現する場合は後に適用する操作を左に追加していくので x2x1 と書きます。

たとえば、exif-orientationの 5 left-top は元に戻す方法に「左右反転、時計まわりに270度回転」とありますが、

τ4 = σ3τ1

と書きます。この操作を逆にすると

τ2 = τ1σ3

になります。

また、表から2つ組み合わせて τ4 となるのは、たくさんあることがわかります。

τ4 = σ3τ1 = σ2τ2 = σ1τ3
   = τ1σ1 = τ2σ2 = τ3σ3