Portrait images rotating 90 degrees anti-clockwise with 6.9.10-68 Q16

Started by timbo79, August 10, 2020, 10:17:32 AM

Previous topic - Next topic

timbo79

Hi all,

My first post here so please go easy on me! :)

I'm afraid I'm not a developer I just mess with things until they work or I break something else.

I'm using ImageMagick together with Xenforo to process images.

A developer created an add-on for me that extracts some exif data from the images (using exiftool) that are uploaded as attachments and displays it below the images (it's a photography forum).

It's working perfectly for horizontal/landscape orientation images but for vertical/portrait orientation they are being rotated 90 degrees clockwise.

The problem is that it's working fine on my developers test server but not on my production server.

They did point me to this post https://forum.cgru.info/viewtopic.php?f=34&p=4719 where someone is having a similar problem with version 6.9.10-68 Q16 and fixed it by rolling back to a previous version.

Unfortunately right now I'm on a shared server and can't roll back, although I will be moving to a dedicated server soon so I can try this to see if rolling back will fix it.

However, first I just wanted to check if there's another option?

Below is the imagick.php that I'm using:


Thank you!





<?php


namespace XF\Image;


class 
Imagick extends AbstractDriver
{
/**
 * @var \Imagick
 */
protected $imagick;


public static function isDriverUsable()
{
return class_exists('Imagick');
}


protected function _imageFromFile($file$type)
{
switch ($type)
{
case IMAGETYPE_GIF:
case IMAGETYPE_JPEG:
case IMAGETYPE_PNG:
$image = new \Imagick($file);
break;


default:
throw new \InvalidArgumentException("Unknown image type '$type'");
}


$this->setImage($image);


return true;
}


protected function _createImage($width$height)
{
$image = new \Imagick();
$background = new \ImagickPixel('white');
$image->newImage($width$height$background);


$this->setImage($image);


return true;
}


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


public function setImage(\Imagick $image)
{
$image->setImageBackgroundColor(new \ImagickPixel('transparent'));
$image $image->coalesceImages();


$this->imagick $image;


$this->updateDimensions();
}


protected function updateDimensions()
{
$this->width $this->imagick->getImageWidth();
$this->height $this->imagick->getImageHeight();
}


protected function isOldImagick()
{
// imagick module < 3 or ImageMagick < 6.3.2 don't support the 4th thumbnailImage param
$oldImagick version_compare(phpversion('imagick'), '3''<');


$version $this->imagick->getVersion();
if (preg_match('#ImageMagick (\d+\.\d+\.\d+)#i'$version['versionString'], $match))
{
if (version_compare($match[1], '6.3.2''<'))
{
$oldImagick true;
}
}


return $oldImagick;
}


public function resizeTo($width$height)
{
$scaleUp = ($width $this->width || $height $this->height);


try
{
            foreach (
$this->imagick AS $frame)
            {
                if (
$scaleUp)
                {
                    
$frame->resizeImage($width$height\Imagick::FILTER_LANCZOS1true);
$frame->unsharpMaskImage(0.5 0.05);
                }
                else if (
$this->isOldImagick())
                {
                    
$frame->resizeImage($width$height\Imagick::FILTER_LANCZOS1true);
$frame->unsharpMaskImage(0.5 0.05);
                }
                else
                {
                    
$frame->resizeImage($width$height\Imagick::FILTER_LANCZOS1true);
$frame->unsharpMaskImage(0.5 0.05);
                }
                
$frame->setImagePage($width$height00);
            }


$this->updateDimensions();
}
catch (\Exception $e) {}


return $this;
}


public function crop($width$height$x 0$y 0$srcWidth null$srcHeight null)
{
foreach ($this->imagick AS $frame)
{
$frame->cropImage($srcWidth ?: $width$srcHeight ?: $height$x$y);
if ($this->isOldImagick())
{
$frame->thumbnailImage($width$heightfalse);
}
else
{
$frame->thumbnailImage($width$heightfalsetrue);
}
$frame->setImagePage($frame->getImageWidth(), $frame->getImageHeight(), 00);
}
$this->updateDimensions();


return $this;
}


public function rotate($angle)
{
foreach ($this->imagick AS $frame)
{
$frame->rotateImage(new \ImagickPixel('none'), $angle);
}
$this->updateDimensions();


return $this;
}




public function flip($mode)
{
foreach ($this->imagick AS $frame)
{
switch ($mode)
{
case self::FLIP_HORIZONTAL:
$frame->flopImage();
break;


case self::FLIP_VERTICAL:
$frame->flipImage();
break;


case self::FLIP_BOTH:
$frame->flopImage();
$frame->flipImage();
break;


default:
throw new \InvalidArgumentException("Unknown flip mode");
}
}


$this->updateDimensions();


return $this;
}


public function setOpacity($opacity)
{
foreach ($this->imagick AS $frame)
{
$frame->evaluateImage(\Imagick::EVALUATE_MULTIPLY$opacity\Imagick::CHANNEL_ALPHA);
}


return $this;
}


public function appendImageAt($x$y$toAppend)
{
if (!($toAppend instanceof \Imagick))
{
throw new \InvalidArgumentException('Image to append must be a valid Imagick object.');
}


foreach ($this->imagick AS $frame)
{
$frame->compositeImage($toAppend$toAppend->getImageCompose(), $x$y);
}


return $this;
}


protected function _unsharpMask($radius$sigma$amount$threshold)
{
foreach ($this->imagick AS $frame)
{
$frame->unsharpMaskImage($radius$sigma$amount$threshold);
}


return $this;
}


public function save($file$format null$quality null)
{
if ($format === null)
{
$format $this->type;
}


if ($quality === null)
{
$quality 82;
}


if (method_exists($this->imagick'getImageProfiles'))
{
$profiles $this->imagick->getImageProfiles('icc');
            
//$this->imagick->stripImage();


if ($profiles && !empty($profiles['icc']))
{
$this->imagick->setImageProfile('icc'$profiles['icc']);
}
}
else
{
$this->imagick->stripImage();
}


switch ($format)
{
case IMAGETYPE_GIF:
if (is_callable(array($this->imagick'optimizeimagelayers')))
{
$optimized = @$this->imagick->optimizeimagelayers();
if ($optimized instanceof \Imagick)
{
$this->imagick $optimized;
}


$deconstructed = @$this->imagick->deconstructImages();
if ($deconstructed instanceof \Imagick)
{
$this->imagick $deconstructed;
}
}
$success $this->imagick->setImageFormat('gif');
break;


case IMAGETYPE_JPEG:
$success $this->imagick->setImageFormat('jpeg')
&& $this->imagick->setImageCompression(\Imagick::COMPRESSION_JPEG)
&& $this->imagick->setImageCompressionQuality($quality);
break;


case IMAGETYPE_PNG:
$success $this->imagick->setImageFormat('png');
break;


default:
throw new \InvalidArgumentException('Invalid format given. Expects IMAGETYPE_XXX constant.');
}


if ($success)
{
try
{
return $this->imagick->writeImages($filetrue);
}
catch (\ImagickException $e) {}
}


return false;
}


public function output($format null$quality null)
{
if ($format === null)
{
$format $this->type;
}


if ($quality === null)
{
$quality 82;
}


$this->imagick->stripImage();


switch ($format)
{
case IMAGETYPE_GIF:
$success $this->imagick->optimizeImageLayers();
break;


case IMAGETYPE_JPEG:
$success $this->imagick->setImageFormat('jpeg')
&& $this->imagick->setImageCompression(\Imagick::COMPRESSION_JPEG)
&& $this->imagick->setImageCompressionQuality($quality);
break;


case IMAGETYPE_PNG:
$success $this->imagick->setImageFormat('png');
break;


default:
throw new \InvalidArgumentException('Invalid format given. Expects IMAGETYPE_XXX constant.');
}


if ($success)
{
try
{
echo $this->imagick->getImagesBlob();
}
catch (\ImagickException $e) {}
}
}


public function isValid()
{
return $this->imagick->valid();
}


public function __destruct()
{
if ($this->imagick)
{
$this->imagick->destroy();
$this->imagick null;
}
}
}









StarGeek

From the sound of things, ImageMagick isn't preserving/honoring the EXIF:Orientation.  And while your code does appear to have a subroutine to deal with rotation, it doesn't look like this is the code that would actually extract the the Orientation for the image.

I should point out that this is a forum for Exiftool and your example code is completely about ImageMagick.  As far as I can tell, exiftool isn't even called from it.
* Did you read FAQ #3 and use the command listed there?
* Please use the Code button for exiftool code/output.
 
* Please include your OS, Exiftool version, and type of file you're processing (MP4, JPG, etc).

timbo79

Quote from: StarGeek on August 10, 2020, 10:45:52 AM
From the sound of things, ImageMagick isn't preserving/honoring the EXIF:Orientation.  And while your code does appear to have a subroutine to deal with rotation, it doesn't look like this is the code that would actually extract the the Orientation for the image.

I should point out that this is a forum for Exiftool and your example code is completely about ImageMagick.  As far as I can tell, exiftool isn't even called from it.

Thanks for replying, I really appreciate it. You are right, I should probably find a forum that is focused on ImageMagick. I'm scratching my head now wondering why I posted this here!