GD библиотека загрузить изображение вращения - PullRequest
0 голосов
/ 04 января 2019

Я использую библиотеку GD для загрузки / обработки фотографий, но при загрузке фотографии через Android или какой-либо мобильный телефон фотографии загружаются некорректно в качестве ориентации.У меня есть сайт, где пользователи могут загружать фотографии с мобильных устройств, но все фотографии, загруженные с мобильных телефонов, показывают 90 градусов влево при загрузке.

У меня сейчас проблема exeif, но я попытался с помощью плагинано не работает.Любая помощь рекомендуется.

Поделитесь моим кодом скрипта: CImageHandler.php

/**
 * Image handler
 * @author  Yaroslav Pelesh aka Tokolist http://tokolist.com
 * @link    https://github.com/tokolist/yii-components
 * @version 1.2
 * @license http://www.opensource.org/licenses/mit-license.php The MIT License
 */
ini_set('memory_limit', '8192M'); 
class CImageHandler extends CApplicationComponent
{
    private $originalImage = null;
    private $image = null;

    private $format = 0;

    private $width = 0;
    private $height = 0;

    private $mimeType = '';

    private $fileName = '';

    public $transparencyColor = [0, 0, 0];


    const IMG_GIF = 1;
    const IMG_JPEG = 2;
    const IMG_PNG = 3;

    const CORNER_LEFT_TOP = 1;
    const CORNER_RIGHT_TOP = 2;
    const CORNER_LEFT_BOTTOM = 3;
    const CORNER_RIGHT_BOTTOM = 4;
    const CORNER_CENTER = 5;
    const CORNER_CENTER_TOP = 6;
    const CORNER_CENTER_BOTTOM = 7;
    const CORNER_LEFT_CENTER = 8;
    const CORNER_RIGHT_CENTER = 9;

    const FLIP_HORIZONTAL = 1;
    const FLIP_VERTICAL = 2;
    const FLIP_BOTH = 3;


    public function getImage()
    {
        return $this->image;
    }

    public function getFormat()
    {
        return $this->format;
    }

    public function getWidth()
    {
        return $this->width;
    }

    public function getHeight()
    {
        return $this->height;
    }

    public function getMimeType()
    {
        return $this->mimeType;
    }

    public function __destruct()
    {
        $this->freeImage();
    }

    private function freeImage()
    {
        if (is_resource($this->image)) {
            imagedestroy($this->image);
        }

        if ($this->originalImage !== null) {
            if (is_resource($this->originalImage['image'])) {
                imagedestroy($this->originalImage['image']);
            }
            $this->originalImage = null;
        }
    }

    private function checkLoaded()
    {
        if (!is_resource($this->image)) {
            throw new Exception('Load image first');
        }
    }

    private function loadImage($file)
    {
        $result = [];


        if ($imageInfo = @getimagesize($file)) {
            $result['width'] = $imageInfo[0];
            $result['height'] = $imageInfo[1];

            $result['mimeType'] = $imageInfo['mime'];

            switch ($result['format'] = $imageInfo[2]) {
                case self::IMG_GIF:
                    if(file_exists($file)) {
                        $gd = @imagecreatefromstring(file_get_contents($file));    
                        if ($gd === false) {
                            throw new Exception ('Invalid image gif format');
                        } else {
                            if ($result['image'] = imagecreatefromgif($file)) {
                                return $result;
                            } else {
                                throw new Exception('Invalid image gif format');
                            }
                        }
                    } else {
                        throw new Exception('Invalid image gif format');
                    }
                    break;
                case self::IMG_JPEG:
                    if(file_exists($file)) {
                        $gd = @imagecreatefromstring(file_get_contents($file));    
                        if ($gd === false) {
                            throw new Exception ('Invalid image jpeg format');
                        } else {
                            /*

                            //Read the JPEG image Exif data to get the Orientation value
                            if (function_exists('exif_read_data')) {
                                $exif = exif_read_data($file);
                                $orientation = @$exif['IFD0']['Orientation'];
                                if (!$orientation) {
                                    $orientation = @$exif['Orientation'];
                                }
                                if(!$orientation) return;
                                $source = @imagecreatefromjpeg($file);
                                if(!$source) return;
                                switch ($orientation) {
                                    case 1: // nothing
                                        break;
                                    case 2: // horizontal flip
                                        imageflip($source, IMG_FLIP_HORIZONTAL);
                                        break;
                                    case 3: // 180 rotate left
                                        $modifiedImage = imagerotate($source, 180, 0);
                                        imagejpeg($modifiedImage, $file, 90);  //save output to file system at full quality
                                        break;
                                    case 4: // vertical flip
                                        imageflip($source, IMG_FLIP_VERTICAL);
                                        break;
                                    case 5: // vertical flip + 90 rotate right
                                        imageflip($source, IMG_FLIP_VERTICAL);
                                        $modifiedImage = imagerotate($source, -90, 0);
                                        imagejpeg($modifiedImage, $file, 90);  //save output to file system at full quality
                                        break;
                                    case 6: // 90 rotate right
                                        $modifiedImage = imagerotate($source, -90, 0);
                                        imagejpeg($modifiedImage, $file, 90);  //save output to file system at full quality
                                        break;
                                    case 7: // horizontal flip + 90 rotate right
                                        imageflip($source, IMG_FLIP_HORIZONTAL);
                                        $modifiedImage = imagerotate($source, -90, 0);
                                        imagejpeg($modifiedImage, $file, 90);  //save output to file system at full quality
                                        break;
                                    case 8:    // 90 rotate left
                                        $modifiedImage = imagerotate($source, 90, 0);
                                        imagejpeg($modifiedImage, $file, 90);  //save output to file system at full quality    
                                        break;
                                }
                            }
                            //Read the JPEG image Exif data to get the Orientation value
                            */
                            if ($result['image'] = @imagecreatefromjpeg($file)) {
                                return $result;
                            } else {
                                throw new Exception('Invalid image jpeg format');
                            }
                        }
                    } else {
                        throw new Exception('Invalid image jpeg format');
                    }
                    break;
                case self::IMG_PNG:
                    if(file_exists($file)) {
                        $gd = @imagecreatefromstring(file_get_contents($file));    
                        if ($gd === false) {
                            throw new Exception ('Invalid image png format');
                        } else {
                            if ($result['image'] = imagecreatefrompng($file)) {
                                return $result;
                            } else {
                                throw new Exception('Invalid image png format');
                            }
                        }
                    } else {
                        throw new Exception('Invalid image png format');
                    }
                    break;
                default:
                    throw new Exception('Not supported image format');
            }
        } else {
            throw new Exception('Invalid image file');
        }


    }

    protected function initImage($image = false)
    {
        if ($image === false) {
            $image = $this->originalImage;
        }

        $this->width = $image['width'];
        $this->height = $image['height'];
        $this->mimeType = $image['mimeType'];
        $this->format = $image['format'];

        //Image
        if (is_resource($this->image))
            imagedestroy($this->image);
        //10-08-2018
        $this->image = imagecreatetruecolor($this->width, $this->height);
        $this->preserveTransparency($this->image);
        imagecopy($this->image, $image['image'], 0, 0, 0, 0, $this->width, $this->height);
    }

    /**
     * @param $file
     *
     * @return CImageHandler
     * @throws Exception
     */
    public function load($file)
    {
        $this->freeImage();

        if (($this->originalImage = $this->loadImage($file))) {
            $this->initImage();
            $this->fileName = $file;


            return $this;
        } else {
            return false;
        }
    }

    public function reload()
    {
        $this->checkLoaded();
        $this->initImage();

        return $this;
    }

    private function preserveTransparency($newImage)
    {
        switch ($this->format) {
            case self::IMG_GIF:
                $color = imagecolorallocate(
                    $newImage,
                    $this->transparencyColor[0],
                    $this->transparencyColor[1],
                    $this->transparencyColor[2]
                );

                imagecolortransparent($newImage, $color);
                imagetruecolortopalette($newImage, false, 256);
                break;
            case self::IMG_PNG:
                imagealphablending($newImage, false);

                $color = imagecolorallocatealpha(
                    $newImage,
                    $this->transparencyColor[0],
                    $this->transparencyColor[1],
                    $this->transparencyColor[2],
                    0
                );

                imagefill($newImage, 0, 0, $color);
                imagesavealpha($newImage, true);
                break;
        }
    }

    public function resize($toWidth, $toHeight, $proportional = true)
    {
        $this->checkLoaded();

        $toWidth = $toWidth !== false ? $toWidth : $this->width;
        $toHeight = $toHeight !== false ? $toHeight : $this->height;

        if ($proportional) {
            $newHeight = $toHeight;
            $newWidth = round($newHeight / $this->height * $this->width);


            if ($newWidth > $toWidth) {
                $newWidth = $toWidth;
                $newHeight = round($newWidth / $this->width * $this->height);
            }
        } else {
            $newWidth = $toWidth;
            $newHeight = $toHeight;
        }

        $newImage = imagecreatetruecolor($newWidth, $newHeight);

        $this->preserveTransparency($newImage);

        imagecopyresampled($newImage, $this->image, 0, 0, 0, 0, $newWidth, $newHeight, $this->width, $this->height);


        imagedestroy($this->image);

        $this->image = $newImage;
        $this->width = $newWidth;
        $this->height = $newHeight;

        return $this;

    }

    public function thumb($toWidth, $toHeight, $proportional = true)
    {
        $this->checkLoaded();

        if ($toWidth !== false)
            $toWidth = min($toWidth, $this->width);

        if ($toHeight !== false)
            $toHeight = min($toHeight, $this->height);


        $this->resize($toWidth, $toHeight, $proportional);

        return $this;

    }

    public function watermark($watermarkFile, $offsetX, $offsetY, $corner = self::CORNER_RIGHT_BOTTOM, $zoom = false)
    {

        $this->checkLoaded();

        if ($wImg = $this->loadImage($watermarkFile)) {

            $posX = 0;
            $posY = 0;

            $watermarkWidth = $wImg['width'];
            $watermarkHeight = $wImg['height'];

            if ($zoom !== false) {
                $dimension = round(max($this->width, $this->height) * $zoom);

                $watermarkHeight = $dimension;
                $watermarkWidth = round($watermarkHeight / $wImg['height'] * $wImg['width']);

                if ($watermarkWidth > $dimension) {
                    $watermarkWidth = $dimension;
                    $watermarkHeight = round($watermarkWidth / $wImg['width'] * $wImg['height']);
                }
            }

            switch ($corner) {
                case self::CORNER_LEFT_TOP:
                    $posX = $offsetX;
                    $posY = $offsetY;
                    break;
                case self::CORNER_RIGHT_TOP:
                    $posX = $this->width - $watermarkWidth - $offsetX;
                    $posY = $offsetY;
                    break;
                case self::CORNER_LEFT_BOTTOM:
                    $posX = $offsetX;
                    $posY = $this->height - $watermarkHeight - $offsetY;
                    break;
                case self::CORNER_RIGHT_BOTTOM:
                    $posX = $this->width - $watermarkWidth - $offsetX;
                    $posY = $this->height - $watermarkHeight - $offsetY;
                    break;
                case self::CORNER_CENTER:
                    $posX = floor(($this->width - $watermarkWidth) / 2);
                    $posY = floor(($this->height - $watermarkHeight) / 2);
                    break;
                case self::CORNER_CENTER_TOP:
                    $posX = floor(($this->width - $watermarkWidth) / 2);
                    $posY = $offsetY;
                    break;
                case self::CORNER_CENTER_BOTTOM:
                    $posX = floor(($this->width - $watermarkWidth) / 2);
                    $posY = $this->height - $watermarkHeight - $offsetY;
                    break;
                case self::CORNER_LEFT_CENTER:
                    $posX = $offsetX;
                    $posY = floor(($this->height - $watermarkHeight) / 2);
                    break;
                case self::CORNER_RIGHT_CENTER:
                    $posX = $this->width - $watermarkWidth - $offsetX;
                    $posY = floor(($this->height - $watermarkHeight) / 2);
                    break;
                default:
                    throw new Exception('Invalid $corner value');
            }

            imagecopyresampled(
                $this->image,
                $wImg['image'],
                $posX,
                $posY,
                0,
                0,
                $watermarkWidth,
                $watermarkHeight,
                $wImg['width'],
                $wImg['height']
            );


            imagedestroy($wImg['image']);

            return $this;
        } else {
            return false;
        }
    }


    public function flip($mode)
    {
        $this->checkLoaded();

        $srcX = 0;
        $srcY = 0;
        $srcWidth = $this->width;
        $srcHeight = $this->height;

        switch ($mode) {
            case self::FLIP_HORIZONTAL:
                $srcX = $this->width - 1;
                $srcWidth = -$this->width;
                break;
            case self::FLIP_VERTICAL:
                $srcY = $this->height - 1;
                $srcHeight = -$this->height;
                break;
            case self::FLIP_BOTH:
                $srcX = $this->width - 1;
                $srcY = $this->height - 1;
                $srcWidth = -$this->width;
                $srcHeight = -$this->height;
                break;
            default:
                throw new Exception('Invalid $mode value');
        }

        $newImage = imagecreatetruecolor($this->width, $this->height);
        $this->preserveTransparency($newImage);

        imagecopyresampled($newImage, $this->image, 0, 0, $srcX, $srcY, $this->width, $this->height, $srcWidth, $srcHeight);

        imagedestroy($this->image);

        $this->image = $newImage;
        //dimensions not changed

        return $this;
    }

    public function rotate($degrees)
    {
        $this->checkLoaded();

        $degrees = (int)$degrees;
        $this->image = imagerotate($this->image, $degrees, 0);

        $this->width = imagesx($this->image);
        $this->height = imagesy($this->image);

        return $this;
    }

    public function crop($width, $height, $startX = false, $startY = false)
    {
        $this->checkLoaded();

        $width = (int)$width;
        $height = (int)$height;

        //Centered crop
        $startX = $startX === false ? floor(($this->width - $width) / 2) : intval($startX);
        $startY = $startY === false ? floor(($this->height - $height) / 2) : intval($startY);

        //Check dimensions
        $startX = max(0, min($this->width, $startX));
        $startY = max(0, min($this->height, $startY));
        $width = min($width, $this->width - $startX);
        $height = min($height, $this->height - $startY);


        $newImage = imagecreatetruecolor($width, $height);

        $this->preserveTransparency($newImage);

        imagecopyresampled($newImage, $this->image, 0, 0, $startX, $startY, $width, $height, $width, $height);

        imagedestroy($this->image);

        $this->image = $newImage;
        $this->width = $width;
        $this->height = $height;

        return $this;
    }

    public function text($text, $fontFile, $size = 12, $color = [0, 0, 0],
                         $corner = self::CORNER_LEFT_TOP, $offsetX = 0, $offsetY = 0, $angle = 0, $alpha = 0)
    {
        $this->checkLoaded();

        $bBox = imagettfbbox($size, $angle, $fontFile, $text);
        $textHeight = $bBox[1] - $bBox[7];
        $textWidth = $bBox[2] - $bBox[0];


        switch ($corner) {
            case self::CORNER_LEFT_TOP:
                $posX = $offsetX;
                $posY = $offsetY;
                break;
            case self::CORNER_RIGHT_TOP:
                $posX = $this->width - $textWidth - $offsetX;
                $posY = $offsetY;
                break;
            case self::CORNER_LEFT_BOTTOM:
                $posX = $offsetX;
                $posY = $this->height - $textHeight - $offsetY;
                break;
            case self::CORNER_RIGHT_BOTTOM:
                $posX = $this->width - $textWidth - $offsetX;
                $posY = $this->height - $textHeight - $offsetY;
                break;
            case self::CORNER_CENTER:
                $posX = floor(($this->width - $textWidth) / 2);
                $posY = floor(($this->height - $textHeight) / 2);
                break;
            case self::CORNER_CENTER_TOP:
                $posX = floor(($this->width - $textWidth) / 2);
                $posY = $offsetY;
                break;
            case self::CORNER_CENTER_BOTTOM:
                $posX = floor(($this->width - $textWidth) / 2);
                $posY = $this->height - $textHeight - $offsetY;
                break;
            case self::CORNER_LEFT_CENTER:
                $posX = $offsetX;
                $posY = floor(($this->height - $textHeight) / 2);
                break;
            case self::CORNER_RIGHT_CENTER:
                $posX = $this->width - $textWidth - $offsetX;
                $posY = floor(($this->height - $textHeight) / 2);
                break;
            default:
                throw new Exception('Invalid $corner value');
        }

        if ($alpha > 0) {
            $color = imagecolorallocatealpha($this->image, $color[0], $color[1], $color[2], $alpha);
        } else {
            $color = imagecolorallocate($this->image, $color[0], $color[1], $color[2]);
        }

        imagettftext($this->image, $size, $angle, $posX, $posY + $textHeight, $color, $fontFile, $text);

        return $this;
    }

    public function adaptiveThumb($width, $height)
    {
        $this->checkLoaded();

        $width = intval($width);
        $height = intval($height);

        $widthProportion = $width / $this->width;
        $heightProportion = $height / $this->height;

        if ($widthProportion > $heightProportion) {
            $newWidth = $width;
            $newHeight = round($newWidth / $this->width * $this->height);
        } else {
            $newHeight = $height;
            $newWidth = round($newHeight / $this->height * $this->width);
        }

        $this->resize($newWidth, $newHeight);

        $this->crop($width, $height);

        return $this;
    }

    public function resizeCanvas($toWidth, $toHeight, $backgroundColor = [255, 255, 255])
    {
        $this->checkLoaded();

        $newWidth = min($toWidth, $this->width);
        $newHeight = min($toHeight, $this->height);

        $widthProportion = $newWidth / $this->width;
        $heightProportion = $newHeight / $this->height;

        if ($widthProportion < $heightProportion) {
            $newHeight = round($widthProportion * $this->height);
        } else {
            $newWidth = round($heightProportion * $this->width);
        }

        $posX = floor(($toWidth - $newWidth) / 2);
        $posY = floor(($toHeight - $newHeight) / 2);


        $newImage = imagecreatetruecolor($toWidth, $toHeight);

        $backgroundColor = imagecolorallocate($newImage, $backgroundColor[0], $backgroundColor[1], $backgroundColor[2]);
        imagefill($newImage, 0, 0, $backgroundColor);

        imagecopyresampled($newImage, $this->image, $posX, $posY, 0, 0, $newWidth, $newHeight, $this->width, $this->height);

        imagedestroy($this->image);

        $this->image = $newImage;
        $this->width = $toWidth;
        $this->height = $toHeight;

        return $this;
    }

    public function grayscale()
    {
        $newImage = imagecreatetruecolor($this->width, $this->height);

        imagecopy($newImage, $this->image, 0, 0, 0, 0, $this->width, $this->height);
        imagecopymergegray($newImage, $newImage, 0, 0, 0, 0, $this->width, $this->height, 0);

        imagedestroy($this->image);

        $this->image = $newImage;

        return $this;
    }

    public function show($inFormat = false, $jpegQuality = 75)
    {
        $this->checkLoaded();

        if (!$inFormat) {
            $inFormat = $this->format;
        }

        switch ($inFormat) {
            case self::IMG_GIF:
                header('Content-type: image/gif');
                imagegif($this->image);
                break;
            case self::IMG_JPEG:
                header('Content-type: image/jpeg');
                imagejpeg($this->image, null, $jpegQuality);
                break;
            case self::IMG_PNG:
                header('Content-type: image/png');
                imagepng($this->image);
                break;
            default:
                throw new Exception('Invalid image format for putput');
        }

        return $this;
    }

    public function save($file = false, $toFormat = false, $jpegQuality = 75, $touch = false)
    {
        if (empty($file)) {
            $file = $this->fileName;
        }

        $this->checkLoaded();

        if (!$toFormat) {
            $toFormat = $this->format;
        }

        switch ($toFormat) {
            case self::IMG_GIF:
                if (!imagegif($this->image, $file)) {
                    throw new Exception('Can\'t save gif file');
                }
                break;
            case self::IMG_JPEG:
                if (!imagejpeg($this->image, $file, $jpegQuality)) {
                    throw new Exception('Can\'t save jpeg file');
                }
                break;
            case self::IMG_PNG:
                if (!imagepng($this->image, $file)) {
                    throw new Exception('Can\'t save png file');
                }
                break;
            default:
                throw new Exception('Invalid image format for save');
        }

        if ($touch && $file != $this->fileName) {
            touch($file, filemtime($this->fileName));
        }

        return $this;
    }

}

Ответы [ 2 ]

0 голосов
/ 04 января 2019

Спасибо @Yanik Lupien ваш простой код очень хорошая работа:)

                   if (function_exists('exif_read_data')) {
                        $buffer = imagecreatefromjpeg($file);
                        $exif = @exif_read_data($file);

                        if ($exif && !empty($exif['Orientation']))
                        {
                            switch($exif['Orientation']) {
                                case 8:
                                    $buffer = imagerotate($buffer, 90, 0);
                                break;
                                case 3:
                                    $buffer = imagerotate($buffer, 180, 0);
                                break;
                                case 6:
                                    $buffer = imagerotate($buffer, -90, 0);
                                break;
                                case 5: // vertical flip + 90 rotate right
                                    $buffer = imagerotate($buffer, -90, 0);
                                break;
                                case 7: // horizontal flip + 90 rotate right
                                    $buffer = imagerotate($buffer, -90, 0);
                                break;
                            }
                        }
                        imagejpeg($buffer, $file, 90);
                    }
0 голосов
/ 04 января 2019

Вот небольшой фрагмент для исправления вращения.

$imagePathName = 'file.jpg';
$buffer = ImageCreateFromJPEG($imagePathName);
$exif = @exif_read_data($imagePathName);

if ($exif && !empty($exif['Orientation']))
{
    switch($exif['Orientation']) {
        case 8:
            $buffer = imagerotate($buffer, 90, 0);
        break;
        case 3:
            $buffer = imagerotate($buffer, 180, 0);
        break;
        case 6:
            $buffer = imagerotate($buffer, -90, 0);
        break;
    }
}

imagejpeg($buffer, $imagePathName, 90);
...