J'utilise le code suivant pour faire pivoter une image jpeg téléchargée si l'orientation est désactivée. Je n'ai que des problèmes avec les images téléchargées à partir d'iPhones et d'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';
}
Est-ce que je fais quelque chose de mal avec la façon dont je lis les données EXIF du jpeg? Il ne s'agit pas de faire pivoter les images comme il est supposé.
C'est ce qui se passe quand je lance 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) }
La documentation de imagerotate fait référence à un type différent du premier paramètre que celui que vous utilisez:
Une ressource image, renvoyée par l'une des fonctions de création d'image, telle que imagecreatetruecolor ().
Voici un petit exemple d'utilisation de cette fonction:
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);
}
Basé sur le code de Daniel, j'ai écrit une fonction qui fait simplement pivoter une image si nécessaire, sans ré-échantillonnage.
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;
}
}
}
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);
}
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;
}
}
}
Fonction plus simple pour ceux qui téléchargent une image, il effectue juste une autorotation si nécessaire.
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);
}
}
Juste au cas où quelqu'un tomberait dessus. D'après ce que je peux comprendre, certaines des déclarations ci-dessus sont fausses.
Basé sur l'information ici , il devrait être:
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;
}
Il vaut probablement la peine de mentionner que si vous utilisez ImageMagick à partir de la ligne de commande, vous pouvez utiliser l'option - auto-orient qui fera pivoter automatiquement l'image en fonction des données d'orientation EXIF existantes.
convert -auto-orient /tmp/uploadedImage.jpg /save/to/path/image.jpg
Remarque: si les données EXIF ont été supprimées avant le processus, elles ne fonctionneront pas comme décrit.
Pourquoi personne ne considère les cas en miroir 2,4,5,7? Il y a 4 autres cas sur les terres d'orientation exif:
Voici une solution complète prenant un nom de fichier:
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;
}
Ici, j’explique tout, j’utilise Laravel) et j’utilise le paquet d’intervention image.
Tout d'abord, je récupère mon image et l'envoie à une autre fonction de redimensionnement et à d'autres fonctionnalités. Si nous n'en avons pas besoin, vous pouvez ignorer ...
Prenez le fichier avec une méthode dans mon contrôleur,
public function getImageFile(Request $request){
$image = $request->image;
$this->imageUpload($image);
}
Maintenant, je l'envoie pour redimensionner et obtenir le nom de l'image et l'extension ...
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;
}
Maintenant, j'appelle ma fonction d'orientation d'image,
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);
}
}
Et c'est tout...
jhead -autorot jpegfile.jpg
C'est aussi un moyen utile d'aborder cela.
jhead est un programme standard sous Linux (utilisez 'Sudo apt-get install jhead' pour installer), cette option examine l'orientation et fait pivoter l'image correctement et sans perte, uniquement si elle est requise. Il met ensuite également à jour les données EXIF correctement.
De cette manière, vous pouvez traiter un fichier jpeg (ou plusieurs fichiers jpeg dans un dossier) d’une manière simple en un seul passage qui corrige les problèmes de rotation de façon permanente.
E.g: jhead -autorot * .jpg corrigera tout un dossier d’images jpeg de la manière dont le PO a besoin dans la question initiale.
Bien que ce ne soit pas techniquement PHP, j’ai lu ce fil de discussion, puis j’ai utilisé ma suggestion jhead, appelé à partir d’un appel PHP system () pour obtenir les résultats que j’étais après quoi coïncidaient avec les PO: faire pivoter les images pour que tout logiciel (comme 'fbi' dans Raspbian) puisse les afficher correctement.
À la lumière de cela, j’ai pensé que d’autres pourraient tirer avantage de savoir avec quelle facilité jhead résout ce problème et n’a publié les informations ici qu’à titre informatif - car personne ne l’avait mentionné auparavant.
Je n'aime pas trop insister sur un autre ensemble de valeurs d'orientation, mais après avoir utilisé l'une des valeurs répertoriées ci-dessus, j'ai toujours eu des images à l'envers lors du téléchargement de photos d'orientation portrait directement à partir d'un iPhone. Voici la déclaration de commutateur je me suis retrouvé avec.
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;
}
J'ai également utilisé orientate()
form Intervention, et cela fonctionne parfaitement.
$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);