Skip to content

Commit

Permalink
Merge pull request #168 from joshuapaling/feature-honour-exif-data
Browse files Browse the repository at this point in the history
honour exif data for jpg thumbnails (aka, prevent thumbnails showing up sideways)
  • Loading branch information
josegonzalez committed Dec 13, 2013
2 parents 8d4e545 + 453718b commit b990efb
Showing 1 changed file with 156 additions and 16 deletions.
172 changes: 156 additions & 16 deletions Model/Behavior/UploadBehavior.php
Expand Up @@ -952,6 +952,7 @@ protected function _resizeImagick(Model $model, $field, $path, $size, $geometry,
}

$image->readImage($srcFile);
$this->_exifRotateImagick($image);
$height = $image->getImageHeight();
$width = $image->getImageWidth();

Expand Down Expand Up @@ -1067,22 +1068,7 @@ protected function _resizePhp(Model $model, $field, $path, $size, $geometry, $th

copy($srcFile, $destFile);
$src = null;
$createHandler = null;
$outputHandler = null;
switch (strtolower($pathInfo['extension'])) {
case 'gif':
$createHandler = 'imagecreatefromgif';
break;
case 'jpg':
case 'jpeg':
$createHandler = 'imagecreatefromjpeg';
break;
case 'png':
$createHandler = 'imagecreatefrompng';
break;
default:
return false;
}

$supportsThumbnailQuality = false;
$adjustedThumbnailQuality = $this->settings[$model->alias][$field]['thumbnailQuality'];
Expand All @@ -1105,7 +1091,9 @@ protected function _resizePhp(Model $model, $field, $path, $size, $geometry, $th
return false;
}

if ($src = $createHandler($destFile)) {
$src = $this->_createImageResource($destFile, $pathInfo);
if ($src) {

$srcW = imagesx($src);
$srcH = imagesy($src);

Expand Down Expand Up @@ -1194,6 +1182,158 @@ protected function _resizePhp(Model $model, $field, $path, $size, $geometry, $th
return false;
}

protected function _createImageResource($filename, $pathInfo) {
switch (strtolower($pathInfo['extension'])) {
case 'gif':
$src = imagecreatefromgif($filename);
break;
case 'jpg':
case 'jpeg':
$src = $this->_imagecreatefromjpegexif($filename);
break;
case 'png':
$src = imagecreatefrompng($filename);
break;
default:
return false;
}

return $src;
}

/**
* Same as imagecreatefromjpeg, but honouring the file's Exif data.
* See http://www.php.net/manual/en/function.imagecreatefromjpeg.php#112902
*/
protected function _imagecreatefromjpegexif($filename) {
$image = imagecreatefromjpeg($filename);
$exif = exif_read_data($filename);
if ($image && $exif && isset($exif['Orientation'])) {
$ort = $exif['Orientation'];
} else {
return $image;
}

$trans = $this->_exifOrientationTransformations($ort);

if ($trans['flip_vert']) {
$image = $this->_flipImage($image,'vert');
}

if ($trans['flip_horz']) {
$image = $this->_flipImage($image,'horz');
}

if ($trans['rotate_clockwise']) {
$image = imagerotate($image, -1 * $trans['rotate_clockwise'], 0);
}

return $image;
}

/**
* Determine what transformations need to be applied to an image,
* in order to maintain it's orientation and get rid of it's Exif Orientation data
* http://www.impulseadventure.com/photo/exif-orientation.html
* @param int $orientation The exif orientation of the image
* @return array of transformations - array keys are:
* 'flip_vert' - true if the image needs to be flipped vertically
* 'flip_horz' - true if the image needs to be flipped horizontally
* 'rotate_clockwise' - number of degrees image needs to be rotated, clockwise
*/
protected function _exifOrientationTransformations($orientation) {
$trans = array(
'flip_vert' => false,
'flip_horz' => false,
'rotate_clockwise' => 0,
);

switch($orientation) {
case 1:
break;

case 2:
$trans['flip_horz'] = true;
break;

case 3:
$trans['rotate_clockwise'] = 180;
break;

case 4:
$trans['flip_vert'] = true;
break;

case 5:
$trans['flip_vert'] = true;
$trans['rotate_clockwise'] = 90;
break;

case 6:
$trans['rotate_clockwise'] = 90;
break;

case 7:
$trans['flip_horz'] = true;
$trans['rotate_clockwise'] = 90;
break;

case 8:
$trans['rotate_clockwise'] = -90;
break;
}

return $trans;
}

/**
* Flip an image object. Code from http://www.roscripts.com/snippets/show/55
* @param resource $img An image resource, such as one returned by imagecreatefromjpeg()
* @param string $type 'horz' or 'vert'
* @return resource The flipped image
*/
protected function _flipImage($img, $type) {
$width = imagesx($img);
$height = imagesy($img);
$dest = imagecreatetruecolor($width, $height);
switch($type){
case 'vert':
for ($i = 0; $i < $height; $i++) {
imagecopy($dest, $img, 0, ($height - $i - 1), 0, $i, $width, 1);
}
break;
case 'horz':
for ($i = 0; $i < $width; $i++) {
imagecopy($dest, $img, ($width - $i - 1), 0, $i, 0, 1, $height);
}
break;
}
return $dest;
}

/**
* rotate an imagick object based on it's exif data.
* @param imagick $image an instance of imagick
*/
protected function _exifRotateImagick($image) {
$orientation = $image->getImageOrientation();
$trans = $this->_exifOrientationTransformations($orientation);

if ($trans['flip_vert']) {
$image->flopImage();
}

if ($trans['flip_horz']) {
$image->flipImage();
}

if ($trans['rotate_clockwise']) {
$image->rotateimage("#000", $trans['rotate_clockwise']);
}

$image->setImageOrientation(imagick::ORIENTATION_TOPLEFT);
}

protected function _getPath(Model $model, $field) {
$path = $this->settings[$model->alias][$field]['path'];
$pathMethod = $this->settings[$model->alias][$field]['pathMethod'];
Expand Down

0 comments on commit b990efb

Please sign in to comment.