ImageMagickでjpegの縦横(exifのOrientation)情報を元に画像を回転する
やりたい事
元々、iphoneのsafariで、写真uploadできる機能を作りたかった。 ※ちなみに、iOS6からsafariでも画像up可
upする時に、jpegに入ってる重力の方向を元に自動で画像を回転して保存したい。
概要
この記事では以下の話を書いて行く。
- jpegのexif情報について説明
- ImageMagickの画像変換処理(auto_orient)で楽する
- iOSのsafariの特殊な動作
※ImageMagickのruby用のクライアントRmagick使うが、他言語も殆ど同じなんじゃないかと
jpegのexif
画像ファイルのフォーマットとして、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(rubyのImageMagick用クライアント)を使って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も書かなくて良いかも(これは未確認)
まとめ
- iOSのsafariはOrientationを元に勝手に画像を回転してしまうっぽい
- 画像を回転したら、Orientationのresetを忘れずに
- そもそも、Exif情報には緯度経度等含まれるので、削除するべき
- ImageMagickにはauto-orientという自動で適切に回転してくれるオプションもある
以上。