简体   繁体   English

在iPad上以人像模式启动图像选择器

[英]Launching Image Picker in Portrait Mode on iPad

I am using the following code to launch the image picker in my iPad app (which uses Cocos2D) : 我正在使用以下代码在我的iPad应用程序(使用Cocos2D)中启动图像选择器:

UIImagePickerController * imagePickerController = [[UIImagePickerController alloc] init];

if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { 

    imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
    imagePickerController.showsCameraControls = YES;
    imagePickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
    imagePickerController.delegate = self;
    imagePickerController.cameraDevice = UIImagePickerControllerCameraDeviceFront;
    [self.view addSubview:imagePickerController.view];
    [self presentModalViewController:imagePickerController animated:YES];

}

I want it to launch in the portrait mode all the time, but it always launches like this : 我希望它始终以纵向模式启动,但是它总是这样启动:

在此处输入图片说明

The image appears in portrait and the image picker UI is in landscape mode. 图像以纵向显示,图像选择器UI处于横向模式。 But When I capture the image, it get's rotated 90 degrees clockwise. 但是,当我捕获图像时,它会顺时针旋转90度。

I want the image picker UI and the taken image, both to be in portrait mode. 我希望图像选择器UI和拍摄的图像都处于纵向模式。 How can I fix this ? 我怎样才能解决这个问题 ?

There are three things you need to do: 您需要做三件事:

  1. Tell the viewController that is presenting the imagePicker to only support portrait orientation. 告诉viewController展示imagePicker仅支持纵向。
  2. Tell the imagePicker to not to rotate the live camera feed. 告诉imagePicker不要旋转实时摄影机的提要。
  3. Un-rotate captured images. 取消旋转捕获的图像。

The imagePicker receives notifications of device orientation changes directly. imagePicker直接接收设备方向更改的通知。 To keep the live camera feed from rotating with the device you can stop it from receiving these notifications by telling UIDevice to endGenerating the orientation notifications after the imagePicker is presented via: 为了防止实时摄像头馈送随设备一起旋转,您可以通过告诉UIDevice在显示imagePicker之后通过显示以下内容来停止定向,以使其停止接收这些通知:

while ([currentDevice isGeneratingDeviceOrientationNotifications])
        [currentDevice endGeneratingDeviceOrientationNotifications];

The reason why you put it in a loop is because the imagePicker beginsGeneratingDeviceOrientationNotifications, and then ends its when it is dismissed, bringing the notification count on a normal device from 1 to 2 back to 1. 之所以将其置于循环中,是因为imagePicker开始GeneratingDeviceOrientationNotifications,然后在被关闭时结束,从而将正常设备上的通知计数从1减少到2,使其回到1。

After the imagePicker is dismissed, you can call: 在关闭imagePicker之后,您可以调用:

while (![currentDevice isGeneratingDeviceOrientationNotifications])
        [currentDevice beginGeneratingDeviceOrientationNotifications];

so that your ViewControllers can continue to receive orientation change notifications. 这样您的ViewController可以继续接收方向更改通知。

Unfortunately, even after turning this off, the images will still be saved with the correct imageOrientation of the camera on capture, so before you save the image or do anything with it, you'll have to remove the applied orientation transformation by manually countering it: 不幸的是,即使将其关闭,图像仍会以正确的图像方向保存在相机上,因此在保存图像或对其进行任何操作之前,您必须通过手动抵消图像来移除应用的方向变换:

-(UIImage *)turnMeAround:(UIImage *)image{
    CGAffineTransform transform = CGAffineTransformIdentity;
    CGFloat scale = [[UIScreen mainScreen] scale]; //retina
    CGSize size = CGSizeMake(image.size.width*scale,image.size.height*scale);
    switch (image.imageOrientation) {
        case UIImageOrientationUp:
            return image;
        case UIImageOrientationDown:
            size = CGSizeMake(size.height,size.width);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;
        case UIImageOrientationLeft:
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;
        case UIImageOrientationRight:
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;
    }
    CGContextRef context = CGBitmapContextCreate(NULL, size.width, size.height, CGImageGetBitsPerComponent(image.CGImage), 0, CGImageGetColorSpace(image.CGImage), CGImageGetBitmapInfo(image.CGImage));
    CGContextConcatCTM(context, transform);
    CGContextDrawImage(context, CGRectMake(0,0,size.width,size.height), image.CGImage);
    CGImageRef ref = CGBitmapContextCreateImage(context);
    UIImage *upsideRight = [UIImage imageWithCGImage:ref];
    CGContextRelease(context);
    CGImageRelease(ref);
    return upsideRight;
}

Thanks so much guys for all the help, but what worked for me is as follows : 非常感谢你们提供的所有帮助,但对我有用的是:

So I found out that it was Xcode's Cocos2D template which was the culprit. 因此,我发现罪魁祸首是Xcode的Cocos2D模板。 It had generated the following code in the RootViewController : 它在RootViewController中生成了以下代码:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

//
// There are 2 ways to support auto-rotation:
//  - The OpenGL / cocos2d way
//     - Faster, but doesn't rotate the UIKit objects
//  - The ViewController way
//    - A bit slower, but the UiKit objects are placed in the right place
//

#if GAME_AUTOROTATION==kGameAutorotationNone
//
// EAGLView won't be autorotated.
// Since this method should return YES in at least 1 orientation, 
// we return YES only in the Portrait orientation
//
return ( interfaceOrientation == UIInterfaceOrientationPortrait );

#elif GAME_AUTOROTATION==kGameAutorotationCCDirector
//
// EAGLView will be rotated by cocos2d
//
// Sample: Autorotate only in landscape mode
//
if( interfaceOrientation == UIInterfaceOrientationLandscapeLeft ) {
    [[CCDirector sharedDirector] setDeviceOrientation: kCCDeviceOrientationLandscapeRight];
} else if( interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
    [[CCDirector sharedDirector] setDeviceOrientation: kCCDeviceOrientationLandscapeLeft];
}

// Since this method should return YES in at least 1 orientation, 
// we return YES only in the Portrait orientation
return ( interfaceOrientation == UIInterfaceOrientationPortrait );

#elif GAME_AUTOROTATION == kGameAutorotationUIViewController
//
// EAGLView will be rotated by the UIViewController
//
// Sample: Autorotate only in landscpe mode
//
// return YES for the supported orientations

return ( UIInterfaceOrientationIsLandscape( interfaceOrientation ) );

#else
#error Unknown value in GAME_AUTOROTATION

#endif // GAME_AUTOROTATION


// Shold not happen
return NO;
}

In the above code I changed this : 在上面的代码中,我对此进行了更改:

return ( UIInterfaceOrientationIsLandscape( interfaceOrientation ) );

To this : 对此:

return ( UIInterfaceOrientationIsPortrait( interfaceOrientation ) );

And that fixed it. 这样就解决了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM