2014-09-19 114 views
38

我有一个非常简单的应用程序的UIImagePickerController相机视图: - 所有方位允许只有一个屏幕 上的按钮 - 按钮显示UIImagePickerController(拍照) - 建立在Xcode 5和SDK 7在iOS 8奇怪的旋转(图片)

iOS 8的,所述UIImagePickerController的相机出现正确我是否在横向或纵向,但是当我旋转设备,我得到旋转90度的摄像机视图,这里有一个例子:

  1. 我有我的肖像应用
  2. 我推,显示我的按钮UIImagePickerController
  3. 我在相机视图和我去到风景模式,这里是我得到:

视图在风景中,但相机旋转90度

是否有人已经有这个问题?

PS:如果我拍张照片(再次景观),照片是正确服用,现在正确显示:


编辑

的错误似乎在运行iOS 8.1的iPad上修复,但没有任何内容与iOS 8.1中的错误相关发布说明:https://developer.apple.com/library/content/releasenotes/General/RN-iOSSDK-8.1/

感谢所有为早期版本的iOS 8提出的修补程序!

+0

嗨凯文....你是在景观mode.The排序,我现在所面临的问题的启动你的相机是我的iPhone应用程序是在人像模式,并在一个视图中我有一个摄像头按钮和我希望只在横向模式下启动相机。我使用Google搜索,但没有运气。所以我需要一些想法或一些参考,以便我可以将其应用到我的项目中。预先感谢:) – 2015-03-05 05:04:26

+0

@wimcNilesh:此问题不是关于启动照相机处于特殊的方向,但是相机屏幕上的方向改变问题。 – 2015-03-05 12:02:37

+0

没问题。谢谢。还有一件事要问“我只能在我的iPhone应用程序中以横向模式启动相机,其中每个视图都处于肖像模式?” – 2015-03-05 12:12:08

回答

18

我认为这是一个iOS 8的错误。例如,如果您打开通讯录应用程序并单击编辑/添加照片/拍照,则标准iOS应用程序会发生同样的问题!像我一样将问题发布到Apple支持。

+0

感谢您的帮助!我会立即将这个问题发布给苹果公司。 – 2014-09-22 07:53:08

+0

可能值得指出的是它不影响iPhone 6 Plus,假设6也是,似乎只影响我的ipad Air, – Woodmister1 2014-09-22 09:39:49

+4

它不影响我的iPhone 5s,只有我的iPad mini。我相信iPad中的Bug – hitme 2014-09-22 09:44:40

4

我相信这是一个iOS 8的Bug,因为hitme提到。我提起了苹果票的问候联系人应用程序的例子,用它制成的开放式雷达副本这里提交BUG的http://openradar.appspot.com/18416803

详细
摘要: 在联系人应用程序,如果用户旋转iPad设备所以其横向定位,然后将设备平放在桌面上或与相机取景器的地面保持水平,并将两侧的黑条旋转90度。然后用户可以拍下显示正确旋转的照片。这是一种糟糕的用户体验,并且导致用户在拍摄图像时遇到很多困难。

重现步骤:
1.打开联系人应用程序
2.将iPad旋转为横向模式
3.将iPad来平放在桌子
4.添加新联系人
5。添加照片>拍照 6.拿起iPad

预期结果:
图像捕捉取景器在全屏幕中以横向模式显示。

实际结果:
图像捕捉取景器旋转90度而不是全屏。

受影响的版本: iOS 8.0,8.0.2,& 8.1。

+0

Apple将我报告的问题关闭为“重复17075455(打开)”。 – 2014-09-30 17:38:19

+0

从iOS 9 Beta 1开始解决此问题。它在联系人应用程序中不再是问题。 – 2015-06-30 02:09:20

0

我得到了同样的问题。我对双方的iOS 7.1.2和iOS 8.测试到目前为止,它只是发生在iOS 8. iPad设备,所以我暂时通过下面的代码解决这个问题:

// In my app, I subclass UIImagePickerController and code my own control buttons 
// showsCameraControls = NO; 
- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
    [[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIInterfaceOrientationPortrait] forKey:@"orientation"]; 
} 

不推荐,因为它会搞砸呈现视图控制器的方向。

Apple还有答复吗?

+0

苹果还没有回复... – 2014-09-26 09:45:49

+1

没有回复苹果,这个问题还没有在8.0.2更新中解决难过 – hitme 2014-09-30 20:50:18

+0

不是在iOS 8.1测试版:( – Ray 2014-10-01 02:41:48

0

不能等待苹果来解决问题...

- (void)viewWillAppear:(BOOL)animated 
{ 
    ... 
    if (iPad & iOS 8) 
    { 
    switch (device_orientation) 
    { 
     case UIDeviceOrientationPortraitUpsideDown: self.cameraViewTransform = CGAffineTransformMakeRotation(DEGREES_RADIANS(180)); break; 
     case UIDeviceOrientationLandscapeLeft: self.cameraViewTransform = CGAffineTransformMakeRotation(DEGREES_RADIANS(90)); break; 
     case UIDeviceOrientationLandscapeRight: self.cameraViewTransform = CGAffineTransformMakeRotation(DEGREES_RADIANS(-90)); break; 
     default: break; 
    } 
    } 
} 
0

我知道这是一个iOS的错误,但我已经实现了一个临时的解决办法:

就认为呈现的图像拾取,添加此代码,如果你没有得到任何方向改变的事件(或使用didRotateFromInterfaceOrientation otherwhise):

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    // .... 

    if ([[UIDevice currentDevice].systemVersion floatValue] >=8) { 
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRotate:) name:UIDeviceOrientationDidChangeNotification object:nil]; 
    } 

} 
现在

上旋转轻易否定,表示你的imagepicker:

- (void)didRotate:(NSNotification *)notification 
{ 
    if (self.presentedViewController && self.presentedViewController==self.imagePickerController) { 
     [self dismissViewControllerAnimated:NO completion:^{ 
      [self presentViewController:self.imagePickerController animated:NO completion:nil]; 
     }]; 
    } 
} 

作品有点粗糙,但这是UIImagePickerController最好的解决方案我已经找到

0

这里有一个修复我发现通过添加此类别:

@implementation UIImagePickerController (Rotation) 

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator 
{ 
    [self viewWillAppear:NO]; 
    [self viewDidAppear:NO]; 
} 

- (void)viewWillDisappear:(BOOL)animated 
{ 
    [[UIApplication sharedApplication] setStatusBarHidden:NO]; 
} 

@end 

我意识到这一点hacky直接调用UIViewController生命周期方法,但这是我找到的唯一解决方案。希望苹果很快就能解决这个问题!

+0

不是使用当前的XCode版本6.2 – Pion 2015-03-26 19:41:37

3

该问题已在iOS 8.1中修复 使用联系人应用测试。工作正常。

但另一个问题,我发现,

  1. 进入电话簿应用
  2. 让您的设备,如iPad相机朝向地面。
  3. 添加联系人 - >拍摄照片

测试其2〜3次与面朝上的方向,相机视图将开始旋转奇怪再次,你可以在上面上传的照片看。

+0

事实上,我编辑了我的问题让大家知道,我没有设法重现你的问题,你保持iPad始终面向地面在肖像模式下有这个问题吗? – 2014-10-22 12:13:51

+0

我能够重现此问题与8.1 - 1)握住iPad,使联系人应用程序处于肖像模式2)打开相机3)将iPad平放在桌子上4)拿起iPad并旋转到横向5)将iPad放回桌子上6)取消相机7)再次打开相机 - 您必须将iPad平放并拾起它并做一些愚蠢的事情,但它仍然会发生 – Chris 2014-11-06 18:35:40

+0

@KevinHirsch是的,让iPad面对地面。并尝试旋转它在景观,如克里斯说,做一些愚蠢的事情。尝试关闭并打开相机多次。这个问题将被复制 – Mann 2014-11-10 05:33:53

1

我有同样的问题,回到基础和创建一个实际工作的新项目..我追踪到;

-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator 
{ 
    // Had forgot to call the following.. 
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; 
} 

希望它有帮助。

1

正如@hitme说,它是在iOS 8的一个bug,但你可以展示它之前解决该问题,通过设置-[UIImagePickerController cameraViewTransform]

CGFloat angle; 
switch (interfaceOrientation) 
{ 
    case UIInterfaceOrientationLandscapeLeft: 
     angle = M_PI_2; 
     break; 

    case UIInterfaceOrientationLandscapeRight: 
     angle = -M_PI_2; 
     break; 

    case UIInterfaceOrientationPortraitUpsideDown: 
     angle = M_PI; 
     break; 

    default: 
     angle = 0; 
     break; 
} 
imagePicker.cameraViewTransform = CGAffineTransformMakeRotation([UIApplication sharedApplication].statusBarOrientation); 
+0

有趣的...设置cameraViewTransform如你的代码片段所示实际上对我来说有点作品 - 它似乎在演示相机问题后解决旋转设备问题。但它将所有视图旋转至45° - 向右转动,向左转动风景。此外,如果我注释掉开关,它的行为完全相同。然后我注意到CGFloat角度根本不在你的代码片段中使用。我们如何使用它?谢谢! – 2015-03-18 15:26:17

5

我发现了一个简单而准确的补丁来解决这个问题。呈现的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"]; 
       } 
      } 
} 

你也需要继承的UIImagePickerController并覆盖以下,如下的方法来解决它更好。

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

使用上面的代码后,它会针对横向方向运作良好,方向不会改变,以UIDeviceOrientationFaceUp模式。

+0

但是,OP的问题是关于设备旋转后出现的方向问题?发生问题时已经显示UIImagePickerController。 – 2015-03-18 14:50:21

+1

shouldAutorotate => NO解决了我的问题。 – Robert 2015-04-08 12:36:04

14

我发现了另一个非常好的解决方案,目前我正在使用这个问题。在使用UIImagePickerController捕获图像后,您只需将图像作为方法传递给此方法即可。它适用于所有版本的iOS以及Camera的纵向和横向方向。它使用UIImageOrientaiton检查图像的EXIF属性,并调整方向值,它会对图像进行缩放,以便您可以获得与摄像机视图方向相同方向的相同返回图像。

这里我保留了3000的最大分辨率,这样在使用视网膜设备时图像质量不会变坏,但您可以按照您的要求更改其分辨率。

- (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; 
} 
+0

它的工作完美...! Thanx – sohil 2015-08-07 10:45:34

+0

这应该是被接受的答案 – bader 2016-02-25 12:16:25

+0

谢谢bader和sohil – sajgan2015 2016-02-26 12:09:05

0

这是我用来解决我的应用程序,正在转OpenCV的摄像头变成景观如果摄像机开始在仰卧位置在桌子上的设备的代码。相机需要强制进入肖像模式才能使应用程序正常工作。

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

-(void)viewDidAppear:(BOOL)animated 
{ 

    [super viewDidAppear: animated]; 

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