如何根据EXIF'方向'数据停止PHP iMagick自动旋转图像

时间:2010-11-24 12:17:35

标签: php image web-applications exif imagick

目前正在与PHP和iMagick合作开发海报打印Web应用程序。

这是我用来测试应用程序的上传/图像编辑功能的示例图像:

alt text

图像包含以下EXIF数据:

[FileName] => 1290599108_IMG_6783.JPG
    [FileDateTime] => 1290599109
    [FileSize] => 4275563
    [FileType] => 2
    [MimeType] => image/jpeg
    [SectionsFound] => ANY_TAG, IFD0, THUMBNAIL, EXIF, INTEROP, MAKERNOTE
    [COMPUTED] => Array
        (
            [html] => width="3504" height="2336"
            [Height] => 2336
            [Width] => 3504
            [IsColor] => 1
            [ByteOrderMotorola] => 0
            [CCDWidth] => 22mm
            [ApertureFNumber] => f/5.6
            [UserComment] => 
            [UserCommentEncoding] => UNDEFINED
            [Thumbnail.FileType] => 2
            [Thumbnail.MimeType] => image/jpeg
        )

    [Make] => Canon
    [Model] => Canon EOS 30D
    [Orientation] => 6
    [XResolution] => 72/1
    [YResolution] => 72/1
    [ResolutionUnit] => 2
    [DateTime] => 2009:08:31 08:23:49
    [YCbCrPositioning] => 2
    [Exif_IFD_Pointer] => 196

然而 - 当使用此图像进行__construct时,iMagick会根据[Orientation] => 6自动将其旋转90度CCW(我想!)。导致这......

alt text

我想知道的是......

如何保持页面顶部图像的原始方向?这是否可以通过禁用iMagick执行的自动旋转来实现?

非常感谢

更新:以下是我提出的解决方案......它将根据EXIF数据中的方向修复方向

   public function fixOrientation() {

       $exif = exif_read_data($this->imgSrc);
       $orientation = $exif['Orientation'];
       switch($orientation) {

           case 6: // rotate 90 degrees CW
               $this->image->rotateimage("#FFF", 90);
           break;

           case 8: // rotate 90 degrees CCW
              $this->image->rotateimage("#FFF", -90);
           break;

       }

 }

5 个答案:

答案 0 :(得分:45)

  

“然而 - 当使用此图像进行__construct时,iMagick会根据[方向] => 6(我认为!)自动将其旋转90度CCW。”

问题实际上恰恰相反。 Imagick 不会自动旋转图像。您只能在其他软件/网络浏览器中正确看到它,因为这些程序会根据EXIF信息自动旋转它。 Imagick中的某些操作会导致您丢失正确的EXIF信息(复制图像,thumbnailImage(),stripImage()和其他操作)。因此,在这种情况下您需要做的是实际旋转图像。

ajmicek的答案很好,但是可以通过使用Imagick自己的内置函数而不是PHP EXIF函数来改进。此片段似乎也是类的一部分,因此它不能用作单独的函数。旋转后用setImageOrientation()设置正确的EXIF方向也是个好主意。

// Note: $image is an Imagick object, not a filename! See example use below.
function autoRotateImage($image) {
    $orientation = $image->getImageOrientation();

    switch($orientation) {
        case imagick::ORIENTATION_BOTTOMRIGHT: 
            $image->rotateimage("#000", 180); // rotate 180 degrees
            break;

        case imagick::ORIENTATION_RIGHTTOP:
            $image->rotateimage("#000", 90); // rotate 90 degrees CW
            break;

        case imagick::ORIENTATION_LEFTBOTTOM: 
            $image->rotateimage("#000", -90); // rotate 90 degrees CCW
            break;
    }

    // Now that it's auto-rotated, make sure the EXIF data is correct in case the EXIF gets saved with the image!
    $image->setImageOrientation(imagick::ORIENTATION_TOPLEFT);
}

使用示例:

$image = new Imagick('my-image-file.jpg');
autoRotateImage($image);
// - Do other stuff to the image here -
$image->writeImage('result-image.jpg');

答案 1 :(得分:3)

答案 2 :(得分:1)

良好的开端 - 增加一些功能以使功能更加强大。首先,当图像上下颠倒时发生情况3。有一个很好的说明不同的方向代码by Calvin Hass。 方向信息可能出现在exif_read_data数组的不同部分(我认为取决于相机模型),所以我试图在我的示例代码中考虑到这一点。

这样的事情:

public function fixOrientation() {

    $exif = exif_read_data($this->imgSrc);

    if( isset($exif['Orientation']) )
        $orientation = $exif['Orientation'];
    elseif( isset($exif['IFD0']['Orientation']) )
        $orientation = $exif['IFD0']['Orientation'];
    else
        return false;

    switch($orientation) {
        case 3: // rotate 180 degrees
            $this->image->rotateimage("#FFF", 180);
        break;

        case 6: // rotate 90 degrees CW
            $this->image->rotateimage("#FFF", 90);
        break;

        case 8: // rotate 90 degrees CCW
            $this->image->rotateimage("#FFF", -90);
        break;
    }
}

转型&保存不包含先前的EXIF信息,包括Orientation。变换后的图像中缺少 Orientation将阻止进一步处理通过再次旋转来尝试“纠正”事物。我希望Imagick支持ImageMagick's -auto-orient,但是很好。

哦,还有:旋转是lossy operation(除非你使用jpegtran),所以你应该尝试只与调整大小或其他转换一起使用。

答案 3 :(得分:0)

这个代码在orrd的优秀答案中需要iMagick版本6.3 +:

$图像 - > setImageOrientation(imagick :: ORIENTATION_TOPLEFT);

完美运行并处理操作系统/设备方向的差异。不适用于6.2。

我已编码获取设备。在这种情况下有人需要它。

$ua = $_SERVER['HTTP_USER_AGENT'];
$strcut = stristr($ua, '(')."<br>";
$textlen = strpos($strcut,";");
$deviceos = substr($strcut,1,($textlen-1));
echo "Device O/S: * $deviceos"."<br>";

答案 4 :(得分:0)

function thumbnailImage($imagePath,$color,$quality)
{   

    $fileType = pathinfo($imagePath, PATHINFO_EXTENSION);

    if (!empty($fileType))
    {
        switch($fileType)
        {
            case "gif":
                $im = imagecreatefromgif($imagePath);
                break;

            case "jpg":
                $im = imagecreatefromjpeg($imagePath);
                break;

            case "jpeg":
                $im = imagecreatefromjpeg($imagePath);
                break;

            case "png":
                $im = imagecreatefrompng($imagePath);
                break;
        }
    }

    $imagick = new Imagick();
    $imagick->readImage($imagePath);
    $compression_type = Imagick::COMPRESSION_JPEG; 
    $imagick->setImageCompression($compression_type);
    $imagick->setImageCompressionQuality($quality);

    if ($fileType == "jpeg" || $fileType == "jpeg" )
    {
        $exif = exif_read_data($imagePath);
        if (!empty($exif['Orientation'])) {
            switch ($exif['Orientation']) {
                case 3:
                    $imagick = imagerotate($imagick, 180, 0);
                    break;

                case 6:
                    $imagick = imagerotate($imagick, -90, 0);
                    break;

                case 8:
                    $imagick = imagerotate($imagick, 90, 0);
                    break;
            }
        }
    }
    $imagick->setImageBackgroundColor($color);
    $imagick->thumbnailImage(150, 150, true, true);
    header("Content-type: image/jpg");
    echo $imagick->getImageBlob();
}

超级简单的缩略图。致电

thumbnailImage('file.ext','#ffffff',50); // full path, color, quality 1-100

可以与jpggifpng一起使用,但显然只能在jpeg上使用EXIF

缩略图将加载到页面上,如果您指定$_GETs

,则可以通过URL调用缩略图

享受