Как остановить автоматическое вращение изображений PHP iMagick на основе данных EXIF' orientation
В настоящее время работает с PHP и iMagick для разработки веб-приложения для печати плакатов.
Это пример изображения, которое я использую для тестирования функций загрузки / редактирования изображений приложения:
изображение содержит следующие данные 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 градусов CCW согласно [Orientation] => 6
(Я так думаю!). В результате этот...
что я хотел бы знать...
как я могу сохранить исходную ориентацию изображения, видимого в верхней части страницы? И возможно ли это путем отключения автоматического вращения, выполняемого iMagick?
большое спасибо
UPDATE: вот решение, которое я придумал... Он будет фиксировать ориентацию на основе ориентации в данных 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 ответов
попробовать Imagick::setImageOrientation
. Экспериментируйте с доступные константы.
"однако-iMagick, когда _ _ construct'ED с этим изображением, автоматически поворачивает его на дополнительные 90 градусов CCW согласно [Orientation] = > 6 (я думаю!)."
проблема на самом деле наоборот. Imagick не автоматическое вращение изображения. Вы видите его правильно только в другом программном обеспечении / вашем веб-браузере, потому что эти программы автоматически поворачивают его на основе информации EXIF. Некоторые операции в Imagick заставят вас потерять это правильная информация EXIF (копирование изображения, миниатюры (), 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 возникает, когда изображение появляется вверх ногами. Существует отличная иллюстрация различных кодов ориентации от Calvin Хасс.
Возможно, что информация об ориентации может появиться в другой части exif_read_data
array (в зависимости от модели камеры, я думаю), поэтому я попытался учесть это в моем примере кода.
что-то вроде этого:
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
. The отсутствие of Orientation
в преобразованном изображении предотвратит дальнейшую обработку от попытки "исправить" вещи путем вращения снова. Я желаю Imagick была поддержка ImageMagick в -auto-orient
, ну да ладно.
Да, это вращение является операции с потерями (если вы не используете jpegtran), поэтому вы должны попытаться сделать это только в в сочетании с изменением размера или другим преобразованием.
этот код в отличном ответе оррда требует 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>";