0

The title to this question should be rather clear. The code below performs a cropping operation and then displays the new cropped photo in an Image View. The problem is that the image, once cropped, is displayed with a different orientation than the original source image. Why is that? And what should I do about it?

-(void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[self.popoverController dismissPopoverAnimated:true];

NSString *mediaType = [info
                       objectForKey:UIImagePickerControllerMediaType];
[self dismissModalViewControllerAnimated:YES];
if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
    UIImage *image = [info
                      objectForKey:UIImagePickerControllerOriginalImage];


    CGRect rect = CGRectMake(0, ((image.size.height - image.size.width) / 2), image.size.width, image.size.width);


    CGImageRef subImageRef = CGImageCreateWithImageInRect(image.CGImage, rect);
    CGRect smallBounds = CGRectMake(rect.origin.x, rect.origin.y, CGImageGetWidth(subImageRef), CGImageGetHeight(subImageRef));

    UIGraphicsBeginImageContext(smallBounds.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextDrawImage(context, smallBounds, subImageRef);
    croppedImage = [UIImage imageWithCGImage:subImageRef];
    UIGraphicsEndImageContext();

    imageView.image = croppedImage;

*EDIT

Based on the comments suggesting that root cause of the issue is the removal of the EXIF tag I attempted to correct the orientation with the following code. This still doesn't fix the problem but I think it is a step in the right direction. Perhaps it will help someone to propose a new answer to the question.

if (image.imageOrientation == UIImageOrientationLeft) {
        NSLog(@"left");
        CGContextRotateCTM (context, radians(90));

    } else if (image.imageOrientation == UIImageOrientationRight) {
        NSLog(@"right");
        CGContextRotateCTM (context, radians(-90));

    } else if (image.imageOrientation == UIImageOrientationUp) {
        NSLog(@"up");
        // NOTHING
    } else if (image.imageOrientation == UIImageOrientationDown) {
        NSLog(@"down");
        CGContextRotateCTM (context, radians(-180.));
    }

See https://stackoverflow.com/a/5184134/549273

Community
  • 1
  • 1
hughesdan
  • 3,019
  • 12
  • 57
  • 80
  • I believe that Apple uses an EXIF tag to achieve the rotation of photos. Your new image is presumably missing that orientation information, and therefore is showing up incorrectly. – paulbailey Oct 08 '12 at 14:52
  • The image is coming from the iPhone camera so it should have an EXIF tag. – hughesdan Oct 08 '12 at 14:53
  • You're not taking the exif data into consideration when drawing it into the context. The image will always be in it's "raw" orientation. UIImage rotates it according to the exif. Except that you're drawing it raw into a new UIImage that doesn't have the exif data and so is "un-rotated". – Fogmeister Oct 08 '12 at 14:56
  • Is there anyway to preserve the EXIF data through the context? – hughesdan Oct 08 '12 at 14:58

2 Answers2

0

I think your best bet will be to get the orientation from the incoming image, and then create your new image with the appropriate rotation.

Grab the metadata from the info dictionary passed in:

NSDictionary *metadata = [info objectForKey:UIImagePickerControllerMediaMetadata];
NSNumber *orientation = [metadata objectForKey:@"Orientation"];

Then when you create your UIImage:

croppedImage = [UIImage imageWithCGImage:subImageRef 
                                   scale:1.0 
                             orientation:[orientation intValue]];

Hope that's a starting point for you, at least.

paulbailey
  • 5,328
  • 22
  • 35
0

What you should do is fix the image orientation before coping it, I had the same problem, I'm using swift so I had to change this answer:

iOS UIImagePickerController result image orientation after upload

But the code works just fine. Just remember that it returns an image and its not editing the image, I struggled to get it right just because of that simple mistake. And by the way you should not use UIImageOrientation but UIImageOrientation.rawValue, at least in swift.

I'll leave the code for swift here, HOPE IT HELPS:

extension UIImage {
public func fixOrientation() -> UIImage?{

    if self.imageOrientation.rawValue == UIImageOrientation.Up.rawValue {
        return self
    }

    var transform : CGAffineTransform = CGAffineTransformIdentity

    switch self.imageOrientation.rawValue {

    case UIImageOrientation.Down.rawValue:
            transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height)
            transform = CGAffineTransformRotate(transform, CGFloat(M_PI))
    case UIImageOrientation.DownMirrored.rawValue:
            transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height)
            transform = CGAffineTransformRotate(transform, CGFloat(M_PI))

    case UIImageOrientation.Left.rawValue:
            transform = CGAffineTransformTranslate(transform, self.size.width, 0)
            transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2))
    case UIImageOrientation.LeftMirrored.rawValue:
            transform = CGAffineTransformTranslate(transform, self.size.width, 0)
            transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2))

    case UIImageOrientation.Right.rawValue:
            print("working on right orientation")
            transform = CGAffineTransformTranslate(transform, 0, self.size.height)
            transform = CGAffineTransformRotate(transform, CGFloat(-M_PI_2))
    case UIImageOrientation.RightMirrored.rawValue:
            transform = CGAffineTransformTranslate(transform, 0, self.size.height)
            transform = CGAffineTransformRotate(transform, CGFloat(-M_PI_2))

    case UIImageOrientation.Up.rawValue: break
    case UIImageOrientation.UpMirrored.rawValue: break

    default: break
    }

    switch self.imageOrientation.rawValue {

    case UIImageOrientation.UpMirrored.rawValue:
            transform = CGAffineTransformTranslate(transform, self.size.width, 0)
            transform = CGAffineTransformScale(transform, -1, 1)
    case UIImageOrientation.DownMirrored.rawValue:
            transform = CGAffineTransformTranslate(transform, self.size.width, 0)
            transform = CGAffineTransformScale(transform, -1, 1)

    case UIImageOrientation.LeftMirrored.rawValue:
            transform = CGAffineTransformTranslate(transform, self.size.height, 0)
            transform = CGAffineTransformScale(transform, -1, 1)
    case UIImageOrientation.RightMirrored.rawValue:
            transform = CGAffineTransformTranslate(transform, self.size.height, 0)
            transform = CGAffineTransformScale(transform, -1, 1)

    case UIImageOrientation.Up.rawValue: break
    case UIImageOrientation.Down.rawValue: break
    case UIImageOrientation.Left.rawValue: break
    case UIImageOrientation.Right.rawValue: break

    default: break
    }

    let bitmapInfo = CGImageGetBitmapInfo(self.CGImage)

    let ctx = CGBitmapContextCreate(nil, Int(self.size.width), Int(self.size.height), CGImageGetBitsPerComponent(self.CGImage), 0, CGImageGetColorSpace(self.CGImage),
        bitmapInfo.rawValue)

    CGContextConcatCTM(ctx, transform)

    switch self.imageOrientation {

    case UIImageOrientation.Left:
            CGContextDrawImage(ctx, CGRectMake(0, 0, self.size.height, self.size.width), self.CGImage)
    case UIImageOrientation.LeftMirrored:
            CGContextDrawImage(ctx, CGRectMake(0, 0, self.size.height, self.size.width), self.CGImage)
    case UIImageOrientation.Right:
            CGContextDrawImage(ctx, CGRectMake(0, 0, self.size.height, self.size.width), self.CGImage)
    case UIImageOrientation.RightMirrored:
            CGContextDrawImage(ctx, CGRectMake(0, 0, self.size.height, self.size.width), self.CGImage)

    default:
        CGContextDrawImage(ctx, CGRectMake(0, 0, self.size.width, self.size.height), self.CGImage)

    }

    let cgimg = CGBitmapContextCreateImage(ctx)
    let image = UIImage(CGImage: cgimg!)

    return image

    }
}
Community
  • 1
  • 1
reojased
  • 709
  • 1
  • 7
  • 19