been trying to detect the image orientation of uploaded images from iPhones and then adjust their orientation from that.
I am trying to fix the issue where images taken in potrait, are uploaded with a -90 degree rotate. I tried numerous switch statements which were not working, so decided to return the exif data in my JSON return.
The issue i see is that their is no orientation in the exif data.
I am doing so:
$imagefile = $fileToUpload["tmp_name"];
$destinationImage = imagecreatefromstring(file_get_contents($imagefile));
$exif = exif_read_data($imagefile);
$moveUploadedFile = imagejpeg($destinationImage, $this->uploadDir . "/" . $newFileName, 100);
imagedestroy($destinationImage);
if ($moveUploadedFile) {
$return['ort'] = $exif;
echo json_encode($return);
}
What i am seeing in my return (using firebug) is:
FileName:"phpUQZFHh"
FileDateTime:1410465904
FileSize:473421
FileType:2
MimeType:"image/jpeg"
SectionsFound:"COMMENT"
Computed: OBJECT:
Height:700
Width:933
IsColor:1
Comment: ARRAY:
0:"CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 100"
I want to be able use the exif data like so:
if (!empty($exif['Orientation'])){
//get the orientation
$ort = $exif['Orientation'];
//determine what oreientation the image was taken at
switch($ort){
case 2: // horizontal flip
break;
case 3: // 180 rotate left
$destinationImage = imagerotate($destinationImage, 180, -1);
break;
}
}
Any help?
EDIT: After downloaded an image that had been uploaded and checking its properties it appears that all exif data was removed in the upload process.
This still baffles me as to why it is rotated before / during upload / how to fix this.
I guess the "Orientation" value presents in the returned data of exif_read_data function in case when you upload the picture from your iOS device only. It won't work in desktop browser. I might be wrong.
I ran into the same problem. Turns out some images really did not have any exif data on Orientation at all -- usually ones with the "correct" orientation do not have it. I tried one landscape image taken with an iPhone and there was.
In your case, the photos may have had no exif data in the first place. I had some photos like that as well (rotated -90 degrees but no Orientation info). I could be wrong but without exif data, there's no programmatic way to know if an image is incorrectly oriented.
For incorrectly oriented photos without Orientation info, I suggest you just make sure the user sees (gets a preview) of what about to be uploaded. IME, most users are more than willing to get out of their way to fire up paint/photoshop/etc. just to ensure they have good looking photos.
You can get Orientation value before move the file to the server directory (Worked with iPhone as well)
$image = $_FILES["image"]["tmp_name"];
$orientation = '';
if (function_exists('exif_read_data'))
{
$exif = exif_read_data(image);
if($exif && isset($exif['Orientation']))
$orientation = $exif['Orientation'];
}
Related
I have developed a website in PHP which displays the many thousands of photos I've taken over the years. To date I've had no problem with orientation - landscape and portrait pictures all display correctly.
I have recently started editing some of the photos and it has changed some of their orientation. I have now modified my code to handle EXIF's 'Orientation' data (using the function 'correctImageOrientation' created by Wes on Stack Overflow - many thanks Wes!) to rotate the photos accordingly and it works well.
However, some of my edited photos do not now have EXIF Orientation data so I can't use it to rotate the photo but yet File Explorer somehow knows the correct orientation and displays the photo correctly.
My question, therefore, is where does File Explorer get the photos orientation from and how do I access it from PHP?
Can't comment yet, so will post as answer.
Exif data is just metadata which is used by specific devices. Otherwise it can be stripped. You could explore this workaround from the comment section in php's manual:
$orientation = 1;
if (function_exists('exif_read_data')) {
$exif = exif_read_data($filename);
if (isset($exif['Orientation'])) $orientation = $exif['Orientation'];
} else if (preg_match('#\x12\x01\x03\x00\x01\x00\x00\x00(.)\x00\x00\x00#', file_get_contents($filename), $matches)) {
$orientation = ord($matches[1]);
}
I’m experiencing some strange issues with image rotation.
Originally we were having the problem of some users uploading images onto our site but they were appearing the wrong way around. We therefore wanted to implement some code to check the EXIF Orientation flag and rotate the image if necessary.
Here is what the simplified function looks like:
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, 100);
}
}
This seems to work fine for the images which have the Orientation flag set, were rotated and causing the original issue.
However, bizarrely I have found a number of images previously uploaded onto our server (we retain the original image with EXIF data intact) from before we have implemented the above code which appear to contain an Orientation flag (of say ‘3’) but their raw picture is the correct way up. If I feed one of these images into my new upload code it reads the Orientation flag and rotates the image, but the image was the correct way around to begin with.
I believe the user has likely manually rotated the image prior to upload yet it’s still retaining the Orientation flag value. For example, if I rotate an image in Paint it seems to retain the same Orientation value. Here is an example image http://s16.postimg.org/cv5ejchqt/exig.jpg (arrow points to the true top of the image), yet it has the Orientation flag value of 3 so is rotated when using my new upload code.
Is there a way to detect if the user has manually rotated, somehow?
Thanks
I use a PHP script that uploads an image, then gets the dimensions with PHP's getImageSize() and then does things to the image according to the pictures orientation (portrait or landscape).
However (PHP version 5.4.12) on some .jpg files it gets the height and width as they are, and in some (taken with an iPhone) it swaps them, thinking the portrait pictures are actually landscape.
It does not only happen on my local Wampserver, but also on a remote server (with a different PHP version).
Has anyone a clue how
1) to repair this or
2) find a way around the problem?
Some cameras include an orientation tag within the metadata section of the file itself. This is so the device itself can show it in the correct orientation every time regardless of the picture's orientation in its raw data.
It seems like Windows doesn't support reading this orientation tag and instead just reads the pixel data and displays it as-is.
A solution would be to either change the orientation tag in afflicted pictures' metadata on a per-image basis, OR
Use PHP's exif_read_data() function to read the orientation and orient your image accordingly like so:
<?php
$image = imagecreatefromstring(file_get_contents($_FILES['image_upload']['tmp_name']));
$exif = exif_read_data($_FILES['image_upload']['tmp_name']);
if(!empty($exif['Orientation'])) {
switch($exif['Orientation']) {
case 8:
$image = imagerotate($image,90,0);
break;
case 3:
$image = imagerotate($image,180,0);
break;
case 6:
$image = imagerotate($image,-90,0);
break;
}
}
// $image now contains a resource with the image oriented correctly
?>
References:
https://stackoverflow.com/a/10601175/1124793 (research as to why this is happening)
http://php.net/manual/en/function.exif-read-data.php#110894 (PHP Code)
Function getimagesize() changes width and height in photos that are landscape orientation (horizontal) .
You can use this code:
<?php
$img = "test.jpg";
$exif = exif_read_data($img);
if(empty($exif['Orientation'])) {
list($width, $height, $type, $attr) = getimagesize($img);
}else{
list($height, $width, $type, $attr) = getimagesize($img);
}
?>
But it was fixed automatically in PHP7 and above.
Using the safari mobile browser with IOS6, the file upload function gives users the option to snap a photo. Unfortunately, upon snapping the photo, while the photo thumb shows up properly in the browser, when you upload to a server, the file is rotated 90 degrees. This appears to be due to the exif data that the iphone sets. I have code that fixes the orientation by rotating the image when serving. However, I suspect it would be better to save the rotated, properly oriented, image so I no longer have to worry about orientation. Many of my other photos do not even have exif data and i don't want to mess with it if I can avoid it.
Can anyone suggest code to save the image so it is properly oriented?
Here is the code that rotates the image. The following code will display the properly oriented image, however, what I want to do is save it so I can then serve it whenever I want without worrying about orientation.
Also I would like to replace impagejpeg call in code below so that any code works for gifs as well as jpgs.
Thanks for suggestions/code!
PHP
//Here is sample image after uploaded to server and moved to a directory
$target = "pics/779_pic.jpg";
$source = imagecreatefromstring(file_get_contents($target));
$exif = exif_read_data($target);
if(!empty($exif['Orientation'])) {
switch($exif['Orientation']) {
case 8:
$image = imagerotate($source,90,0);
//echo 'It is 8';
break;
case 3:
$image = imagerotate($source,180,0);
//echo 'It is 3';
break;
case 6:
$image = imagerotate($source,-90,0);
//echo 'It is 6';
break;
}
}
// $image now contains a resource with the image oriented correctly
//This is where I want to save resource properly oriented instead of display.
header('Content-type: image/jpg');
imagejpeg($image);
?>
Only JPEG or TIFF files can carry EXIF metadata, so there's no need to worry about handling GIFs (or PNGs, for that matter) with your code.
From page 9 of what I believe is the official specification:
Compressed files are recorded as JPEG (ISO/IEC 10918-1) with application marker segments (APP1 and APP2) inserted. Uncompressed files are recorded in TIFF Rev. 6.0 format.
http://www.cipa.jp/english/hyoujunka/kikaku/pdf/DC-008-2010_E.pdf
To save your image just use the same function imagejpeg and the next parameter to save the image, something like:
imagejpeg($image, $target, 100);
In this case you don't need the specify the header, because you are not showing nothing.
Reference:
http://sg3.php.net/manual/en/function.imagejpeg.php
When I use the GD image library the orientation EXIF data is missing, is it possible to get the data straight from the raw data string before I use imagecreatefromstring() to make the jpg file? The orientation data is there because when I look at the email in gmail in chrome it shows the proper orientation, but as soon as I download the image that data is lost. I also tried using exif_thumbnail to see if I could figure out the orientation from that but the thumbnail is missing too.
If I download the attachment through chrome, windows image viewer displays it as landscape, but if I upload it to flickr it is displayed portrait, what is flickr using to determine orientation?
EDIT: solved it
createimagefromstring strips out a ton of meta data from the image file, but using fwrite creates the file verbatim from the data string, so I did this
$filename = 'pic.jpg';
$r = fopen($filename,'x');
fwrite($r,$raw_data); //$raw_data is the data string of the image
fclose($r);
and voila all the exif data was there! Stupid GD library! >:(
If you're really using the GD library like you say you are, you can leverage getimagesize() to check for the image's dimensions. If the width is greater than the height of the image, you can safely assume that it was taken in landscape mode.
$params = getimagesize($image);
$width = $params[0];
$height = $params[1];
if ($width > $height) {
$mode = "landscape";
} else if ($width < $height) {
$mode = "portrait";
}