Andy Wallace
Andy Wallace

Reputation: 689

ImageMagick and PHP to properly rotate an image

I am trying to use Imagick in my php code to properly orient images, so that I can strip the metadata from them and have them properly show up. I tried the methodology in this post:

Detect EXIF Orientation and Rotate Image using ImageMagick

But it is not working. Using the autorotate function in that post, this is what I am doing:

$working_image = new \Imagick();
$working_image->readImageBlob( $source_data);
$working_image->setImageFormat('jpeg');
autorotate($working_image);

... some resizing code:
$working_image->resizeImage( $width, $height, \Imagick::FILTER_CATROM, .7);

// get rid of metadata
$working_image->stripImage();

$working_image->writeImage( <unique filename> );

$working_image->getImageBlob();
... write out to data file to google

We're using Google's cloud stuff to store our files, hence the "getImageBlob" call.

Problem is that this doesn't seem to work. The resultant images are still oriented the same way they were, but now have no metadata, so the tag won't "fix" them.

What am I doing wrong here? I am using this version of the Imagick PHP object:

[versionNumber] => 1673 [versionString] => ImageMagick 6.8.9-9 Q16 x86_64 2015-01-05 http://www.imagemagick.org

In response to your answer:

Thanks for the clarifications. Looking at one of the specific images that I am having problems with, identify -verbose shows multiple places defining orientation:

Orientation: RightTop
exif:Orientation: 6
exif:thumbnail:Orientation: 6

And this is reflected in my call to Imagick::getImageOrientation in PHP, which returns the "6" value, which then causes my code to call functions like "Imagick::rotateImage("#000", 180);". The problem is that the image is unchanged by these calls. 8-(

The core problem is this: We get these images by the thousands every day from MLS's all over the country. We currently process them (resizing currently) via an automatic process. When they are displayed on our site, everything is currently fine, because the <img> tag seems to be happy to interpret the EXIF data and show the image in proper orientation. BUT... we want to start optimizing images, which means stripping the EXIF info out. So I need to figure out why Imagick->rotateImage() isn't working.

Upvotes: 1

Views: 3639

Answers (3)

Kevin Glier
Kevin Glier

Reputation: 1386

@Satendra Rawat posted a good, but incomplete answer. There is the GitHub repository https://github.com/ianare/exif-samples, where you can see 8 orientation examples. Only 3, 5 and 8 worked correctly.

So here is a update for all the orientations:

public function fix_image_orientation()
{
    $working_image = new \Imagick();
    $working_image->readImageBlob($source_data);
    $working_image->setImageFormat('jpeg');
    $orientation = $working_image->getImageOrientation();
    if (!empty($orientation)) {
        switch ($orientation) {
            default:
            case imagick::ORIENTATION_TOPLEFT:
                break;
            case imagick::ORIENTATION_TOPRIGHT:
                $working_image->flipImage();
                $working_image->rotateImage("#000", 180);
                break;
            case imagick::ORIENTATION_BOTTOMRIGHT:
                $working_image->rotateImage("#000", 180);
                break;
            case imagick::ORIENTATION_BOTTOMLEFT:
                $working_image->flipImage();
                break;
            case imagick::ORIENTATION_LEFTTOP:
                $working_image->rotateImage("#000", -90);
                $working_image->flipImage();
                break;
            case imagick::ORIENTATION_RIGHTTOP:
                $working_image->rotateImage("#000", 90);
                break;
            case imagick::ORIENTATION_RIGHTBOTTOM:
                $working_image->rotateImage("#000", 90);
                $working_image->flipImage();
                break;
            case imagick::ORIENTATION_LEFTBOTTOM:
                $working_image->rotateImage("#000", -90);
                break;
        }
    }
    $working_image->setImageOrientation(imagick::ORIENTATION_TOPLEFT);
    $working_image->writeImage( <unique filename> );
}

Upvotes: 0

Satendra Rawat
Satendra Rawat

Reputation: 1404

We can get the current image orientation and can easily update to the original one with Imagick

public function fix_image_orientation()
    {
        $working_image = new \Imagick();
        $working_image->readImageBlob($source_data);
        $working_image->setImageFormat('jpeg');
        $orientation = $working_image->getImageOrientation();
        if (!empty($orientation)) {
            switch ($orientation) {
                case imagick::ORIENTATION_BOTTOMRIGHT:
                    $working_image->rotateimage("#000", 180);
                    break;

                case imagick::ORIENTATION_RIGHTTOP:
                    $working_image->rotateimage("#000", 90);
                    break;

                case imagick::ORIENTATION_LEFTBOTTOM:
                    $working_image->rotateimage("#000", -90);
                    break;
            }
        }
        $working_image->setImageOrientation(imagick::ORIENTATION_TOPLEFT);
        $working_image->writeImage( <unique filename> );
    }

Upvotes: 1

lp1051
lp1051

Reputation: 501

Ok, let's write a whole answer:)

What I meant with the link to ImageMagick's -auto-orient, was to point out, that this kind of auto-orientation depends on EXIF profile and "Orientation" setting. If it's missing or is wrong the auto-orientation will not work as expected. To check whether your images has the EXIF profile with Orientation in tact, you can use several ways:

PHP Imagick (check it with image before you call ->stripImage())

echo 'Orientation is: ', $working_image->getImageOrientation();

PHP (if you have local file)

$exif = exif_read_data('input.jpg');
echo 'Orientation is: ', isset($exif['Orientation']) ? $exif['Orientation'] : 'missing';

Online EXIF reader.

The values you get are described for example here or more about image auto-rotation topic and sample images are here

Or you can use programs like Gimp or Photoshop.

So you're doing nothing wrong, without EXIF this won't work. It's camera that is writing the tags into images, so there is no guarantee all your photos have it.

Perhaps offer image rotation for visitors in your website instead? There is now CSS3 transform: rotate(deg) property that makes it really easy, see....

Upvotes: 1

Related Questions