0

I use this script to compress uploaded photos. Photo is uploaded via move_uploaded_file() and then I call this function. But when I try to compress portrait photo which was directly taken from the camera (click to upload button on the page and choose option "take a picture" and then upload is started), it is always rotated by 90deg to the left.

I've tried to find out where is the problem, but list of my ideas is empty now and I just can not figure it out. Any ideas, where could be the problem?

(Landscape images are uploaded fine, they are not rotated.)

function image_resize($file, $string = null, $width = 0, $height = 0, $proportional = true, $output = 'file', $delete_original = true, $quality = 100, $grayscale = false) {
if ($height <= 0 && $width <= 0) return false;
if ($file === null && $string === null) return false;

$info = $file !== null ? getimagesize($file) : getimagesizefromstring($string);
$image = '';
$final_width = 0;
$final_height = 0;
list($width_old, $height_old) = $info;
$cropHeight = $cropWidth = 0;

if ($proportional) {
  if ($width  == 0) $factor = $height/$height_old;
  elseif ($height == 0) $factor = $width/$width_old;
  else $factor = min($width / $width_old, $height / $height_old);

  $final_width  = round($width_old * $factor);
  $final_height = round($height_old * $factor);
} else {
  $final_width = ($width <= 0 ? $width_old : $width);
  $final_height = ($height <= 0 ? $height_old : $height);
  $widthX = $width_old / $width;
  $heightX = $height_old / $height;

  $x = min($widthX, $heightX);
  $cropWidth = ($width_old - $width * $x) / 2;
  $cropHeight = ($height_old - $height * $x) / 2;
}

// if the image is smaller than max. width/height, just keep it as is
if ($width_old < $width && $height_old < $height) {
  $cropHeight = $cropWidth = 0;

  $final_width = $width_old;
  $final_height = $height_old;
}

switch($info[2]) {
  case IMAGETYPE_JPEG:
    $file !== null ? $image = imagecreatefromjpeg($file) : $image = imagecreatefromstring($string);
    break;

  case IMAGETYPE_GIF:
    $file !== null ? $image = imagecreatefromgif($file) : $image = imagecreatefromstring($string);
    break;

  case IMAGETYPE_PNG:
    $file !== null ? $image = imagecreatefrompng($file) : $image = imagecreatefromstring($string);
    break;

  default:
    return false;
    break;
}

// grayscale image
if ($grayscale) {
  imagefilter($image, IMG_FILTER_GRAYSCALE);
}

$image_resized = imagecreatetruecolor($final_width, $final_height);
if (($info[2] == IMAGETYPE_GIF) || ($info[2] == IMAGETYPE_PNG)) {
  $transparency = imagecolortransparent($image);
  $palletsize = imagecolorstotal($image);

  if ($transparency >= 0 && $transparency < $palletsize) {
    $transparent_color = imagecolorsforindex($image, $transparency);
    $transparency = imagecolorallocate($image_resized, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']);
    imagefill($image_resized, 0, 0, $transparency);
    imagecolortransparent($image_resized, $transparency);
  } elseif ($info[2] == IMAGETYPE_PNG) {
    imagealphablending($image_resized, false);
    $color = imagecolorallocatealpha($image_resized, 0, 0, 0, 127);
    imagefill($image_resized, 0, 0, $color);
    imagesavealpha($image_resized, true);
  }
}

imagecopyresampled($image_resized, $image, 0, 0, $cropWidth, $cropHeight, $final_width, $final_height, $width_old - 2 * $cropWidth, $height_old - 2 * $cropHeight);

// delete original image, if set
if ($delete_original) {
  @unlink($file);
}

switch(strtolower($output)) {
  case 'browser':
    $mime = image_type_to_mime_type($info[2]);
    header("Content-type: " . $mime);
    $output = NULL;
    break;

  case 'file':
    $output = $file;
    break;

  case 'return':
    return $image_resized;
    break;

  default:
    break;
}

// saving new image
switch($info[2]) {
  case IMAGETYPE_GIF:
    imagegif($image_resized, $output);
    break;

  case IMAGETYPE_JPEG:
    imagejpeg($image_resized, $output, $quality);
    break;

  case IMAGETYPE_PNG:
    $quality = 9 - (int)((0.9 * $quality) / 10.0);
    imagepng($image_resized, $output, $quality);
    break;

  default:
    return false;
}

return true;
}
sylar32
  • 197
  • 3
  • 16
  • 1
    Did you process your image according the "orientation" tag before you do the compression ? You may refer to this post for further information: (https://stackoverflow.com/questions/65604949/php-imagerotate-angle/65605140#65605140) – Ken Lee May 09 '21 at 11:45

1 Answers1

0

Thanks to Ken's Lee idea I tried to check image orientation and if orientation > 1, I will rotate it via functions below.

Just notice, You have to save orientation based on exif data before upload and other manipulating with photo. When I save it and compress it, it lost any exif information and orientation is 1.

Is there any change how to keep exif data even after compressing photo, when completely new image is created?

// 1) save orientation before upload
if (getimagesize($file['tmp_name'])['mime'] === 'image/jpeg') {
  $exif = exif_read_data($file['tmp_name']);
  if (!empty($exif['Orientation'])) {
    $this->file_orientation = $exif['Orientation'];
  }
}

// 2) upload and compress your photo
// ... 
// $output = '/path/to/compressed/photo.jpg';

// 3) check orientation of original photo and rotate the new-compressed one
if ($this->file_orientation > 1) {
  $image = imagecreatefromjpeg($output);
  if (in_array($orientation, [3, 4])) {
    $image = imagerotate($image, 180, 0);
  }
  if (in_array($orientation, [5, 6])) {
    $image = imagerotate($image, -90, 0);
  }
  if (in_array($orientation, [7, 8])) {
    $image = imagerotate($image, 90, 0);
  }
  if (in_array($orientation, [2, 5, 7, 4])) {
    imageflip($image, IMG_FLIP_HORIZONTAL);
  }
  imagejpeg($image, $output, $quality);
}
sylar32
  • 197
  • 3
  • 16