Search code examples
iosuiimagepickercontrollerios7uipopovercontrolleruiinterfaceorientation

iPad iOS7 - UIImagePickerController in UIPopoverController has wrong preview image


I am using an UIImagePickerController within an UIPopoverController which is working perfectly with iOS6. With iOS 7 the "preview" image which is shown to capture the image is rotated, but if I take a picture it is saved correctly.

This is how I get my picker:

UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.mediaTypes = [NSArray arrayWithObjects:
                              (NSString *) kUTTypeImage,
                              nil];
imagePicker.allowsEditing = NO;

And add it to a popover controller:

self.imagePickerPopOver = [[UIPopoverController alloc] initWithContentViewController:imagePicker];
    [self.imagePickerPopOver presentPopoverFromRect:CGRectMake(aPosViewA.x, cameraButton_y, 100.0, 30.0) inView:self.detailViewController.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

Those are calculations for the button position at a UIScrollView to show the popover at the correct position:

presentPopoverFromRect:CGRectMake(aPosViewA.x, cameraButton_y, 100.0, 30.0)

I don't think that the problem lies there as I have tried out several combinations.

I have also tried to capture the image in fullscreen-mode, but the app is only allowed to use landscape mode. If the image is taken in portrait-mode and the modal view is dismissed, the app stays in portrait mode as well. I couldn't find a way to prevent the UIImagePickerController to switch to portrait mode or to force the app back to landscape mode if the modal view was dismissed.

UPDATE

I have taken the answer from here and came a step further.

I transform the view after creating the picker and before showing the popover :

switch ([UIApplication sharedApplication].statusBarOrientation) {
        case UIInterfaceOrientationLandscapeLeft:
            self.imagePicker.view.transform = CGAffineTransformMakeRotation(M_PI/2);
            break;
        case UIInterfaceOrientationLandscapeRight:
            self.imagePicker.view.transform = CGAffineTransformMakeRotation(-M_PI/2);
            break;
        default:
            break;
    }

which works as long as i don't turn around the iPad. For that I am registering for the orientation changed event:

[[NSNotificationCenter defaultCenter] addObserver:self  selector:@selector(orientationChanged:)  name:UIDeviceOrientationDidChangeNotification  object:nil];

and change the picker view:

- (void)orientationChanged:(NSNotification *)notification{

    if (self.imagePicker) {
        switch ([UIApplication sharedApplication].statusBarOrientation) {
            case UIInterfaceOrientationLandscapeLeft:
                self.imagePicker.view.transform = CGAffineTransformMakeRotation(M_PI/2);
                break;
            case UIInterfaceOrientationLandscapeRight:
                self.imagePicker.view.transform = CGAffineTransformMakeRotation(-M_PI/2);
                break;
            default:
                break;
        }
    }
}

REMAINING PROBLEM: As I wrote in the beginning, when the picture was taken, it was shown correctly to accept or dismiss it. This is now transformed as well. Somehow I need to know when the image is taken and transform it back.

AND, this is really a nasty hack and probably won't work with the next iOS Update. Has anybody an idea how to implement that in a cleaner way?

UPDATE 2

This was too nasty, I have found a cleaner solution which solves my problem but is not the answer to the initial question regarding an imagepicker in a popover controller, which is not recommended by Apple, but allowed.

I have subclassed now the UIImagePickerController like this:

@implementation QPImagePickerController

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
}

- (BOOL)shouldAutorotate {
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscape;
}

@end

and I am using the imagepicker in fullscreen instead in a popover. Tested so far in iOS7.


Solution

  • The UIImagePickerController has a property called cameraViewTransform. Applying a CGAffineTransform to this will transform the preview image but will not transform the captured image which will therefore be correctly captured. I have the same problem that you describe and I solved it (for iOS7) by creating my camera controller and placing it in a popover as follows:

    UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
    
    [imagePickerController setDelegate:self];
    
    imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
    
    CGFloat scaleFactor=1.3f;
    
    switch ([UIApplication sharedApplication].statusBarOrientation) {
    
            case UIInterfaceOrientationLandscapeLeft:
    
                imagePickerController.cameraViewTransform = CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI * 90 / 180.0), scaleFactor, scaleFactor);
    
                break;
    
            case UIInterfaceOrientationLandscapeRight:
    
                imagePickerController.cameraViewTransform = CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI * -90 / 180.0), scaleFactor, scaleFactor);
    
                break;
    
            case UIInterfaceOrientationPortraitUpsideDown:
    
                imagePickerController.cameraViewTransform = CGAffineTransformMakeRotation(M_PI * 180 / 180.0);
    
                break;
    
                default:
                    break;
            }
    
     __popoverController = [[UIPopoverController alloc] initWithContentViewController:imagePickerController];
    
    [__popoverController presentPopoverFromRect:presentationRect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
    

    I also scale the image when in Landscape so that it fills the viewfinder more than it otherwise would. To my mind this is all rather nasty, but I will hopefully be able to remove it once iOS7.1 arrives.