Заставьте UIImagePickerController сфотографировать в портретной ориентации / размерах iOS
Единственная разрешенная ориентация в моем приложении - альбомная. Я устанавливаю это в свойствах проекта в target > summery и разрешаю только портрет в 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;
1 ответ
Флаг imageOrientation устанавливается на UIImage в зависимости от того, в какую сторону держится камера во время съемки. Этот флаг доступен только для чтения и определяет ориентацию, с которой 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;
}
Другим вариантом может быть создание нового изображения из imageRep: это должно удалить информацию об ориентации.
Обновить
Размеры родного пикселя на фотографии 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
Неправильно ссылаться на свойство imageOrientation UIImage как флаг EXIF по двум причинам:
(1) метаданные изображения хранятся в структуре словарного стиля, в которой может быть несколько под-словарей, одним из которых является EXIF. Другие включают TIFF, IPTC, PNG, например. Существует также общий набор тегов в словаре верхнего уровня. Ключ ориентации НЕ находится в разделе EXIF, он находится в подкаталогах TIFF и IPTC (если имеется), а также в качестве ключа верхнего уровня. Мы склонны использовать термин EXIF при ссылке на метаданные изображения в целом, но это вводит в заблуждение.
(2) Метаданные для ориентации в файле изображения используют набор соглашений о флагах, отличающийся от тех, которые Apple использует в своем свойстве UIImage.imageOrientation. Поэтому вы должны позаботиться о том, чтобы прочитать это свойство, чтобы правильно отобразить изображение. Apple, очевидно, использует метаданные ориентации файла изображения, чтобы установить свойство 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