Подтвердить что ты не робот

Изображение камеры UIImagePickerController странно запущено на iOS 8 (картинки)

У меня очень простое приложение: - Все ориентации разрешены только с помощью кнопки на экране - Кнопка показывает UIImagePickerController (чтобы сделать снимок) - Создайте с Xcode 5 и SDK 7

В iOS 8 камера с изображением UIImagePickerController появляется правильно, независимо от того, нахожусь ли я в альбомной или портретной ориентации, но когда я поворачиваю устройство, я получил вид камеры, повернутый на 90 градусов, вот пример:

  • У меня есть приложение в портрете
  • Я нажимаю кнопку, которая показывает мне UIImagePickerController
  • Я нахожусь в режиме просмотра камеры, и я перехожу в альбомный режим, вот что я получаю:

Вид в ландшафте, но камера поворачивается на 90 градусов

У кого-то еще была эта проблема?

PS: И если я сделаю снимок (снова в пейзаже), фотография будет правильно сделана и теперь правильно отображена:


ИЗМЕНИТЬ

Исправлена ​​ошибка на моем iPad под управлением iOS 8.1, но ничего не было связано с этой ошибкой в ​​примечаниях к выпуску iOS 8.1: https://developer.apple.com/library/content/releasenotes/General/RN-iOSSDK-8.1/

Спасибо всем за предлагаемые исправления для более ранних версий iOS 8!

4b9b3361

Ответ 1

Я считаю, что это ошибка iOS 8. Например, если вы открываете приложение для контактов, а затем редактируете/добавляете фотографию/фотографируете, то такая же проблема возникает в стандартном приложении iOS! Опубликуйте вопрос для поддержки Apple так же, как и я.

Ответ 2

Я нашел еще одно очень хорошее решение для этой проблемы, которое я использую в настоящее время. Вам просто нужно передать изображение как инструмент для этого метода после захвата изображения с помощью UIImagePickerController. Он отлично работает для всех версий iOS, а также для портретной и альбомной ориентации камеры. Он проверяет свойство EXIF ​​изображения с использованием UIImageOrientaiton и соответствует значению ориентации, преобразует и масштабирует изображение, чтобы вы получили одинаковое обратное изображение с той же ориентацией, что и ориентация вашего изображения.

Здесь я сохранил максимальное разрешение 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;
}

Ответ 3

Я нашел простой и точный патч для решения этой проблемы. Добавьте следующий код перед представлением 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.

Ответ 4

Я считаю, что это iOS 8 Bug, как упоминалось в hitme. Я подал Apple Ticket в отношении примера приложения для контактов и сделал здесь открытую радарную копию http://openradar.appspot.com/18416803

Информация об отчете об ошибках
Резюме: В приложении "Контакты", если пользователь поворачивает iPad-устройство таким образом, что он имеет ориентацию в альбомной ориентации, а затем закладывает устройство на стол или удерживает его на одном уровне с землей, видоискатель камеры запускается с поворотом на 90 градусов с черными полосами по бокам. Затем пользователь может сделать фотографию, которая выглядит правильно повернутой. Это ужасный пользовательский интерфейс и приводит к тому, что пользователь с большим трудом захватывает изображение.

Шаги по воспроизведению:
1. Откройте приложение "Контакты"
2. Поверните iPad в альбомный режим
3. Положите iPad на плоскость на столе
4. Добавить новый контакт
5. Добавить фото > Take Photo 6. Поднимите iPad.

Ожидаемые результаты:
Image Capture Viewfinder Отображение в полноэкранном режиме в ландшафтном режиме.

Фактические результаты:
Image Capture Видоискатель поворачивается на 90 градусов и не является полноэкранным.

Поврежденные версии: iOS 8.0, 8.0.2 и 8.1.

Ответ 5

Проблема была исправлена ​​в iOS 8.1 Протестировано с помощью приложения "Контакты". отлично работает.

Но еще одна проблема, которую я нашел,

  • Перейти в приложение "Контакты"
  • Держите устройство, как камера ipad, лицом к земле.
  • Добавить контакт → Снять фото

Протестируйте его 2 раза с ориентацией FaceUp, просмотр камеры начнет чередоваться снова, как вы можете видеть на снимках, загруженных выше.

Ответ 6

У меня была такая же проблема и после того, как я вернулся к основам и создал новый проект, который действительно работал. Я отследил его до:

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

Надеюсь, что это поможет.

Ответ 7

Как сказал @hitme, это ошибка в iOS 8, но вы можете обойти проблему, установив -[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);

Ответ 8

У меня такая же проблема. Я тестировал как iOS 7.1.2, так и iOS 8. До сих пор это происходило только на iPad-устройстве с iOS 8. Поэтому я временно исправляю его, следуя коду:

// 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"];
}

Не рекомендуется, потому что это испортит ориентацию presentingViewController.

Есть ли еще ответы от Apple?

Ответ 9

Не могу дождаться, когда Apple исправит проблему...

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

Ответ 10

Я знаю, что это ошибка 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];
        }];
    }
}

работает немного грубо, но это лучшее решение, которое я нашел

Ответ 11

Вот исправление, которое я нашел, добавив эту категорию в UIImagePickerController:

@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 методы жизненного цикла напрямую, но это единственное решение, которое я нашел. Надеюсь, Apple скоро это исправит!

Ответ 12

Это код, который я использовал для исправления моего приложения, которое вращало камеру openCV в альбомной ориентации, если камера была запущена с устройства на столе в позиции Face Up. Чтобы приложение функционировало правильно, камера должна быть принудительно переведена в портретный режим.

- (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"];
            }
        }
}