marcwoozie blog

都内のwebエンジニア2年目です

webからiPhoneで撮影した画像をアップロードしたら回転した

表題の通りスマホサイトなどで、
iPhoneで撮影した画像をアップロードしたら回転してアップされてしまったのでその時の対処を書きます。




とりあえずGoogle先生に聞いてみたところ

iPhoneiPadではタテにもって写真をとった場合でも、内部的に横長のJPGでExifのOrientationタグに回転角度を埋め込んで保存しているという、「なぜ、そんなことをするの?」というツッコミを入れたくなるようなことをiPhone様がしている(して頂いている)と知りました。



Exifってなんだよ。。。?



わからないことはGoogle先生に聞けと学校で教わったので(本当です)またGoogle先生に聞きます


Exchangeable image file format - Wikipedia



Google先生Wikipediaさんによると、どうも画像のmeta情報ということが分かりました。
どうやらiPhoneで撮影した写真のmeta情報に「水平・垂直方向の単位あたり」という情報もあって、これが「Orientation」なんだな〜となんとなく認識しときます。


次にOrientationがどんな値なのかググると、すぐに答えにたどり着きました。

下記のとおり、1〜8まであるようです。

1     回転無し
2     左右反転
3     180°回転
4     上下反転
5     時計回りに90°回転した後、左右反転
6     時計回りに90°回転
7     反時計回りに90°回転した後、左右反転
8     反時計回りに90°回転




ここまでわかったので、iPhoneで撮影した画像のExif情報を取得しようと試みて、またググると、

exif_read_dataという今の僕にぴったりすぎる関数を発見。

PHP: exif_read_data - Manual



さっそく実装に移りたいと思います。



僕の働いている会社ではFuelPHPをよく使わせていただいていて、今回もFuelPHPで実装してるのでFuelPHPのclassありきで記述していきます。(アップロード部分は省きます)

<?php

  public static function upload_icon() {
    // Upload classでアップロード処理
    foreach(Upload::get_files() as $saved_file) {
      self::create_thumb($saved_file);
    }
  }

  public static function create_thumb($saved_file)
  {
    $thumb_size = array(
      "width"  => "150",
      "height" => "150"
    );

    $image = Image::load("assets/img/icon/" . $saved_file["saved_as"]);
    $filename = DOCROOT."assets/img/icon/" . $saved_file["saved_as"];

    if( $image->extension() == "jpg" && self::is_upload_iphone($filename) ){
      // iPhoneで撮影した画像なら時計回りに90度回転する
      $image->rotate(90);
    }
    return $image->crop_resize($thumb_size["width"], $thumb_size["height"])
                          ->save("assets/img/icon/resize_" . $save_file["saved_as"]);
  }

  public static function is_upload_iphone($filename) {
    $exif = exif_read_data( $filename );
    if( !empty($exif["Orientation"]) && $exif["Orientation"] == 6 ){
      return true;
    } else {
      return false;
    }
  }


アップロード済のアイコン画像をFuelのImageクラスで取得して、

サムネイルを作る際にiPhoneで撮影した画像であれば時計回りに90度回転するといった感じですが、
iPhoneで撮影した画像のOrientationは6のようだったので6限定でrotateをかけていますが、

例外が出てきた時の処理などしていないので、よろしくない部分が多々あるとは思いますが(メソッド名にupload_iconとか嫌ですね)とりあえず一旦こんな感じで対応しました。



追記として、稼働しているサーバーにも自分のPCにもImageMagickが入っていなかったのでこの方法をとりました。
ImageMagickが入っている環境であれば、他の方法もあるようです。(最初にググったらそっちばかり出てきました)