UIImagePickerController camera view rotating strangely on iOS 8 (pictures) UIImagePickerController camera view rotating strangely on iOS 8 (pictures) ios ios

UIImagePickerController camera view rotating strangely on iOS 8 (pictures)


I believe it is an iOS 8 bug. For example if you open your contacts app and click edit/add photo/take photo, the same issue occurs on a standard iOS app! Post the issue to Apple support just as I have.


I have found an another very good solution for this issue which i am using currently. You just need to pass the image as an arugument to this method after capturing image using UIImagePickerController. It works well for all version of iOS and also for both portrait and landscape orientations of Camera. It checks for EXIF property of image using UIImageOrientaiton and accordind to the value of orientation, it transforms & scales the image so you will get the same return image with same orientation as your camera view orientation.

Here i have kept maximum resolutions of 3000 so that the image quality doesn't get spoiled specially while you are using retina devices but you can change its resolution as per your requirement.

// Objective C code:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info;{     UIImage *imagePicked = [info valueForKey:UIImagePickerControllerOriginalImage];     imagePicked = [self scaleAndRotateImage:imagePicked];     [[self delegate] sendImage:imagePicked];     [self.imagePicker dismissViewControllerAnimated:YES completion:nil];    }- (UIImage *) scaleAndRotateImage: (UIImage *)image{    int kMaxResolution = 3000; // 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 = bounds.size.width / ratio;        }        else {            bounds.size.height = kMaxResolution;            bounds.size.width = 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;}

// Swift 4.0 Code:

func scaleAndRotateImage(image: UIImage, MaxResolution iIntMaxResolution: Int) -> UIImage {        let kMaxResolution = iIntMaxResolution        let imgRef = image.cgImage!        let width: CGFloat = CGFloat(imgRef.width)        let height: CGFloat = CGFloat(imgRef.height)        var transform = CGAffineTransform.identity        var bounds = CGRect.init(x: 0, y: 0, width: width, height: height)        if Int(width) > kMaxResolution || Int(height) > kMaxResolution {            let ratio: CGFloat = width / height            if ratio > 1 {                bounds.size.width = CGFloat(kMaxResolution)                bounds.size.height = bounds.size.width / ratio            }            else {                bounds.size.height = CGFloat(kMaxResolution)                bounds.size.width = bounds.size.height * ratio            }        }        let scaleRatio: CGFloat = bounds.size.width / width        let imageSize = CGSize.init(width: CGFloat(imgRef.width), height: CGFloat(imgRef.height))        var boundHeight: CGFloat        let orient = image.imageOrientation        // The output below is limited by 1 KB.        // Please Sign Up (Free!) to remove this limitation.        switch orient {        case .up:            //EXIF = 1            transform = CGAffineTransform.identity        case .upMirrored:            //EXIF = 2            transform = CGAffineTransform.init(translationX: imageSize.width, y: 0.0)            transform = transform.scaledBy(x: -1.0, y: 1.0)        case .down:            //EXIF = 3            transform = CGAffineTransform.init(translationX: imageSize.width, y: imageSize.height)            transform = transform.rotated(by: CGFloat(Double.pi / 2))        case .downMirrored:            //EXIF = 4            transform = CGAffineTransform.init(translationX: 0.0, y: imageSize.height)            transform = transform.scaledBy(x: 1.0, y: -1.0)        case .leftMirrored:            //EXIF = 5            boundHeight = bounds.size.height            bounds.size.height = bounds.size.width            bounds.size.width = boundHeight            transform = CGAffineTransform.init(translationX: imageSize.height, y: imageSize.width)            transform = transform.scaledBy(x: -1.0, y: 1.0)            transform = transform.rotated(by: CGFloat(Double.pi / 2) / 2.0)            break        default: print("Error in processing image")        }        UIGraphicsBeginImageContext(bounds.size)        let context = UIGraphicsGetCurrentContext()        if orient == .right || orient == .left {            context?.scaleBy(x: -scaleRatio, y: scaleRatio)            context?.translateBy(x: -height, y: 0)        }        else {            context?.scaleBy(x: scaleRatio, y: -scaleRatio)            context?.translateBy(x: 0, y: -height)        }        context?.concatenate(transform)        context?.draw(imgRef, in: CGRect.init(x: 0, y: 0, width: width, height: height))        let imageCopy = UIGraphicsGetImageFromCurrentImageContext()        UIGraphicsEndImageContext()        return imageCopy!    }


I found an easy and accurate patch to resolve this issue. Add following code before presenting UIImagePickerController:

if (iOS8_Device){            if([[UIDevice currentDevice]orientation] == UIDeviceOrientationFaceUp)            {                if([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeLeft)                {                    [[UIDevice currentDevice]setValue:[NSNumber numberWithInteger:UIDeviceOrientationLandscapeRight] forKey:@"orientation"];                }                else                {                    [[UIDevice currentDevice]setValue:[NSNumber numberWithInteger:UIDeviceOrientationLandscapeLeft] forKey:@"orientation"];                }            }}

Also you need to subclass UIImagePickerController and override following method as below to work it better.

- (BOOL)shouldAutorotate{    [super shouldAutorotate];    return NO;}

After using above code it will work for both landscape orientation well and the orientation will not be changed to UIDeviceOrientationFaceUp mode.