スマートフォンで撮影した画像があさっての方へ向くという問題

こんにちは。
開発チームのワイルド担当、まんだいです。
最近では、高画質な写真が、スマートフォンで手軽に撮れる時代になり、一眼レフの出番がめっきり減った感がありますね。
子供の写真も、手軽に撮ってクラウドに保存するというのが当たり前になってきました。
そんな画像をシステムで扱った時に、何故か向きが揃わないという事件が発生した時の対処方法を共有します。
画像の取り扱いには問題なかった!
画像の取り扱いに問題があったかというと、そこは大丈夫でした。
FuelPHPのアップロードモジュールを使っていたので、手を入れる余地はありませんでした。
画像をURLを直接指定して表示する分には、問題ないのに、HTMLタグを通じて読み込むと反転したり・・・。
となると、画像そのものの問題~!?
開発環境にあった画像では、特に問題はなく、現象が発生する画像をPCからアップロードすると、やはり変な方向を向きます。
画像はスマートフォンで撮影したjpeg画像でしか起きません。
するってぇと、あれですかい。Exif情報が悪さしてるんでしょうか、という事でExifにそれ系の情報がないか、確認しました。
PHPで確認する場合は、exif_read_data関数を使います。
$exif = exif_read_data('/path/to/hogehoge.jpg');
すると、ズラッと出てきました。
array (
'FileName' => 'hogehoge.jpg',
'FileDateTime' => 1478746964,
'FileSize' => 1510220,
'FileType' => 2,
'MimeType' => 'image/jpeg',
'SectionsFound' => 'ANY_TAG, IFD0, THUMBNAIL, EXIF, GPS',
'COMPUTED' =>
array (
'html' => 'width="2592" height="1936"',
'Height' => 1936,
'Width' => 2592,
'IsColor' => 1,
'ByteOrderMotorola' => 1,
'ApertureFNumber' => 'f/2.4',
'Thumbnail.FileType' => 2,
'Thumbnail.MimeType' => 'image/jpeg',
),
'Make' => 'Apple',
'Model' => 'iPad mini 2',
'Orientation' => 6,
'XResolution' => '72/1',
'YResolution' => '72/1',
'ResolutionUnit' => 2,
'Software' => '9.3.2',
'DateTime' => '2016:10:10 15:52:37',
'YCbCrPositioning' => 1,
'Exif_IFD_Pointer' => 206,
'GPS_IFD_Pointer' => 1030,
'THUMBNAIL' => array (
'Compression' => 6,
'XResolution' => '72/1',
'YResolution' => '72/1',
'ResolutionUnit' => 2,
'JPEGInterchangeFormat' => 1434,
'JPEGInterchangeFormatLength' => 9014,
),
'ExposureTime' => '1/1506',
'FNumber' => '12/5',
'ExposureProgram' => 2,
'ISOSpeedRatings' => 32,
'ExifVersion' => '0221',
'DateTimeOriginal' => '2016:10:10 15:52:37',
'DateTimeDigitized' => '2016:10:10 15:52:37',
'ComponentsConfiguration' => '^A^B^C' . "\0" . '',
'ShutterSpeedValue' => '12045/1141',
'ApertureValue' => '4845/1918',
'BrightnessValue' => '14471/1420',
'ExposureBiasValue' => '0/1',
'MeteringMode' => 5,
'Flash' => 32,
'FocalLength' => '33/10',
'SubjectLocation' =>
...(中略)...
)
スマートフォンのExif情報は、かなり詳細に記録されており、画像サイズ、撮影日時、GPS(ONの場合)、シャッタースピード、F値、などなど、これだけでも相当なものです。
情報の量が多すぎるような気もするのですが、この中に目的のデータが・・・!
それが、「Orientation」の部分です。
Orientation情報を元に、画像回転を補正する
画像のExif情報に関して、詳しい情報を探していると、一般社団法人 電子情報技術産業協会の資料というのを見つけました。
めちゃくちゃ詳しく記載されている反面、なかなか読み手の読解力を試してくる内容になっています。
画像方向の項を元に、コーディングすればいいだけですね。
分かるかいな。
ということで、一覧表を作りました。
反転させる系の画像に出会ったことはないんですが、資料を読み解く限りでは、そうするようです。
よく出てくるのは、1、3、6、8あたりでしょうか。手元にある画像を見てみると、ランドスケープの場合、3が、ポートレートの場合、6が設定される事が多いようです。
3というと180度回転なので、横向きに構えて撮影した(ランドスケープなので)けれど、スマートフォン的には、逆さまに撮影されたという認識という訳ですね。
(iPhoneでいうと、HOMEボタンの左右が逆の状態)
また、6というと90度回転で、画像の向きはポートレートなので、スマートフォンを縦向きに構えて撮ったという様子が窺い知れます。ここまで分かれば、後はExif情報通りに画像を回転させ、保存してやるだけです。回転(rotate)、反転(flip)は、FuelPHPのImageクラスで簡単に対応できます。
ただ、Exif情報の書き換えには、PELというライブラリが必要です。Exif情報は不要、という場合は、単にOrientationの情報に基いて回転させて、上書きしてしまっても良さそうです。回転処理だけして、Exif情報は未編集のままだと、収集がつかなくなりますので要注意です。
以上です。
| Orientationの値 | 修正 |
|---|---|
| 1 | 未加工でOK |
| 2 | 画像を水平方向に反転 |
| 3 | 画像を180度時計回りに回転させる |
| 4 | 画像を垂直方向に反転 |
| 5 | 画像を90度時計回りに回転させ、水平方向に反転 |
| 6 | 画像を90度時計回りに回転させる |
| 7 | 画像を90度反時計回りに回転させ、水平方向に反転 |
| 8 | 画像を90度反時計回りに回転させる |
1