iOS UIImagePickerController result image orientation after upload iOS UIImagePickerController result image orientation after upload ios ios

iOS UIImagePickerController result image orientation after upload


A UIImage has a property imageOrientation, which instructs the UIImageView and other UIImage consumers to rotate the raw image data. There's a good chance that this flag is being saved to the exif data in the uploaded jpeg image, but the program you use to view it is not honoring that flag.

To rotate the UIImage to display properly when uploaded, you can use a category like this:

UIImage+fixOrientation.h

@interface UIImage (fixOrientation)- (UIImage *)fixOrientation;@end

UIImage+fixOrientation.m

@implementation UIImage (fixOrientation)- (UIImage *)fixOrientation {    // No-op if the orientation is already correct    if (self.imageOrientation == UIImageOrientationUp) return self;    // We need to calculate the proper transformation to make the image upright.    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.    CGAffineTransform transform = CGAffineTransformIdentity;    switch (self.imageOrientation) {        case UIImageOrientationDown:        case UIImageOrientationDownMirrored:            transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height);            transform = CGAffineTransformRotate(transform, M_PI);            break;        case UIImageOrientationLeft:        case UIImageOrientationLeftMirrored:            transform = CGAffineTransformTranslate(transform, self.size.width, 0);            transform = CGAffineTransformRotate(transform, M_PI_2);            break;        case UIImageOrientationRight:        case UIImageOrientationRightMirrored:            transform = CGAffineTransformTranslate(transform, 0, self.size.height);            transform = CGAffineTransformRotate(transform, -M_PI_2);            break;        case UIImageOrientationUp:        case UIImageOrientationUpMirrored:            break;    }    switch (self.imageOrientation) {        case UIImageOrientationUpMirrored:        case UIImageOrientationDownMirrored:            transform = CGAffineTransformTranslate(transform, self.size.width, 0);            transform = CGAffineTransformScale(transform, -1, 1);            break;        case UIImageOrientationLeftMirrored:        case UIImageOrientationRightMirrored:            transform = CGAffineTransformTranslate(transform, self.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, self.size.width, self.size.height,                                             CGImageGetBitsPerComponent(self.CGImage), 0,                                             CGImageGetColorSpace(self.CGImage),                                             CGImageGetBitmapInfo(self.CGImage));    CGContextConcatCTM(ctx, transform);    switch (self.imageOrientation) {        case UIImageOrientationLeft:        case UIImageOrientationLeftMirrored:        case UIImageOrientationRight:        case UIImageOrientationRightMirrored:            // Grr...            CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage);            break;        default:            CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.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;}@end


I figured out a much simpler one:

- (UIImage *)normalizedImage {    if (self.imageOrientation == UIImageOrientationUp) return self;     UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);    [self drawInRect:(CGRect){0, 0, self.size}];    UIImage *normalizedImage = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();    return normalizedImage;}

BTW: @Anomie's code does not take scale into account, so will not work for 2x images.


Here is a Swift version of the answer by @an0:

func normalizedImage() -> UIImage {  if (self.imageOrientation == UIImageOrientation.Up) {       return self;  }  UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale);  let rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)  self.drawInRect(rect)  let normalizedImage : UIImage = UIGraphicsGetImageFromCurrentImageContext()  UIGraphicsEndImageContext();  return normalizedImage;}

Also in a more general function:

func fixOrientation(img:UIImage) -> UIImage {  if (img.imageOrientation == UIImageOrientation.Up) {       return img;  }  UIGraphicsBeginImageContextWithOptions(img.size, false, img.scale);  let rect = CGRect(x: 0, y: 0, width: img.size.width, height: img.size.height)  img.drawInRect(rect)  let normalizedImage : UIImage = UIGraphicsGetImageFromCurrentImageContext()  UIGraphicsEndImageContext();  return normalizedImage;}

Swift 3 version:

func fixOrientation(img: UIImage) -> UIImage {    if (img.imageOrientation == .up) {        return img    }    UIGraphicsBeginImageContextWithOptions(img.size, false, img.scale)    let rect = CGRect(x: 0, y: 0, width: img.size.width, height: img.size.height)    img.draw(in: rect)    let normalizedImage = UIGraphicsGetImageFromCurrentImageContext()!    UIGraphicsEndImageContext()    return normalizedImage}