Правильная Ориентация при заливке изображений JPEG

Замечали такую замечательную вещь. Получив изображение из фотоаппарата — вы вкладываете его на сайт, а загружается оно повернутым на 90 градусов? Что же это за бяка такая, почему крупные ресурсы вроде контакта заливают изображение правильно?
Чем наш сервис то хуже? Почему в базовом PHP и GD так криво настроено чтение исходных изображений?..
А код у вас выглядит примерно так?

<?php
$prop=getimagesize($filename);
switch($prop[2]){
  case IMAGETYPE_JPEG:
    $image = imagecreatefromjpeg($filename);
    break;
  case IMAGETYPE_GIF:
    $image = imagecreatefromgif($filename);
    break;
  case IMAGETYPE_PNG:
    $image = imagecreatefrompng($filename);
    break;
  }

На самом деле — все просто. PHP Правильно читает изображение, на самом деле оно повернуто лежа. Просто 90% всех виндовых программ умеет распознавать ориентацию. А фокус весь кроется в EXIF мета данных внутри изображений. Фотоаппараты прячут туда всю свою служебную информацию вроде фокусного расстояния, яркости, вспышки и ориентацию.
По этому — все что нам нужно делать — поворачивать изображение вручную при помощи того же PHP.
Для определения EXIF данных изображения — нам понадобится расширения

extension=php_mbstring.dll
extension=php_exif.dll

и функция read_exif_data() для определения параметров. Опытным путем были получены цифры поповора — 3-180 градусов, 6 - -90 градусов, 8-90 градусов. Все что нужно делать — дополнить наш скрипт парой строк

<?php
$prop=getimagesize($filename);
switch($prop[2]){
  case IMAGETYPE_JPEG:
    $image = imagecreatefromjpeg($filename);
    $exif = read_exif_data($filename);
    if ($exif['Orientation']==3)$mage=imagerotate($image,180,0);
    elseif ($exif['Orientation']==6)$image=imagerotate($image,270,0);
    elseif ($exif['Orientation']==8)$image=imagerotate($image,90,0);
    if ($exif['Orientation']==6 || $exif['Orientation']==8){
      $temp=$prop[0];
      $prop[0]=$prop[1];
      $prop[1]=$temp;
    }
    break;
  case IMAGETYPE_GIF:
    $image = imagecreatefromgif($filename);
    break;
  case IMAGETYPE_PNG:
    $image = imagecreatefrompng($filename);
    break;
}

Небольшие пояснения к коду.
Замену prop мы сделали только для случаев поворота изображения на 90 градусов. Оно нужно, если мы будем в дальнейшем сжимать изображение, т. к. ориентироваться на базовые prop мы уже не можем, его тоже нужно повернуть
Почему я не сделал через switch case – так проще выглядит код, а условий не так уж и много, чтобы городить огород.
Замена 2х переменных идет через 3ю переменную, т. к. для универсальной замены — это самый простой способ. Это не тот случай, когда замену переменных можно провести без использования 3й переменной, как спрашивают на собеседованиях. Извратиться то можно, а кто будет код поддерживать в дальнейшем? Не забывайте, что возможно нам понадобятся какие-то еще части этого массива
Уделяйте внимание всем мелочам. Из них зависит отношение пользователя к вашему ресурсу и успешное его развитие

  • Автор: kosmom
  • Рейтинг: 0
  • Просмотров: 1582
  • Комментариев: 3
  • Создан: 11.03.2014 13:34

Комментарии (3)

13.10.2015 15:21
Гость

>> Замена 2х переменных идет через 3ю переменную, т. к. для универсальной замены —
>> это самый простой способ. Это не тот случай, когда замену переменных можно провести
>> без использования 3й переменной, как спрашивают на собеседованиях.

Вообще, обойтись без третьей переменной тут вполне можно, не попортив остальной массив:
$prop[0] = $prop[0] + $prop[1];
$prop[1] = $prop[0] - $prop[1];
$prop[0] = $prop[0] - $prop[1];

13.10.2015 15:21
Гость

А в вывод комментов не помешало бы впилить nl2br )))

17.10.2015 20:36
Константин

Спасибо за замечания

Вопрос использования 3й переменной в том, нужна ли она. Да, мы экономим память, но нагружаем процессор. При этом вид использования временной переменной мне кажется более лаконичным, чем арифметические операции. Можно, конечно без 3й переменной, но тогда нужно обязательно добавить комментарий. Ведь, возможно, однажды этот код придется кому-то поддерживать