読者です 読者をやめる 読者になる 読者になる

lxyuma BLOG

開発関係のメモ

ImageMagickでjpegの縦横(exifのOrientation)情報を元に画像を回転する

やりたい事

元々、iphonesafariで、写真uploadできる機能を作りたかった。 ※ちなみに、iOS6からsafariでも画像up可

upする時に、jpegに入ってる重力の方向を元に自動で画像を回転して保存したい。

概要

この記事では以下の話を書いて行く。

ImageMagickruby用のクライアントRmagick使うが、他言語も殆ど同じなんじゃないかと

jpegexif

画像ファイルのフォーマットとして、exif(Exchangeable digicame-exif file format)規格がある。

Exifは一般的なjpeg/tiffファイルフォーマットに準拠している。

このExifには、タグが幾つか準備されていて、そこに、以下の様な情報が入ってる。(沢山あるので一部のみ)

  • 画像の幅(imageWidth)
  • 画素の並び(Orientation)
  • 解像度(XResolution)
  • メーカ(Make)
  • 撮影者(Artist)
  • exifdpointer(露出時間/F値/絞り/露出補正/シャッタースピード等の情報へのポインタ)
  • GPSInfoIFDPointer(GPS情報へのポインタ)

※ちなみに、先日のPC遠隔操作事件で、真犯人からの猫の写真が江ノ島だと特定できたのは、このExif情報から、だそう。(link

今から話すのは、上記、上から二つ目のOrientationの話。

なお、以下のサイトにExif規格についての詳しい説明がある。(参考にさせて頂いた)

Orientation

jpegの中のOrientationという属性に、一桁の数値が入っていて、

それぞれ、方向を示していて、以下の回転操作が必要。

  • 1:そのまま
  • 2:水平反転
  • 3:180度回転
  • 4:180度回転して水平反転
  • 5:時計回りに90度回転して水平反転
  • 6:時計回りに90度回転
  • 7:時計回りに270度回転して水平反転
  • 8:時計回りに270度回転

※水平反転が必要になるケースは、おそらく、自撮りする時に、左右反転してると思われる(未確認だが)

詳しくは、以下。

RMagickでorientation

RMagick(rubyImageMagick用クライアント)を使ってOrientation見てみる。

image = File.open('/***/your.jpg').read

m_image = Magick::Image.from_blob(image).shift

# 自分で、exif属性ほじっても取れるが
m_image.get_exif_by_entry("Orientation")
#=> [["Orientation", "1"]]

# orientationでも取得できる。Typeも分かり易いので、こっちが良い。
m_image.orientation
#=> TopLeftOrientation=1

# ちなみに、ここで表示される型のクラスの値を見てみると、以下が定義されている
Magick::OrientationType.values
# => [
# UndefinedOrientation=0,
# TopLeftOrientation=1,
# TopRightOrientation=2,
# BottomRightOrientation=3,
# BottomLeftOrientation=4,
# LeftTopOrientation=5,
# RightTopOrientation=6,
# RightBottomOrientation=7,
# LeftBottomOrientation=8,
# TopLeftOrientation=1,
# TopLeftOrientation=1,
# TopLeftOrientation=1]

回転を実装する。

さて、ここからが、本題。

皆、ガリガリ実装してるから、俺も書かなきゃ行けないのかと思ってた。

rubyでガリガリ実装して、ブラウザ上ではバッチリ動いた後、

iOS7のsafariで動かすと、なんか、方向がおかしい。

色々、試した結果、どうやら、iOS7は、safari上への画像表示時に、

exif情報を元に、画像を勝手に回転しているみたい。

※しかも、その時、一部のcssを無視してくれるので、表示が若干崩れる(^ ^ #)

なので、画像を回転した後に、ちゃんと、orientationを1にしないと、意図した表示にならない。

inner_img.orientation = Magick::OrientationType.values[1]

自力で書くなら、上記忘れずに。

※そもそも、facebookや他の大手サービスでは、セキュリティやプライバシの観点からExif情報を削除している。家で撮ったら家の緯度経度ももろばれにもなるので、そもそも削除するべき。

auto_orient

所で、調べて行くと、どうやら、rmagickには、auto_orientというメソッドがある。

これを使うと、勝手に回転してくれるらしい。(結局、ガリガリ自分で実装しなくて良かった)

m_image.auto_orient!
# auto_orientとauto_orient!(破壊的メソッド)がある。

どうやら、ImageMagickのオプションにある、--auto-orientと同じ動きをしてるっぽい。

ImageMagick側のドキュメントによると、--auto-orientはresetもすると書いているので、上記のorientation=1も書かなくて良いかも(これは未確認)

まとめ

  • iOSsafariはOrientationを元に勝手に画像を回転してしまうっぽい
    • 画像を回転したら、Orientationのresetを忘れずに
    • そもそも、Exif情報には緯度経度等含まれるので、削除するべき
  • ImageMagickにはauto-orientという自動で適切に回転してくれるオプションもある

以上。