exif_read_data php orientation exif

exif_read_data - exif php



PHP read_exif_data y Adjust Orientation (9)

Estoy usando el siguiente código para rotar una imagen jpeg cargada si la orientación está desactivada. Solo estoy teniendo problemas con las imágenes cargadas desde iPhones y Android.

if(move_uploaded_file($_FILES[''photo''][''tmp_name''], $upload_path . $newfilename)){ chmod($upload_path . $newfilename, 0755); $exif = exif_read_data($upload_path . $newfilename); $ort = $exif[''IFD0''][''Orientation'']; switch($ort) { case 3: // 180 rotate left $image->imagerotate($upload_path . $newfilename, 180, -1); break; case 6: // 90 rotate right $image->imagerotate($upload_path . $newfilename, -90, -1); break; case 8: // 90 rotate left $image->imagerotate($upload_path . $newfilename, 90, -1); break; } imagejpeg($image, $upload_path . $newfilename, 100); $success_message = ''Photo Successfully Uploaded''; }else{ $error_count++; $error_message = ''Error: Upload Unsuccessful<br />Please Try Again''; }

¿Estoy haciendo algo mal con la forma en que estoy leyendo los datos EXIF ​​del jpeg? No está girando las imágenes como se supone que debe hacerlo.

Esto es lo que sucede cuando ejecuto var_dump ($ exif);

array(41) { ["FileName"]=> string(36) "126e7c0efcac2b76b3320e6187d03cfd.JPG" ["FileDateTime"]=> int(1316545667) ["FileSize"]=> int(1312472) ["FileType"]=> int(2) ["MimeType"]=> string(10) "image/jpeg" ["SectionsFound"]=> string(30) "ANY_TAG, IFD0, THUMBNAIL, EXIF" ["COMPUTED"]=> array(8) { ["html"]=> string(26) "width="2048" height="1536"" ["Height"]=> int(1536) ["Width"]=> int(2048) ["IsColor"]=> int(1) ["ByteOrderMotorola"]=> int(1) ["ApertureFNumber"]=> string(5) "f/2.8" ["Thumbnail.FileType"]=> int(2) ["Thumbnail.MimeType"]=> string(10) "image/jpeg" } ["Make"]=> string(5) "Apple" ["Model"]=> string(10) "iPhone 3GS" ["Orientation"]=> int(6) ["XResolution"]=> string(4) "72/1" ["YResolution"]=> string(4) "72/1" ["ResolutionUnit"]=> int(2) ["Software"]=> string(5) "4.3.5" ["DateTime"]=> string(19) "2011:09:16 21:18:46" ["YCbCrPositioning"]=> int(1) ["Exif_IFD_Pointer"]=> int(194) ["THUMBNAIL"]=> array(6) { ["Compression"]=> int(6) ["XResolution"]=> string(4) "72/1" ["YResolution"]=> string(4) "72/1" ["ResolutionUnit"]=> int(2) ["JPEGInterchangeFormat"]=> int(658) ["JPEGInterchangeFormatLength"]=> int(8231) } ["ExposureTime"]=> string(4) "1/15" ["FNumber"]=> string(4) "14/5" ["ExposureProgram"]=> int(2) ["ISOSpeedRatings"]=> int(200) ["ExifVersion"]=> string(4) "0221" ["DateTimeOriginal"]=> string(19) "2011:09:16 21:18:46" ["DateTimeDigitized"]=> string(19) "2011:09:16 21:18:46" ["ComponentsConfiguration"]=> string(4) "" ["ShutterSpeedValue"]=> string(8) "3711/949" ["ApertureValue"]=> string(9) "4281/1441" ["MeteringMode"]=> int(1) ["Flash"]=> int(32) ["FocalLength"]=> string(5) "77/20" ["SubjectLocation"]=> array(4) { [0]=> int(1023) [1]=> int(767) [2]=> int(614) [3]=> int(614) } ["FlashPixVersion"]=> string(4) "0100" ["ColorSpace"]=> int(1) ["ExifImageWidth"]=> int(2048) ["ExifImageLength"]=> int(1536) ["SensingMethod"]=> int(2) ["ExposureMode"]=> int(0) ["WhiteBalance"]=> int(0) ["SceneCaptureType"]=> int(0) ["Sharpness"]=> int(1) }


Aquí estoy explicando todo, uso Laravel y uso el paquete de Intervención de imágenes.

Antes que nada, obtengo mi imagen y la envío a mi otra función para cambiar el tamaño y otra funcionalidad, si no la necesitamos, puede omitir ...

Toma el archivo con un método en mi controlador,

public function getImageFile(Request $request){ $image = $request->image; $this->imageUpload($image); }

Ahora, lo envío para cambiar el tamaño y obtener el nombre y la extensión de la imagen ...

public function imageUpload($file){ ini_set(''memory_limit'', ''-1''); $directory = ''uploads/''; $name = str_replace([" ", "."], "_", $file->getClientOriginalName()) . "_"; $file_name = $name . time() . rand(1111, 9999) . ''.'' . $file->getClientOriginalExtension(); //path set $img_url = $directory.$file_name; list($width, $height) = getimagesize($file); $h = ($height/$width)*600; Image::make($file)->resize(600, $h)->save(public_path($img_url)); $this->image_fix_orientation($file,$img_url); return $img_url; }

Ahora llamo a mi función de orientación de imagen,

public function image_fix_orientation($file,$img_url ) { $data = Image::make($file)->exif(); if (!empty($data[''Orientation''])) { $image = imagecreatefromjpeg($file); switch ($data[''Orientation'']) { case 3: $image = imagerotate($image, 180, 0); break; case 6: $image = imagerotate($image, -90, 0); break; case 8: $image = imagerotate($image, 90, 0); break; } imagejpeg($image, $img_url, 90); } }

Y eso es todo...


Basado en el código de Daniel, escribí una función que simplemente gira una imagen si es necesario, sin remuestrear.

GD

function image_fix_orientation(&$image, $filename) { $exif = exif_read_data($filename); if (!empty($exif[''Orientation''])) { switch ($exif[''Orientation'']) { case 3: $image = imagerotate($image, 180, 0); break; case 6: $image = imagerotate($image, -90, 0); break; case 8: $image = imagerotate($image, 90, 0); break; } } }

Versión de una línea (GD)

function image_fix_orientation(&$image, $filename) { $image = imagerotate($image, array_values([0, 0, 0, 180, 0, 0, -90, 0, 90])[@exif_read_data($filename)[''Orientation''] ?: 0], 0); }

ImageMagick

function image_fix_orientation($image) { if (method_exists($image, ''getImageProperty'')) { $orientation = $image->getImageProperty(''exif:Orientation''); } else { $filename = $image->getImageFilename(); if (empty($filename)) { $filename = ''data://image/jpeg;base64,'' . base64_encode($image->getImageBlob()); } $exif = exif_read_data($filename); $orientation = isset($exif[''Orientation'']) ? $exif[''Orientation''] : null; } if (!empty($orientation)) { switch ($orientation) { case 3: $image->rotateImage(''#000000'', 180); break; case 6: $image->rotateImage(''#000000'', 90); break; case 8: $image->rotateImage(''#000000'', -90); break; } } }


Función más simple para aquellos que cargan una imagen, solo autorrota si es necesario.

function image_fix_orientation($filename) { $exif = exif_read_data($filename); if (!empty($exif[''Orientation''])) { $image = imagecreatefromjpeg($filename); switch ($exif[''Orientation'']) { case 3: $image = imagerotate($image, 180, 0); break; case 6: $image = imagerotate($image, -90, 0); break; case 8: $image = imagerotate($image, 90, 0); break; } imagejpeg($image, $filename, 90); } }


La documentación para imagerotate refiere a un tipo diferente para el primer parámetro que usted usa:

Un recurso de imagen, devuelto por una de las funciones de creación de imagen, como imagecreatetruecolor ().

Aquí hay un pequeño ejemplo para usar esta función:

function resample($jpgFile, $thumbFile, $width, $orientation) { // Get new dimensions list($width_orig, $height_orig) = getimagesize($jpgFile); $height = (int) (($width / $width_orig) * $height_orig); // Resample $image_p = imagecreatetruecolor($width, $height); $image = imagecreatefromjpeg($jpgFile); imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig); // Fix Orientation switch($orientation) { case 3: $image_p = imagerotate($image_p, 180, 0); break; case 6: $image_p = imagerotate($image_p, -90, 0); break; case 8: $image_p = imagerotate($image_p, 90, 0); break; } // Output imagejpeg($image_p, $thumbFile, 90); }


La imagen de intervención tiene un método orientate() .

$img = Image::make(''foo.jpg'')->orientate();


Odio tener otro conjunto de valores de orientación, pero en mi experiencia usando cualquiera de los valores enumerados anteriormente, siempre terminé con imágenes boca abajo cuando cargaba fotos con orientación vertical directamente desde un iPhone. Aquí está la declaración de cambio con la que terminé.

switch ($exif[''Orientation'']) { case 3: $image = imagerotate($image, -180, 0); break; case 6: $image = imagerotate($image, -90, 0); break; case 8: $image = imagerotate($image, 90, 0); break; }


Por si acaso alguien se encuentra con esto. Por lo que puedo entender, algunas de las declaraciones de cambio anteriores son incorrectas.

Según la información here , debería ser:

switch ($exif[''Orientation'']) { case 3: $image = imagerotate($image, -180, 0); break; case 6: $image = imagerotate($image, 90, 0); break; case 8: $image = imagerotate($image, -90, 0); break; }


Probablemente valga la pena mencionar que si está utilizando ImageMagick desde la línea de comandos, puede usar la opción -auto-orient que rotará automáticamente la imagen en función de los datos de orientación EXIF ​​existentes.

convert -auto-orient /tmp/uploadedImage.jpg /save/to/path/image.jpg

Tenga en cuenta: si los datos EXIF ​​se quitaron antes del proceso, no funcionarán como se describe.


jhead -autorot jpegfile.jpg

También es una forma útil de abordar esto.

jhead es un programa estándar en Linux (use ''sudo apt-get install jhead'' para instalar), esta opción mira la orientación y gira la imagen de manera correcta y sin pérdidas solo si así lo requiere. Luego también actualiza los datos EXIF ​​correctamente.

De esta forma, puede procesar un jpeg (o varios jpegs en una carpeta) de una sola pasada que solucione los problemas de rotación de forma permanente.

Por ejemplo: jhead -autorot * .jpg arreglará una carpeta completa de imágenes jpeg de la manera que el OP requiere en la pregunta inicial.

Si bien no es técnicamente PHP, leí este hilo y luego utilicé mi sugerencia jhead, llamada desde una llamada al sistema PHP () para lograr los resultados que buscaba y que coincidían con los PO: rotar imágenes para cualquier software (como ''fbi ''en Raspbian) podría mostrarlos correctamente.

A la luz de esto, pensé que otros podrían beneficiarse de saber con qué facilidad resolvió jhead este problema y publicó la información aquí solo con fines informativos, porque nadie lo había mencionado anteriormente.