Изображение камеры 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!
Ответы
Ответ 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"];
}
}
}