LoginSignup
5
9

More than 5 years have passed since last update.

PHPでEXIFのOrientationを元に画像を回転

Posted at

EXIFのOrientationを見て画像を回転させる処理です。
訳あってPHP5系で実装しましたが、PHP7系でも動くと思います。

注意点としては、rotate()関数内でメモリを大量に使用するためmemory_limit()で上限を上げています。
「allowed memory size」が発生するケースもあったので、余裕をもって設定しましょう。
※ 1.7MBの画像で128MBを使い切ったケースがありました。

このあたりでメモリ使用量が一気に上昇します。
imagecreatefromstring()
imagerotate()
imagejpeg()
imagepng()
imagegif()

Image.php
<?php
class Image {

    /**
     * 画像(バイナリ)のEXif情報を元に回転する
     */
    public function rotateFromBinary($binary) {
        $exif_data = $this->getExifFromBinary($binary);
        if (empty($exif_data['Orientation']) || in_array($exif_data['Orientation'], [1, 2])) {
            return $binary;
        }
        return $this->rotate($binary, $exif_data);
    }

    /**
     * バイナリデータからexif情報を取得
     */
    private function getExifFromBinary($binary) {
        $temp = tmpfile();
        fwrite($temp, $binary);
        fseek($temp, 0);

        $meta_data = stream_get_meta_data($temp);
        $exif_data = @exif_read_data($meta_data['uri']);

        fclose($temp);
        return $exif_data;
    }

    /**
     * 画像を回転させる
     */
    private function rotate($binary, $exif_data) {
        ini_set('memory_limit', '256M');

        $src_image = imagecreatefromstring($binary);

        $degrees = 0;
        $mode    = '';
        switch($exif_data['Orientation'])
        {
            case 2: // 水平反転
                $mode = IMG_FLIP_VERTICAL;
                break;
            case 3: // 180度回転
                $degrees = 180;
                break;
            case 4: // 垂直反転
                $mode = IMG_FLIP_HORIZONTAL;
                break;
            case 5: // 水平反転、 反時計回りに270回転
                $degrees = 270;
                $mode    = IMG_FLIP_VERTICAL;
                break;
            case 6: // 反時計回りに270回転
                $degrees = 270;
                break;
            case 7: // 反時計回りに90度回転(反時計回りに90度回転) 水平反転
                $degrees = 90;
                $mode    = IMG_FLIP_VERTICAL;
                break;
            case 8: // 反時計回りに90度回転(反時計回りに90度回転)
                $degrees = 90;
                break;
        }

        if (!empty($mode))
        {
            imageflip($src_image, $mode);
        }
        if ($degrees > 0)
        {
            $src_image = imagerotate($src_image, $degrees, 0);
        }

        ob_start();
        if (empty($exif_data['MimeType']) || $exif_data['MimeType'] == 'image/jpeg') {
            imagejpeg($src_image);
        } elseif ($exif_data['MimeType'] == 'image/png') {
            imagepng($src_image);
        } elseif ($exif_data['MimeType'] == 'image/gif') {
            imagegif($src_image);
        }
        imagedestroy($src_image);
        return ob_get_clean();
    }
 }

// 使い方
$Image = new Image();
$binary = $Image->rotateFromBinary(file_get_contents($path_to_file));

参考URL

http://php.o0o0.jp/article/php-orientation
http://blog.diginnovation.com/archives/1104/

5
9
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
9