16

Is there a way to rotate a picture with PHP only if it is not correctly positioned after uploaded from iOS?

Some pictures are rotated 90 degrees while others upload correctly.

John Doe
  • 3,559
  • 15
  • 62
  • 111
  • this will helps you http://stackoverflow.com/questions/14231552/uploading-image-on-server-receiving-rotated-image/14231694#14231694 – Satish Azad Mar 10 '14 at 19:00
  • 2
    IOS devices process the orientation of the image when the photo is taken. If the photo is not rotated properly when it's uploaded to your service then the device was not able to properly judge the orientation when it was taken and the photo will need to be rotated by a person. – Sammitch Mar 10 '14 at 19:39
  • You will either be interested in lossless JPEG roation (AFAIK possible in 90 deg steps, you can find a library here: http://sylvana.net/jpegcrop/jpegtran/) and/or changing the orientation meta-data fields of that image. This depends on file-type and also how the device is handling this (see what @Sammitch wrote). – hakre Mar 16 '14 at 12:17

8 Answers8

61

Use exif_read_data to find out the orientation of the image:

$exif = exif_read_data('image.jpg');

if (isset($exif['Orientation']))
{
  switch ($exif['Orientation'])
  {
    case 3:
      // Need to rotate 180 deg
      break;

    case 6:
      // Need to rotate 90 deg clockwise
      break;

    case 8:
      // Need to rotate 90 deg counter clockwise
      break;
  }
}

You'll find an explanation of the orientation codes here: http://www.impulseadventure.com/photo/exif-orientation.html

Thomas Sahlin
  • 796
  • 1
  • 4
  • 4
  • 17
    Not sure why the bounty answer was selected; this seems to be a question related to how to manipulate an image after it's been uploaded via iOS to a PHP script and then displayed. I've encountered this, and this seems to be the best answer. The above answer gives code in Objective C for iOS. – razzed Dec 17 '14 at 22:37
  • 1
    This script seems more usefool certainly. No matter where you upload a no vertical photo from an iphone (you can upload it from your laptop), the process of auto rotate have to be in the end point : in the website, or the API... where you can do many other treatment on your picture (resizing, duplicating...). Sorry for my ugly english – Benji_X80 Sep 03 '15 at 08:48
18

The image is rotating because you are saving the image in JPEG, if you save your image in PNG then the orientation will not change. here is the code to fix orientation issue.

- (UIImage *)fixrotation:(UIImage *)image{   

    if (image.imageOrientation == UIImageOrientationUp) return image;
    CGAffineTransform transform = CGAffineTransformIdentity;

    switch (image.imageOrientation) {
        case UIImageOrientationDown:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.width, image.size.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;

        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.width, 0);
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;

        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, image.size.height);
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;
        case UIImageOrientationUp:
        case UIImageOrientationUpMirrored:
            break;
    }

    switch (image.imageOrientation) {
        case UIImageOrientationUpMirrored:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.width, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;

        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.height, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
        case UIImageOrientationUp:
        case UIImageOrientationDown:
        case UIImageOrientationLeft:
        case UIImageOrientationRight:
            break;
    }

    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.
    CGContextRef ctx = CGBitmapContextCreate(NULL, image.size.width, image.size.height,
                                             CGImageGetBitsPerComponent(image.CGImage), 0,
                                             CGImageGetColorSpace(image.CGImage),
                                             CGImageGetBitmapInfo(image.CGImage));
    CGContextConcatCTM(ctx, transform);
    switch (image.imageOrientation) {
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            // Grr...
            CGContextDrawImage(ctx, CGRectMake(0,0,image.size.height,image.size.width), image.CGImage);
            break;

        default:
            CGContextDrawImage(ctx, CGRectMake(0,0,image.size.width,image.size.height), image.CGImage);
            break;
    }

    // And now we just create a new UIImage from the drawing context
    CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
    UIImage *img = [UIImage imageWithCGImage:cgimg];
    CGContextRelease(ctx);
    CGImageRelease(cgimg);
    return img;
}
Meet Doshi
  • 4,241
  • 10
  • 40
  • 81
Bhupesh
  • 2,310
  • 13
  • 33
  • 1
    how do I run this code with the image? Is this like a function? – John Doe Mar 22 '14 at 20:34
  • 1
    You need to call this function and it will return you the rotated image. – Bhupesh Mar 24 '14 at 09:17
  • how can I call it? I assume it is different than `[self fixrotation];` or something. – John Doe Mar 24 '14 at 16:47
  • UIImage *imageNew = [self fixrotation:yourOldImage]; this way it call's – Bhupesh Mar 25 '14 at 05:27
  • Thanks for your help, I keep getting this error and it crashes when I call the function `*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSConcreteMutableData imageOrientation]: unrecognized selector sent to instance 0x15f1d7a0'` – John Doe Mar 26 '14 at 03:09
  • NSData *image2 = UIImageJPEGRepresentation([info objectForKey:UIImagePickerControllerOriginalImage], 1.0); UIImage* imageSelected = [info valueForKey:@"UIImagePickerControllerOriginalImage"]; UIImage *imageNew = [self fixrotation:image2]; // you are passing image2 which is NSData, here you need to pass UIImage. Use this way UIImage *imageNew = [self fixrotation:imageSelected]; – Bhupesh Mar 27 '14 at 04:57
9

I have created a function to correct archived images and you can use this with small modification for the on air correction.

gist link of the function

<?php
/*
Correct image orientation v1.0

Author: Mathuvathanan Mounasamy

Licensed under the MIT license

This function correct all the images' orientation in a given path or directory.

Run:    php -r "require 'correctImageOrientation.php'; correctImageOrientation('test/');"
        or
        php -r "require 'correctImageOrientation.php'; correctImageOrientation('test/test1');"
        or
        php -r "require 'correctImageOrientation.php'; correctImageOrientation('test');"
*/
function correctImageOrientation($directory) {
    $scanned_directory = array_diff(scandir($directory), array('..', '.'));
    echo "<pre>";
    print_r("scanned directory: \r\n");
    print_r($scanned_directory);
    echo "</pre>\r\n";
    foreach ($scanned_directory as &$file) {

        if (is_dir($directory."/".$file)) {
            correctImageOrientation($directory."/".$file);
        } else {                                    
            $filen = explode(".", $file);
            $ext = end($filen);
            try {

                $exif = @exif_read_data($directory."/".$file);

                $orientation = $exif['Orientation'];

                if (isset($orientation) && $orientation != 1){
                    switch ($orientation) {
                        case 3:
                        $deg = 180;
                        break;
                        case 6:
                        $deg = 270;
                        break;
                        case 8:
                        $deg = 90;
                        break;
                    }

                    if ($deg) {

                        // If png
                        if ($ext == "png") {
                            $img_new = imagecreatefrompng($directory."/".$file);
                            $img_new = imagerotate($img_new, $deg, 0);

                            // Save rotated image
                            imagepng($img_new,$directory.$file);
                        }else {
                            $img_new = imagecreatefromjpeg($directory."/".$file);
                            $img_new = imagerotate($img_new, $deg, 0);

                            // Save rotated image
                            imagejpeg($img_new,$directory."/".$file,80);
                        }
                    }
                    echo "<pre>";
                    print_r("image changed: \r\n");
                    print_r($directory."/".$file);
                    echo "</pre>\r\n";
                }

            } catch (Exception $e) {
                echo "error:";
                echo $e;
                echo "error";
            }
        }
    }
    unset($file);
}

?>
BenMorel
  • 34,448
  • 50
  • 182
  • 322
Mathuvathanan
  • 121
  • 1
  • 8
5

you can add below script after upload image in folder

 $filename = "/files/1.jpg"; /*ADD YOUR FILENAME WITH PATH*/
 $exif = exif_read_data($filename);
 $ort = $exif['Orientation']; /*STORES ORIENTATION FROM IMAGE */
 $ort1 = $ort;
 $exif = exif_read_data($filename, 0, true);
    if (!empty($ort1))
     {
       $image = imagecreatefromjpeg($filename);
       $ort = $ort1;
          switch ($ort) {
                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); /*IF FOUND ORIENTATION THEN ROTATE IMAGE IN PERFECT DIMENSION*/

this script works after image will uploaded in folder, so you can add this script after upload file in folder

Ketan Chaudhari
  • 556
  • 6
  • 15
4

It doesn't quite answer your question but I always use this script to fix the orientation and scale to a sensible size pre-upload. This way you save hte app user some bandwidth and don't have anything to do server side.

- (UIImage *)scaleAndRotateImage:(UIImage *)image {
    int kMaxResolution = 1024; // Or whatever

    CGImageRef imgRef = image.CGImage;

    CGFloat width = CGImageGetWidth(imgRef);
    CGFloat height = CGImageGetHeight(imgRef);


    CGAffineTransform transform = CGAffineTransformIdentity;
    CGRect bounds = CGRectMake(0, 0, width, height);
    if (width > kMaxResolution || height > kMaxResolution) {
        CGFloat ratio = width/height;
        if (ratio > 1) {
            bounds.size.width = kMaxResolution;
            bounds.size.height = roundf(bounds.size.width / ratio);
        }
        else {
            bounds.size.height = kMaxResolution;
            bounds.size.width = roundf(bounds.size.height * ratio);
        }
    }

    CGFloat scaleRatio = bounds.size.width / width;
    CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
    CGFloat boundHeight;
    UIImageOrientation orient = image.imageOrientation;
    switch(orient) {

        case UIImageOrientationUp: //EXIF = 1
            transform = CGAffineTransformIdentity;
            break;

        case UIImageOrientationUpMirrored: //EXIF = 2
            transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            break;

        case UIImageOrientationDown: //EXIF = 3
            transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;

        case UIImageOrientationDownMirrored: //EXIF = 4
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
            transform = CGAffineTransformScale(transform, 1.0, -1.0);
            break;

        case UIImageOrientationLeftMirrored: //EXIF = 5
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;

        case UIImageOrientationLeft: //EXIF = 6
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;

        case UIImageOrientationRightMirrored: //EXIF = 7
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeScale(-1.0, 1.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;

        case UIImageOrientationRight: //EXIF = 8
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;

        default:
            [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];

    }

    UIGraphicsBeginImageContext(bounds.size);

    CGContextRef context = UIGraphicsGetCurrentContext();

    if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
        CGContextScaleCTM(context, -scaleRatio, scaleRatio);
        CGContextTranslateCTM(context, -height, 0);
    }
    else {
        CGContextScaleCTM(context, scaleRatio, -scaleRatio);
       CGContextTranslateCTM(context, 0, -height);
    }

    CGContextConcatCTM(context, transform);

    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy;
}
Martin
  • 1,135
  • 1
  • 8
  • 19
2

Using the GD Library we can manipulate images in PHP. This script uses the imagerotate () function to rotate a photo. In our case we are rotating it 90 degrees but this can be changed in the script.

 <?php 
 // The file you are rotating
 $image = 'myfile.jpg';

 //How many degrees you wish to rotate
 $degrees = 90;

 // This sets the image type to .jpg but can be changed to png or gif
 header('Content-type: image/jpeg') ;

 // Create the canvas
 $source = imagecreatefromjpeg($image) ;

 // Rotates the image
 $rotate = imagerotate($source, $degrees, 0) ;

 // Outputs a jpg image, you could change this to gif or png if needed
 imagejpeg($rotate) ;
 ?> 

The most important part of this script, the rotating, is done with the imagerotate() function. The parameters of this function are:

imagerotate (The_image, degrees_to_rotate, background_color, Optional_ignore_transparency)

If the optional ignore transparency is blank or 0, then the transparency is preserved.

array getimagesize ( string $filename [, array &$imageinfo ] )

The getimagesize() function will determine the size of any given image file and return the dimensions along with the file type and a height/width text string to be used inside a normal HTML IMG tag and the correspondant HTTP content type.

You should use this to check how the phone image is oriented so you can know when to call imagerotate().

You can also save the image with imagejpeg. http://www.php.net/manual/en/function.imagejpeg.php

// Save the image as 'path/to/myfile.jpg'
imagejpeg($image, 'path/to/myfile.jpg');

// Free up memory
imagedestroy($image);
jemiloii
  • 24,594
  • 7
  • 54
  • 83
1
// File and rotation
$filename = 'test.jpg';
$degrees = 180;

// Content type
header('Content-type: image/jpeg');

// Load
$source = imagecreatefromjpeg($filename);

// Rotate
$rotate = imagerotate($source, $degrees, 0);

// Output
imagejpeg($rotate);

check this link :
http://www.php.net/manual/en/function.imagerotate.php
akr
  • 739
  • 4
  • 15
0

if you are using ImageMagick there is a a very simple fix for it, just add -auto-orient to your command.

convert -auto-orient -quality 90 -resize 1200x800 $f-new
JLGarcia
  • 336
  • 2
  • 5