IPhoneやらAndroidで取った写真のExifをみて画像を回転させるのをたまーに実装するんですが、滅多にすることなくて、やる度に仕様調べないと思い出せないので、ブログに書いておこうと思います。
画像をどう回転させれば良いかは写真についてくるAPP1セグメントに定義されているTIFFフォーマットの0thIFDにあるOrientationタグみると解ります。
*5と7が逆だったのをブコメで指摘頂いて訂正しました。下記のpdfドキュメントに誤りがあったので修正版に差し替えています(2013/9/2)
まぁちゃんと理解はしてないんですけど、仕様はCIPAにあるhttp://www.cipa.jp/hyoujunka/kikaku/pdf/DC-008-2010_J.pdfhttp://www.cipa.jp/hyoujunka/kikaku/pdf/DC-008-2012_J.pdfに定義されています。これみてもいまいち解らないので、図解してあるこっちが解り易かったです。
GPS情報もExifから取れるので、必要な方は仕様をみてみると良いと思いますが、すでにライブラリ沢山あると思うので読まなくても大丈夫だと思います。
で、このOrientationタグの中身が数値で、どれがどれだかすぐに忘れます。
Orientation=1: そのまま Orientation=2: 水平反転 Orientation=3: 180度回転 Orientation=4: 180度回転て水平反転 Orientation=5: 時計回りに90度回転して水平反転 Orientation=6: 時計回りに90度回転 Orientation=7: 時計回りに270度回転して水平反転 Orientation=8: 時計回りに270度回転
図にしたのが上にはったpdfにかいてあったので抜粋(2013/9/2差し替え)

これをimage magicのconvertコマンドでやると、こんな感じになります。
Orientation=1: そのまま
Orientation=2: convert -flop original.jpg flop.jpg
Orientation=3: convert -rotate 180 original.jpg rotate180.jpg
Orientation=4: convert -rotate 180 -flop original.jpg rotate180-flop.jpg または convert -flip original.jpg flip.jpg
Orientation=5: convert -rotate 90 -flop original.jpg rotate90-flop.jpg または convert -transpose original.jpg transpose.jpg
Orientation=6: convert -rotate 90 original.jpg rotate90.jpg
Orientation=7: convert -rotate 270 -flop original.jpg rotate270-flop.jpg または convert -transverse original.jpg transverse.jpg
Orientation=8: convert -rotate 270 original.jpg rotate270.jpg
transposeとtransverseはちょっと解り辛いですね。最初5と7を取り違えちゃいました。
実際に画像でやってみたほうが解りやすそうなので、先日コンプしたLINEシールの画像つかって試して見ました(これ使うと四隅が解りやすい)
1 | 6 | 3 | 8 |
---|---|---|---|
![]() |
![]() |
![]() |
![]() |
2 | 5 | 4 | 7 |
![]() |
![]() |
![]() |
![]() |
最後にPerlでの実装例の一部を乗っけておきます。
こっちは、ImageMagicで変換するパターン
if (substr($org_data, 0, 2) eq "\xFF\xD8") { # if jpeg
my $img_meta = Image::MetaData::JPEG->new(\$org_data);
my $exif_image_data = $img_meta->get_Exif_data('IMAGE_DATA', 'TEXTUAL');
$jpeg_orient = ($exif_image_data ? $exif_image_data->{Orientation}->[0] : 1);
if ($jpeg_orient == 2) {
$img->Flop();
} elsif ($jpeg_orient == 3) {
$img->Rotate(180);
} elsif ($jpeg_orient == 4) {
$img->Flip();
} elsif ($jpeg_orient == 5) {
$img->Transpose();
} elsif ($jpeg_orient == 6) {
$img->Rotate(90);
} elsif ($jpeg_orient == 7) {
$img->Transverse();
} elsif ($jpeg_orient == 8) {
$img->Rotate(270);
}
}
もう一つImagerを使ったケース。やっている事は変わりません
if (substr($image, 0, 2) eq "\xFF\xD8") { # if jpeg
my $img_meta = new Image::MetaData::JPEG( \$image ) or return $im;
my $im = Imager->new;
$im->read(data => $image) or return undef;
my $exif_data = $img_meta->get_Exif_data('IMAGE_DATA', 'TEXTUAL');
my $jpeg_orient = ($exif_data ? $exif_data->{Orientation}->[0] : 1);
if ( $jpeg_orient == 2 ) {
$im->flip(dir=>"h");
} elsif ( $jpeg_orient == 3 ) {
$im = $im->rotate(right=>180);
} elsif ( $jpeg_orient == 4 ) {
$im->flip(dir=>"v");
} elsif ( $jpeg_orient == 5 ) {
$im = $im->rotate(right=>90);
$im->flip(dir=>"v");
} elsif ( $jpeg_orient == 6 ) {
$im = $im->rotate(right=>90);
} elsif ( $jpeg_orient == 7 ) {
$im = $im->rotate(right=>270);
$im->flip(dir=>"v");
} elsif ( $jpeg_orient == 8 ) {
$im = $im->rotate(right=>270);
}
}
コメント