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.
Related
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
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'];
}
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
how to take image from one folder and rename and re-size the images and move to another folder?
I need to get image from one folder and rename and re-size the same image and move into another folder using php
You will most likely be using gd for resizing the images.
Here is a pretty crappy, but hopefully useful code sample. In this case, $originalName is the name given in the $_FILES array's tmp_name position. I am resizing to a width of 1200 in this case, with the height adapting according to such width. You might (and most likely will) not desire this behavior. This is just some ugly code I used in some courses I taught about 3 years ago, I don't have the newer samples in this computer so you will have to get used to the idea :)
$newDir is where the file will be located. by calling imagejpeg or imagepng and passing the filename as second argument, it means to the function that you wish to save the image in that location.
if ($type == 'image/jpeg') {
$original = imagecreatefromjpeg($originalName);
}
else {
$original = imagecreatefrompng($originalName);
}
$width = imagesx($original);
$height = imagesy($original);
//prepare for creation of image with width of 1000
$new_height = floor($height * (1200 / $width));
// create the 1200 width image
$tmp_img = imagecreatetruecolor(1200, $new_height);
// copy and resize old image into new image
imagecopyresized($tmp_img, $original, 0, 0, 0, 0,
1200, $new_height, $width, $height);
//create a random and unique name to identify (here it isn't that random ;)
$newDir = '/this/is/some/directory/and/filename.';
if ($type == 'image/jpeg') {
imagejpeg($tmp_img, $newDir."jpg");
}
else {
imagepng($tmp_img, $newDir."png");
}
Many file system functions are already built-in with PHP (e.g. rename), and you'll find most of what you need to resize images by using the GD library here.
There are libraries available in PHP for image resize.
Here are some useful links you may like.
http://www.fliquidstudios.com/2009/05/07/resizing-images-in-php-with-gd-and-imagick/
http://php.net/manual/en/book.image.php
PHP/GD - Cropping and Resizing Images
http://net.tutsplus.com/tutorials/php/image-resizing-made-easy-with-php/
Use imagick http://php.net/manual/en/imagick.resizeimage.php
If I were you I would write a PE using a diffent language (one that you might be best used to) to adjust anything of the given image then just feel free to phpexec it to do all the steps you mentioned, you can sit relax and wait for the end result. HHAHAHHA :-)
Use imagick library to resize; it's good.
In PHP I'm trying to process an image, that is, I'm trying to make the surrounding color transparent in a jpg file. I'm using the GD library by the way.
I can directly output the image by converting it into a png using imagecreatefromjpeg and imagepng functions. But I can't find a way to make the specified color transparent. Also, some images have lighter gray artifacts around black graphics, created during saving. Is there any way I can include those as well?
I'm kind of lost. I found some answers to make a color transparent on an image but I don't know how to first convert the image without saving it into the server and then process it.
Any ideas?
EDIT: Here's my code so far. I managed to make a specified color transparent but I can't make it detect the surrounding one yet.
Most of the time images will be closed because they'l be logos or texts, saved in the allowed image formats. So I don't think I will have a major issue with gradients but it would be great if I could manage to manipulate transparency in the surrounding gradients, if any, such as drop shadows.
Is there also any way to detect if the png/gif image is already transparent? My code paints the transparent parts into black for those files now.
$file = 'images/18.jpg';
$specs = getimagesize($file);
if($specs[2] == 1) $img = imagecreatefromgif($file); //gif
elseif($specs[2] == 2) $img = imagecreatefromjpeg($file); //jpg
elseif($specs[2] == 3) $img = imagecreatefrompng($file); //png
else exit('unsupported file type!');
$newimg = imagecreatetruecolor(imagesx($img), imagesy($img));
// create a new image with the size of the old one
imagecopy($newimg,$img,0,0,0,0,imagesx($img),imagesy($img));
// copy the old one
imagedestroy($img);
// free the memory
$white = imagecolorallocate($newimg,255,255,255);
imagecolortransparent($newimg,$white);
// make white pixels transparent
header('Content-Type: image/png');
imagepng($newimg);
imagedestroy($newimg);
// and finally output the new image
You can set the transparent color with the imagecolortransparent function.