Estoy usando el siguiente código para rotar una imagen jpeg cargada si la orientación está apagada. Solo tengo 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 leo los datos EXIF del jpeg? No está rotando las imágenes como se supone.
Esto es lo que sucede cuando ejecuto un 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) }
php
orientation
exif
Jeff Thomas
fuente
fuente
var_dump($exif)
para ver qué están produciendo los teléfonos Android en cuanto a datos de rotación.$exif['COMPUTED']['Orientation']
y tiene valor 6.Respuestas:
La documentación de imagerotate se refiere a un tipo diferente para el primer parámetro del que usa:
A continuación, se muestra un pequeño ejemplo del uso de 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); }
fuente
Basado en el código de Daniel, escribí una función que simplemente rota 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; } } }
fuente
getImageOrientation()
no me funcionó correctamente incluso con imágenes sin procesar convertidas. El código anterior funcionó perfectamente.Función más simple para aquellos que cargan una imagen, simplemente gira automáticamente 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); } }
fuente
$exif = @exif_read_data($filename);
¿Por qué nadie está considerando los casos reflejados 2,4,5,7? Hay 4 casos más en terrenos de orientación exif:
Aquí hay una solución completa que toma un nombre de archivo:
function __image_orientate($source, $quality = 90, $destination = null) { if ($destination === null) { $destination = $source; } $info = getimagesize($source); if ($info['mime'] === 'image/jpeg') { $exif = exif_read_data($source); if (!empty($exif['Orientation']) && in_array($exif['Orientation'], [2, 3, 4, 5, 6, 7, 8])) { $image = imagecreatefromjpeg($source); if (in_array($exif['Orientation'], [3, 4])) { $image = imagerotate($image, 180, 0); } if (in_array($exif['Orientation'], [5, 6])) { $image = imagerotate($image, -90, 0); } if (in_array($exif['Orientation'], [7, 8])) { $image = imagerotate($image, 90, 0); } if (in_array($exif['Orientation'], [2, 5, 7, 4])) { imageflip($image, IMG_FLIP_HORIZONTAL); } imagejpeg($image, $destination, $quality); } } return true; }
fuente
Por si acaso alguien se encuentra con esto. Por lo que puedo distinguir, algunas de las declaraciones de cambio anteriores son incorrectas.
Según la información aquí , 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; }
fuente
Probablemente valga la pena mencionar que si está usando ImageMagick desde la línea de comando, puede usar la opción -auto-orient que rotará automáticamente la imagen en función de los datos de orientación EXIF existentes.
Tenga en cuenta: si los datos EXIF se eliminaron antes del proceso, no funcionarán como se describe.
fuente
Aquí estoy explicando todo, uso Laravel y uso el Paquete de intervención de imágenes.
En primer lugar, obtengo mi imagen y la envío a mi otra función para cambiar el tamaño y alguna otra funcionalidad, si no la necesitamos, puede omitir ...
Coge 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...
fuente
Odio intervenir con otro conjunto de valores de orientación, pero en mi experiencia al usar cualquiera de los valores enumerados anteriormente, siempre terminaba con imágenes al revés cuando cargaba tomas de 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; }
fuente
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 rota la imagen correctamente y sin pérdidas solo si es necesario. Luego también actualiza correctamente los datos EXIF.
De esta manera, puede procesar un jpeg (o varios jpegs en una carpeta) de una manera simple de una sola pasada que corrige 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 usé mi sugerencia jhead en su lugar, llamé desde una llamada al sistema PHP () para lograr los resultados que buscaba, que coincidían con los OP: rotar imágenes para que cualquier software (como 'fbi 'en Raspbian) podría mostrarlos correctamente.
En vista de esto, pensé que otros podrían beneficiarse al saber con qué facilidad jhead resuelve este problema y publiqué la información aquí solo con fines informativos, porque nadie lo había mencionado anteriormente.
fuente
También utilicé la
orientate()
intervención de formularios y funciona perfectamente.$image_resize = Image::make($request->file('photo')); $image_resize->resize(1600, null,function ($constraint) { $constraint->aspectRatio(); }); $filename = $this->checkFilename(); $image_resize->orientate()->save($this->photo_path.$filename,80);
fuente
Aquí está mi función PHP 7 inspirada en @ user462990:
/** * @param string $filePath * * @return resource|null */ function rotateImageByExifOrientation(string $filePath) { $result = null; $exif = exif_read_data($filePath); if (!empty($exif['Orientation'])) { $image = imagecreatefromjpeg($filePath); if (is_resource($image)) { switch ($exif['Orientation']) { case 3: $result = imagerotate($image, 180, 0); break; case 6: $result = imagerotate($image, -90, 0); break; case 8: $result = imagerotate($image, 90, 0); break; } } } return $result; }
uso:
$rotatedFile = rotateImageByExifOrientation($absoluteFilePath); if (is_resource($rotatedFile)) { imagejpeg($rotatedFile, $absoluteFilePath, 100); }
fuente
La imagen de intervención tiene un método
orientate()
.$img = Image::make('foo.jpg')->orientate();
fuente