2010-11-24 15 views
18

Actualmente estoy trabajando con PHP e iMagick para desarrollar una aplicación web de impresión de pósters.Cómo detener las imágenes auto-rotatorias de PHP iMagick basadas en los datos de orientación EXIF ​​

Esta es la imagen de ejemplo que estoy utilizando para probar las funciones de edición de carga/de imagen de la aplicación:

alt text

La imagen contiene los siguientes datos 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 

Sin embargo - imagick , cuando __constructó con esta imagen, la gira automáticamente 90 grados adicionales de CCW según [Orientation] => 6 (¡creo!). Lo que resulta en este ...

alt text

Lo que me gustaría saber es ...

¿Cómo puedo mantener la orientación original de la imagen que se ve en la parte superior de la página? ¿Y esto es posible al desactivar la rotación automática realizada por iMagick?

Muchas gracias

ACTUALIZACIÓN: Aquí está la solución que yo he llegado con ... Se fijará la orientación basada en la orientación en los datos 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; 

     } 

} 

Respuesta

3
+0

gracias izym. ¿Tiene más información sobre cómo se pueden usar estas constantes? – kaese

+1

Tenga en cuenta que Imagick :: setImageOrientation() en realidad no rota la imagen, simplemente cambia la información de rotación EXIF ​​que se guardará con la imagen. En algunos casos, eso puede ser lo que desea hacer, pero generalmente es mejor rotar físicamente la imagen (vea la muestra del código que publiqué como respuesta). El problema de depender de la información de rotación EXIF ​​es que no todos los navegadores web y el software de visualización de imágenes lo orientarán automáticamente. – orrd

1

Buen comienzo: algunas adiciones para que la función sea más robusta. Primero, el caso 3 ocurre cuando la imagen aparece al revés. Hay una GRAN ilustración de los diferentes códigos de orientación by Calvin Hass. Es posible que la información de orientación aparezca en una parte diferente de la matriz exif_read_data (dependiendo del modelo de la cámara, creo), así que traté de tener esto en cuenta en mi código de ejemplo.

Algo como esto:

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; 
    } 
} 

La transformación & Guardar le deja sin la información EXIF ​​anterior, incluyendo Orientation. El falta de Orientation en la imagen transformada evitará que el procesamiento posterior intente 'corregir' las cosas volviendo a girar. Ojalá Imagick tuviera soporte para ImageMagick's -auto-orient, pero bueno.

Ah, también: la rotación es un lossy operation (a menos que utilice jpegtran), por lo que debe tratar de hacerlo sólo en conjunción con un cambio de tamaño o cualquier otra transformación.

+0

Grandes adiciones a la función original - ¡gracias! – kaese

+0

¿Por qué FFF no 000? ¿Hay alguna diferencia en el rendimiento? –

+0

Ese primer argumento es solo el color del lienzo. – ajmicek

39

"Sin embargo, iMagick, cuando __construido con esta imagen, lo gira automáticamente una CCW de 90 grados adicionales según [Orientación] => 6 (¡creo!)".

El problema es realmente lo contrario. Imagick no rotar automáticamente la imagen. Solo lo está viendo correctamente en otro software/su navegador web porque esos programas lo rotan automáticamente según la información EXIF.Ciertas operaciones en Imagick harán que pierda esa información EXIF ​​correcta (copiando la imagen, thumbnailImage(), stripImage() y otras manipulaciones). Entonces, lo que tienes que hacer en ese caso es rotar físicamente la imagen.

La respuesta de ajmicek es buena, pero se podría mejorar un poco utilizando las funciones integradas de Imagick en lugar de las funciones PHP EXIF. Además, ese fragmento parece haber sido parte de una clase, por lo que no se puede usar como una función separada tal como está. También es una buena idea establecer la orientación EXIF ​​correcta con setImageOrientation() después de rotarla.

// 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); 
} 

Ejemplo del uso:

$image = new Imagick('my-image-file.jpg'); 
autoRotateImage($image); 
// - Do other stuff to the image here - 
$image->writeImage('result-image.jpg'); 
+0

gran explicación - esto funciona como se desee. – Brade

+0

Tantas horas ahorradas. – jack

+0

@orrd Por favor, ¿puede convertirlo en CodeIgniter –

0

Este código en excelente respuesta de orrd requiere la versión 6.3+ imagick .:

$ imagen-> setImageOrientation (imagick :: ORIENTATION_TOPLEFT);

Funciona perfectamente y se ocupa de las diferencias de orientación del os/dispositivo. No funcionaría con 6.2.

He codificado para obtener el dispositivo. Aquí en caso de que alguien lo necesite.

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