Как остановить автоповорот изображений PHP iMagick на основе данных ориентации EXIF - PullRequest
21 голосов
/ 24 ноября 2010

В настоящее время работаю с PHP и iMagick над разработкой веб-приложения для печати плакатов.

Это пример изображения, которое я использую для тестирования функций загрузки / редактирования изображений в приложении:

alt text

Изображение содержит следующие данные EXIF:

[FileName] => 1290599108_IMG_6783.JPG
    [FileDateTime] => 1290599109
    [FileSize] => 4275563
    [FileType] => 2
    [MimeType] => image/jpeg
    [SectionsFound] => ANY_TAG, IFD0, THUMBNAIL, EXIF, INTEROP, MAKERNOTE
    [COMPUTED] => Array
        (
            [html] => width="3504" height="2336"
            [Height] => 2336
            [Width] => 3504
            [IsColor] => 1
            [ByteOrderMotorola] => 0
            [CCDWidth] => 22mm
            [ApertureFNumber] => f/5.6
            [UserComment] => 
            [UserCommentEncoding] => UNDEFINED
            [Thumbnail.FileType] => 2
            [Thumbnail.MimeType] => image/jpeg
        )

    [Make] => Canon
    [Model] => Canon EOS 30D
    [Orientation] => 6
    [XResolution] => 72/1
    [YResolution] => 72/1
    [ResolutionUnit] => 2
    [DateTime] => 2009:08:31 08:23:49
    [YCbCrPositioning] => 2
    [Exif_IFD_Pointer] => 196

Однако - iMagick, когда __construct'ed с этим изображением, автоматически поворачивает его на 90 градусов против часовой стрелки согласно [Orientation] => 6 (Я думаю!).В результате этого ...

alt text

Что я хотел бы знать, это ...

Как сохранить исходную ориентацию изображения, видимого приверхняя часть страницы?И возможно ли это через отключение автоповорота, выполняемого iMagick?

Большое спасибо

ОБНОВЛЕНИЕ: Вот решение, которое я придумала ... Это исправит ориентациюна основе ориентации в данных EXIF ​​

   public function fixOrientation() {

       $exif = exif_read_data($this->imgSrc);
       $orientation = $exif['Orientation'];
       switch($orientation) {

           case 6: // rotate 90 degrees CW
               $this->image->rotateimage("#FFF", 90);
           break;

           case 8: // rotate 90 degrees CCW
              $this->image->rotateimage("#FFF", -90);
           break;

       }

 }

Ответы [ 4 ]

46 голосов
/ 21 февраля 2013

"Однако - iMagick, когда __construct 'с этим изображением, автоматически поворачивает его еще на 90 градусов против часовой стрелки согласно [Ориентация] => 6 (я думаю!)."* Проблема на самом деле противоположна этому.Imagick не автоматически поворачивает изображение.Вы видите его правильно только в другом программном обеспечении / в вашем веб-браузере, потому что эти программы автоматически поворачивают его на основе информации EXIF.Некоторые операции в Imagick приведут к потере правильной информации EXIF ​​(копирование изображения, thumbnailImage (), stripImage () и другие манипуляции).Поэтому в этом случае вам нужно фактически физически повернуть изображение.

Ответ от ajmicek хорош, но его можно немного улучшить, используя собственные встроенные функции Imagick, а не функции PHP EXIF.Кроме того, этот фрагмент, кажется, был частью класса, поэтому его нельзя использовать как отдельную функцию как есть.Также рекомендуется установить правильную ориентацию EXIF ​​с помощью setImageOrientation () после его поворота.

// Note: $image is an Imagick object, not a filename! See example use below.
function autoRotateImage($image) {
    $orientation = $image->getImageOrientation();

    switch($orientation) {
        case imagick::ORIENTATION_BOTTOMRIGHT: 
            $image->rotateimage("#000", 180); // rotate 180 degrees
            break;

        case imagick::ORIENTATION_RIGHTTOP:
            $image->rotateimage("#000", 90); // rotate 90 degrees CW
            break;

        case imagick::ORIENTATION_LEFTBOTTOM: 
            $image->rotateimage("#000", -90); // rotate 90 degrees CCW
            break;
    }

    // Now that it's auto-rotated, make sure the EXIF data is correct in case the EXIF gets saved with the image!
    $image->setImageOrientation(imagick::ORIENTATION_TOPLEFT);
}

Пример использования:

$image = new Imagick('my-image-file.jpg');
autoRotateImage($image);
// - Do other stuff to the image here -
$image->writeImage('result-image.jpg');
3 голосов
/ 24 ноября 2010

Попробуйте Imagick::setImageOrientation. Поэкспериментируйте с доступными константами .

1 голос
/ 20 января 2012

Хорошее начало - несколько дополнений, чтобы сделать функцию более надежной. Во-первых, случай 3 возникает, когда изображение появляется вверх ногами. Есть отличная иллюстрация различных кодов ориентации от Calvin Hass . Возможно, что информация об ориентации может появиться в другой части массива exif_read_data (в зависимости от модели камеры, я думаю), поэтому я попытался учесть это в своем примере кода.

Примерно так:

public function fixOrientation() {

    $exif = exif_read_data($this->imgSrc);

    if( isset($exif['Orientation']) )
        $orientation = $exif['Orientation'];
    elseif( isset($exif['IFD0']['Orientation']) )
        $orientation = $exif['IFD0']['Orientation'];
    else
        return false;

    switch($orientation) {
        case 3: // rotate 180 degrees
            $this->image->rotateimage("#FFF", 180);
        break;

        case 6: // rotate 90 degrees CW
            $this->image->rotateimage("#FFF", 90);
        break;

        case 8: // rotate 90 degrees CCW
            $this->image->rotateimage("#FFF", -90);
        break;
    }
}

Преобразование и сохранение оставляет вас без предыдущей информации EXIF, включая Orientation. отсутствие из Orientation в преобразованном изображении не позволит дальнейшей обработке попытаться «исправить» вещи, повернув их снова. Я бы хотел, чтобы Imagick поддерживал ImageMagick's -auto-orient, ну да ладно.

Да, также: вращение - это операция с потерями (если вы не используете jpegtran), поэтому вы должны пытаться делать это только вместе с изменением размера или другим преобразованием.

0 голосов
/ 31 мая 2014

Этот код в отличном ответе orrd требует iMagick версии 6.3 +.:

$ image-> setImageOrientation (Imagick :: ORIENTATION_TOPLEFT);

Прекрасно работает и заботится о различиях ориентации ОС / устройства. Не будет работать с 6.2.

Я кодировал, чтобы получить устройство. Вот, если кому-то это нужно.

$ua = $_SERVER['HTTP_USER_AGENT'];
$strcut = stristr($ua, '(')."<br>";
$textlen = strpos($strcut,";");
$deviceos = substr($strcut,1,($textlen-1));
echo "Device O/S: * $deviceos"."<br>";
...