iPhone - Зеркальное отображение изображения, сделанного с передней камеры

При использовании фронтальной камеры iPhone 4 для съемки сделанное изображение зеркально отображается по сравнению с тем, что вы видите на экране iPhone. Как я могу восстановить "экранный" вид UIImage (не UIImageView) и сохранить его в таком виде?

Я пытался :

UIImage* transformedImage = [UIImage imageWithCGImage:pickedImage.CGImage scale:1.0 orientation:UIImageOrientationLeftMirrored];
UIImageWriteToSavedPhotosAlbum (transformedImage, self, @selector(photoSaved:didFinishSavingWithError:contextInfo:), nil);

затем поместите его на экран. Он почти такой же, как на экране, но сохраненное изображение искажено.

Итак ... Как мне восстановить "экранный" вид UIImage (не UIImageView) и сохранить его в таком виде?

Я тоже пробовал так:

UIImage* pickedImage = [[info objectForKey:UIImagePickerControllerOriginalImage] retain];
UIImage* transformedImage;

CGSize imageSize = pickedImage.size;
UIGraphicsBeginImageContextWithOptions(imageSize, YES, 1.0);
GContextRef ctx = UIGraphicsGetCurrentContext();

CGContextRotateCTM(ctx, 3.14);  // rotate by 180°
CGContextScaleCTM(ctx, 1.0, -1.0); // flip vertical
CGContextDrawImage(ctx, CGRectMake(0.0, 0.0, imageSize.width, imageSize.height), pickedImage.CGImage);
transformedImage = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

Но это дает только черное изображение.


person Oliver    schedule 31.03.2011    source источник


Ответы (8)


Лучше всего перенести изображение в новый контекст.

CGSize imageSize = pickedImage.size;
UIGraphicsBeginImageContextWithOptions(imageSize, YES, 1.0);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(ctx, imageSize.width, 0.0);
CGContextScaleCTM(ctx, -1.0, 1.0);
CGContextDrawImage(ctx, pickedImage.CGImage, CGRectMake(0.0, 0.0, imageSize.width, imageSize.height));
UIImage *transformedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum (transformedImage, self, @selector(photoSaved:didFinishSavingWithError:contextInfo:), nil);

Это было написано из памяти и без помощи компилятора, пожалуйста, не копируйте и не вставляйте ...

person Bill Dudney    schedule 31.03.2011
comment
@ Билл Дадни: UIGraphicsBeginImageContextWithOptions не возвращает контекст; Как это установить? а CGContextDrawImage нужен прямоугольник. Я asusme я должен сделать это с 0, 0 и imageSize? - person Oliver; 01.04.2011
comment
обновлен новым и улучшенным кодом, вероятность того, что он будет работать, еще выше. вы не копировали и не вставляли? Вы читали документацию и сами писали? :) - person Bill Dudney; 01.04.2011
comment
@Bill Dudney: :-) У меня было копирование / вставка, но это было легче понять, о чем идет речь в XCode (со ссылками на объявление методов / функций, справку, ...). На самом деле я все еще читаю документ :-) - person Oliver; 01.04.2011
comment
@ Билл Дадни: Вау, я кое-что не понимаю. Изображение зеркально отражается (ось x), поворачивается на 90 ° вправо и деформируется. Значения x и Y размера кажутся инвертированными ... Я не вижу, что заставляет изображение вращаться. Как вы думаете, может ли быть конфликт с изображениями exifs? - person Oliver; 01.04.2011
comment
Почему вы используете CGContextTranslateCTM? - person Oliver; 01.04.2011
comment
@Bill Dudney: Я действительно не понимаю, почему изображение вращается ... Я попробовал сделать это другим способом, вызвав сначала CGContextRotateCTM, затем CGContextScaleCTM, но это все равно не очень хорошо. Или должно быть хорошо. Если вы поворачиваете на 180 °, а затем по вертикали инвертируете зеркальное изображение, вы должны вернуть исходное изображение ... - person Oliver; 01.04.2011
comment
Комбинация перевода и масштабирования перемещает начало координат вправо, а не влево. Измените свой вопрос выше, используя текущий код, и я постараюсь взглянуть на него позже сегодня. - person Bill Dudney; 01.04.2011

Я знаю, что на этот вопрос уже был дан ответ, но ответ выше не сработал для меня, поэтому, если есть другие ...

UIImage *theImage = [info objectForKey:UIImagePickerControllerOriginalImage];
    if (picker.cameraDevice == UIImagePickerControllerCameraDeviceFront) {
        CGSize imageSize = theImage.size;
        UIGraphicsBeginImageContextWithOptions(imageSize, YES, 1.0);
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        CGContextRotateCTM(ctx, M_PI/2);
        CGContextTranslateCTM(ctx, 0, -imageSize.width);
        CGContextScaleCTM(ctx, imageSize.height/imageSize.width, imageSize.width/imageSize.height);
        CGContextDrawImage(ctx, CGRectMake(0.0, 0.0, imageSize.width, imageSize.height), theImage.CGImage);
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    }

и newImage - это ваше новое изображение с ориентацией вверх

person Andrew Park    schedule 26.02.2012

Возможно, вы захотите отразить изображение, которое вы получаете с камеры, но то, что вы получаете изначально, является правильным. Сделайте снимок с текстом для сравнения.

person zambono    schedule 15.01.2013

Ответ Эндрю Парка отлично работает. Это версия Swift.

func flipImage(image: UIImage!) -> UIImage! {
    let imageSize:CGSize = image.size;
    UIGraphicsBeginImageContextWithOptions(imageSize, true, 1.0);
    let ctx:CGContextRef = UIGraphicsGetCurrentContext()!;
    CGContextRotateCTM(ctx, CGFloat(M_PI/2.0));
    CGContextTranslateCTM(ctx, 0, -imageSize.width);
    CGContextScaleCTM(ctx, imageSize.height/imageSize.width, imageSize.width/imageSize.height);
    CGContextDrawImage(ctx, CGRectMake(0.0, 0.0, imageSize.width, imageSize.height), image.CGImage);
    let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage
}
person igraczech    schedule 17.01.2016

Немного более простой ответ, обновленный для Swift 3:

func flipImage(image: UIImage) -> UIImage {
    guard let cgImage = image.cgImage else {
        // Could not form CGImage from UIImage for some reason.
        // Return unflipped image
        return image
    }
    let flippedImage = UIImage(cgImage: cgImage, 
                               scale: image.scale, 
                               orientation: .leftMirrored)
    return flippedImage
}
person Bradley Mackey    schedule 20.09.2016
comment
UIImage не имеет эквивалента CGImage во многих случаях, поэтому это часто бесполезно. - person Stephen Radford; 21.09.2016
comment
Искал решение, которое бы переворачивало изображение предпросмотра с фронтальной камеры. Это работало внутри метода photoOutput. - person Patrick.Bellot; 27.03.2018

Как и другие ответы, у меня была такая же проблема. Но просто переверните окончательное изображение - это только половина ответа, потому что изображение предварительного просмотра, отображаемое UIPickerController, когда вы делаете снимок с помощью передней камеры, все еще инвертировано (зеркально).

Основываясь на некоторых кодах из Интернета, я создал Pod, чтобы добиться этого желаемого поведения:

https://github.com/lucasecf/LEMirroredImagePicker

После установки вам просто нужно вызвать эти две строки кода вместе с вашим UIImagePickerController:

self.mirrorFrontPicker = [[LEMirroredImagePicker alloc] initWithImagePicker:pickerController];
[self.mirrorFrontPicker mirrorFrontCamera];

Вот и все, просто так. Вы можете проверить дополнительную информацию в README по ссылке github.

person Lucas Eduardo    schedule 21.07.2013
comment
Привет, LEImagePickerController, похоже, не работает, предварительный просмотр все еще зеркалируется (iOS7, iPhone 4S) - person Zoltán Matók; 15.10.2014
comment
Привет! Предыдущий код был довольно старым. Теперь я создал Pod и обновил код для работы с более новыми версиями iOS. Если хотите, можете еще раз проверить проект в github. - person Lucas Eduardo; 23.05.2015
comment
Просто попробовал. Работает потрясающе! (Пробовал с iOS 8.3, Swift и Xcode 6.3.1) Я согласен с тем, что переворачивание только окончательного изображения не похоже на хорошее взаимодействие с пользователем. Спасибо за создание LEDMirroredImagePicker! Действительно проста в использовании! - person Alex; 06.06.2015
comment
Очень проста в использовании, но на самом деле конечный результат остается зеркальным. Вы просто инвертируете изображение камеры для начала. Так что если я, например, снимаю селфи, это кажется очень странным. Было бы неплохо, если бы был способ просто не инвертировать превью. Тем не менее, стручок все еще крутой! - person bmurmistro; 03.08.2016

Я хотел бы проголосовать за @Lucas Eduardo, я попытался интегрировать компонент LEImagePickerController в свой проект, как показано ниже:

- (void)onCamera:(id)sender {
    UIImagePickerController* imagePicker = [[UIImagePickerController alloc] init];
    imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
    imagePicker.cameraDevice = UIImagePickerControllerCameraDeviceFront;
    imagePicker.delegate = self;

    //cover the switch button at the top right corner, I just need user take photo with the front facing camera
    UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
    view.center = CGPointMake(CGRectGetWidth(imagePicker.view.bounds) - CGRectGetWidth(view.bounds)/2, CGRectGetHeight(view.bounds)/2);
    view.backgroundColor = [UIColor blackColor];
    [imagePicker.view addSubview:view];

    LEMirroredImagePicker* mirrorFrontPicker = [[LEMirroredImagePicker alloc] initWithImagePicker:imagePicker];
    [mirrorFrontPicker mirrorFrontCamera];

    [self presentViewController:imagePicker animated:YES completion:nil];
}
person roby    schedule 08.07.2015

person    schedule
comment
Это не настоящее зеркальное отображение - person Jakub Truhlář; 04.02.2016
comment
Это не всегда работает: если вы создаете экземпляр UIImage без отображения в UIImageView, у него не будет CGImage для предоставления. - person igraczech; 08.02.2016