How to detect shot angle of photo, and auto rotate for website display like desktop apps do on viewing?
In order to do that, you must read the EXIF information out of the JPEG file. You can either do that with exif
PHP extension or with PEL
.
Basically, you have to read the Orientation
flag in the file. Here is an example using the exif
PHP extension and WideImage
for image manipulation.
<?php
$exif = exif_read_data($filename);
$ort = $exif['Orientation'];
$image = WideImage::load($filename);
// GD doesn't support EXIF, so all information is removed.
$image->exifOrient($ort)->saveToFile($filename);
class WideImage_Operation_ExifOrient
{
/**
* Rotates and mirrors and image properly based on current orientation value
*
* @param WideImage_Image $img
* @param int $orientation
* @return WideImage_Image
*/
function execute($img, $orientation)
{
switch ($orientation) {
case 2:
return $img->mirror();
break;
case 3:
return $img->rotate(180);
break;
case 4:
return $img->rotate(180)->mirror();
break;
case 5:
return $img->rotate(90)->mirror();
break;
case 6:
return $img->rotate(90);
break;
case 7:
return $img->rotate(-90)->mirror();
break;
case 8:
return $img->rotate(-90);
break;
default: return $img->copy();
}
}
}
I modified Chris' example to add a check for the exif function, remove the mirroring, and also to write the file back out to the filesystem using the same filename. This way, you can call this function right after calling move_uploaded_file, like this:
move_uploaded_file($uploadedFile, $destinationFilename);
correctImageOrientation($destinationFilename);
function correctImageOrientation($filename) {
if (function_exists('exif_read_data')) {
$exif = exif_read_data($filename);
if($exif && isset($exif['Orientation'])) {
$orientation = $exif['Orientation'];
if($orientation != 1){
$img = imagecreatefromjpeg($filename);
$deg = 0;
switch ($orientation) {
case 3:
$deg = 180;
break;
case 6:
$deg = 270;
break;
case 8:
$deg = 90;
break;
}
if ($deg) {
$img = imagerotate($img, $deg, 0);
}
// then rewrite the rotated image back to the disk as $filename
imagejpeg($img, $filename, 95);
} // if there is some rotation necessary
} // if have the exif orientation info
} // if function exists
}
If you just want to use GD and the php EXIF extension you can use this:
function _mirrorImage ( $imgsrc)
{
$width = imagesx ( $imgsrc );
$height = imagesy ( $imgsrc );
$src_x = $width -1;
$src_y = 0;
$src_width = -$width;
$src_height = $height;
$imgdest = imagecreatetruecolor ( $width, $height );
if ( imagecopyresampled ( $imgdest, $imgsrc, 0, 0, $src_x, $src_y, $width, $height, $src_width, $src_height ) )
{
return $imgdest;
}
return $imgsrc;
}
function adjustPicOrientation($full_filename){
$exif = exif_read_data($full_filename);
if($exif && isset($exif['Orientation'])) {
$orientation = $exif['Orientation'];
if($orientation != 1){
$img = imagecreatefromjpeg($full_filename);
$mirror = false;
$deg = 0;
switch ($orientation) {
case 2:
$mirror = true;
break;
case 3:
$deg = 180;
break;
case 4:
$deg = 180;
$mirror = true;
break;
case 5:
$deg = 270;
$mirror = true;
break;
case 6:
$deg = 270;
break;
case 7:
$deg = 90;
$mirror = true;
break;
case 8:
$deg = 90;
break;
}
if ($deg) $img = imagerotate($img, $deg, 0);
if ($mirror) $img = _mirrorImage($img);
$full_filename = str_replace('.jpg', "-O$orientation.jpg", $full_filename);
imagejpeg($img, $full_filename, 95);
}
}
return $full_filename;
}
The rotation flag is stored as part of the EXIF data (see this article for more info).
You will need to read the rotation flag from the EXIF data in PHP and then rotate the image to suit. There are a variety of PHP EXIF libraries, if you have the web server set up with the extension installed you would be able to use the PHP provided library.
I would suggest rotating the image once on upload (e.g. using the GD library - most PHP installations these days seem to come with it), so that you don't need to worry about clearing the EXIF rotation data (not sure how easy this is with PHP, I've never tried it).