强制UIImagePickerController在iOS中以纵向方向/尺寸拍照

10

我的应用程序只允许横屏模式。我在项目属性中强制设置了此选项,包括目标>总结,并且在shouldAutorotateToInterfaceOrientation中仅允许竖屏模式。

问题是当我横向(横屏)持手机拍照时,照片将以横向方向拍摄,而界面仍处于竖屏模式。

这意味着在横屏模式下,我获得的图像宽度为3264 x 2448,而在竖屏模式下则为高度为2448 x 3264。

接下来,用户可以裁剪图像,但如果图像是在横屏模式下拍摄的,则会得到非常难看的拉伸图像。添加边框或将界面切换到横向模式都不是一个选项。

是否有一种方法可以强制UIImagePickerController在水平(横屏模式)持有手机时以竖向尺寸拍摄照片?

我使用以下设置初始化UIImagePickerController

    imagePicker =[[UIImagePickerController alloc] init];
    imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
    imagePicker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
    imagePicker.cameraDevice = UIImagePickerControllerCameraDeviceRear;
    imagePicker.showsCameraControls = NO;
    imagePicker.modalPresentationStyle = UIModalPresentationFullScreen;
    imagePicker.wantsFullScreenLayout = YES;
    imagePicker.cameraViewTransform = CGAffineTransformScale(imagePicker.cameraViewTransform,CAMERA_TRANSFORM, CAMERA_TRANSFORM);
    imagePicker.navigationBarHidden = YES;
    imagePicker.toolbarHidden = YES;
    [self presentModalViewController:imagePicker animated:NO];
    imagePicker.cameraOverlayView = self.cameraOverlay;
    imagePicker.cameraFlashMode = UIImagePickerControllerCameraFlashModeOff;

你好!我也有同样的问题。在回答中提供的选项中,哪一个解决了你的问题? - doxsi
@doxsi 在当时,stripExif 对我很有帮助。 - Dirk de Boer
1个回答

17

根据拍照时相机的朝向,UIImage会设置imageOrientation标志。这是一个只读标志,确定iOS在将图像放入视图时尝试显示的方向。

您可以在显示图像之前检查其方向,并相应地操作imageView。假设您有一个包含在同样大小的视图内的imageView...

- (void) imagePickerImage:(UIImage*)image
{
    if (image.imageOrientation == UIImageOrientationUp ) {
        self.imageView.bounds = CGRectMake
           (0, 0, self.view.bounds.size.height, self.view.bounds.size.width);
        self.imageView.transform = CGAffineTransformMakeRotation(M_PI/2);

    } else if (image.imageOrientation == UIImageOrientationDown) {
        self.imageView.bounds = CGRectMake
           (0, 0, self.view.bounds.size.height, self.view.bounds.size.width);
        self.imageView.transform = CGAffineTransformMakeRotation(-M_PI/2);
    }
    else {
        self.imageView.bounds = self.view.bounds;
        self.imageView.transform = CGAffineTransformIdentity;
    }
    self.imageView.image = image;
}

另一种选择可能是从图像副本中创建一个新图像:这应该会去掉方向信息。

更新
iPhone 照片的实际像素尺寸是横向的,不管拍摄时手机如何保持。只有方向 EXIF 标志设置不同。你无法更改 EXIF 标志,但可以通过将图像位图数据复制到新的位图图像来删除它。请参见我的答案 这里

以下是一种去除 EXIF 数据并添加肖像 EXIF 标志的方法。您将创建一个新的 UIImage 并在创建时设置 EXIF 标志。您可以使用此方法将横向图像标记为纵向(UIImageOrientationRight)。

- (UIImage*)stripExif:(UIImage*)image
{
    CGImageRef cgImage = image.CGImage;
    UIImage* result = [UIImage imageWithCGImage:cgImage scale:1 
                                    orientation:UIImageOrientationRight];
    return result;
}

更新2
将UIImage的imageOrientation属性称为EXIF标志是具有误导性的,原因如下:

(1) 图像元数据以字典样式结构存储,其中可以包含多个子字典,其中一个是EXIF。其他包括TIFF、IPTC和PNG等。顶层字典中还有一组通用标签。 方向(orientation)关键字不在EXIF部分中,而是在TIFF和IPTC子字典(如果存在)以及顶层关键字中找到。我们倾向于在涉及图像元数据时使用EXIF这一术语,但这会引起误解。

(2) 图像文件中的方向元数据使用的是一组不同于Apple在其UIImage.imageOrientation属性中使用的标志约定。因此,如果要正确显示图像,则必须注意读取此属性。显然,苹果公司使用图像文件的方向元数据来设置UIImage的属性,但进行了一些转换。

 Orientation 

 Apple/UIImage.imageOrientation     Jpeg/File kCGImagePropertyOrientation

    UIImageOrientationUp    = 0  =  Landscape left  = 1
    UIImageOrientationDown  = 1  =  Landscape right = 3
    UIImageOrientationLeft  = 2  =  Portrait  down  = 8
    UIImageOrientationRight = 3  =  Portrait  up    = 6

这里是一个页面展示了'exif'旋转标志。与Apple的UIImage文档(常量部分)进行比较。还可以查看Apple的CGImageProperties_Reference,特别是kCGImagePropertyOrientation

我已经将一个小项目加载到Github上,记录了各种UIImage元数据问题


谢谢您的回答。然而问题不在于如何显示照片,而是照片拍摄时的尺寸。例如,当我将手机横向放置时,分辨率为3264 x 2448,而纵向则为2448 x 3264。我会修改我的问题以更清晰地表达。但我认为强制相机按特定方向拍摄照片是不可能的。 - Dirk de Boer
1
@DirkdeBoer 原始像素尺寸始终为横向 3264 x 2448... 它是方向标志,指示 NSImage 显示的方向。 - foundry
@DirkdeBoer,摆脱EXIF方向标志的唯一方法是将照片的位图数据复制到一个新的位图图像中。也许这就是你想要的解决方案。 - foundry
实际上,您可以更改EXIF标志并以不同的方向保存图像。 [设置exif数据](https://dev59.com/HG435IYBdhLWcg3w7k6b)是开始这样做的好方法。 - Jonathan Cichon
非常好的答案! :) - sterling archer
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接