11

When using the front camera of the iPhone 4 to take a picture, the taken picture is mirrored compared with what you see on the iPhone screen. How may I restore the "on screen" view of the UIImage (not the UIImageView), and be able to save it like this ?

I tried :

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

then putting it on screen. It is nearly the same as seen on screen, but the saved image is distorted.

So... How may I restore the "on screen" view of the UIImage (not the UIImageView), and be able to save it like this ?

I also tried this way :

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

But that just gives a black image.

Oliver
  • 23,072
  • 33
  • 138
  • 230

8 Answers8

27
- (void)didTakePicture:(UIImage *)picture
{
    UIImage * flippedImage = [UIImage imageWithCGImage:picture.CGImage scale:picture.scale orientation:UIImageOrientationLeftMirrored];
    picture = flippedImage;
}
Mohammed Afsul
  • 692
  • 7
  • 8
10

I know this question was already answered, but the answer above didn't work for me so in case there are others...

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

and newImage is your new image with the up orientation

Andrew Park
  • 1,489
  • 1
  • 17
  • 26
6

The best way is to draw the image into a new context.

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);

This was written out of memory and without aid of a compiler, please don't copy and paste...

Bill Dudney
  • 3,358
  • 1
  • 16
  • 13
  • @Bill Dudney : UIGraphicsBeginImageContextWithOptions does not return a context; How do you set it ? and CGContextDrawImage needs a rect. I asusme i have to make it with 0, 0 and imageSize ? – Oliver Mar 31 '11 at 21:15
  • updated with new and improved code, even more likely to work. you didn't copy and paste did you? You read the docs and wrote it yourself right? :) – Bill Dudney Mar 31 '11 at 21:44
  • @Bill Dudney : :-) I had copy / paste, but that was to understand easier what it is about into XCode (with links to method/functions declaration, help, ...). I'm actually still reading the doc :-) – Oliver Apr 01 '11 at 00:05
  • @Bill Dudney : Wow, there is something I don't understand. The image is mirrored (x axis) and rotated by 90° to the right, and is rendered deformed. The x and Y values of the size seems to be inversed... I don't see what makes the image rotate. Do you think there could be a conflict with image exifs ? – Oliver Apr 01 '11 at 00:13
  • Why do you use CGContextTranslateCTM ? – Oliver Apr 01 '11 at 00:15
  • @Bill Dudney : I really don't see why the image rotates... I tried another way of doing this, calling first CGContextRotateCTM then CGContextScaleCTM, but it's still not good. Or it should be good. If your rotate by 180° then verticaly inverse a Hmirrored image, you should get the original image back... – Oliver Apr 01 '11 at 00:32
  • The translate and scale combination moves the origin to the right instead of the left. Edit your question above with your current code and I'll try to take a look later today. – Bill Dudney Apr 01 '11 at 13:35
5

You might want to mirror the image you get from the camera but what you originally get is correct. Take a picture with text to compare.

zambono
  • 1,397
  • 1
  • 17
  • 26
5

Andrew Park's answer works great. This is Swift version.

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
}
igraczech
  • 2,408
  • 3
  • 25
  • 30
5

A slightly simpler answer updated for 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
}
Bradley Mackey
  • 6,777
  • 5
  • 31
  • 45
3

As the other answers, I had the same problem. But just flip the final image is only half the answer, because the preview image, displayed by the UIPickerController when you take a picture with the front camera, it's still inverted (mirrored).

Based in some codes from internet, I created a Pod to get this wanted behavior:

https://github.com/lucasecf/LEMirroredImagePicker

After installed, you just have to call this two lines of code together with your UIImagePickerController:

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

And thats it, simply as that. You can check for more informations in the README of the github link.

Lucas Eduardo
  • 11,525
  • 5
  • 44
  • 49
  • Hey LEImagePickerController does not seem to work, the preview is still mirrored (iOS7, iPhone 4S) – Zoltán Matók Oct 15 '14 at 13:33
  • 1
    Hi! The previous code was pretty old. Now, I created a Pod and updated the code to work with newer versions of iOS. You can check again the project in github, if you want. – Lucas Eduardo May 23 '15 at 14:31
  • 1
    Just tried it. It works awesome! (Tried with iOS 8.3, Swift and Xcode 6.3.1) I agree that flipping just the final image doesn't seem like a good user experience. Thank you for creating LEDMirroredImagePicker! Really easy to use! – Alex Jun 06 '15 at 01:55
  • Very easy to use, but really the end result is still mirrored. You just invert the camera display to begin with. So if I'm taking a selfie for example it feels very weird. Would be nice if there was a way to simply not invert the preview. Still a cool Pod though! – bmurmistro Aug 02 '16 at 22:18
0

I'd like to vote up @Lucas Eduardo , I have tried to integrate the component LEImagePickerController into my project as below:

- (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];
}
roby
  • 764
  • 5
  • 15