Front facing camera in UIImagePickerController

I am developing a front camera application on iPad2 using the UIImagePickerController .

When I capture an image, it appears as flipped from left to right.

How to fix it?

 if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { UIImagePickerController *imgPkr = [[UIImagePickerController alloc] init]; imgPkr.delegate = self; imgPkr.sourceType = UIImagePickerControllerSourceTypeCamera; imgPkr.cameraDevice=UIImagePickerControllerCameraDeviceFront; UIImageView *anImageView=[[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:@"select%d.png",val]]]; anImageView.frame = CGRectMake(0, 0, anImageView.image.size.width, anImageView.image.size.height); imgPkr.cameraOverlayView = anImageView; [theApp.TabViewControllerObject presentModalViewController:imgPkr animated:YES]; [imgPkr release]; } 
+62
ios objective-c iphone swift uiimagepickercontroller
Feb 13 '12 at 4:30
source share
8 answers

You can flip the image from the original image using this

 UIImage *flippedImage = [UIImage imageWithCGImage:picture.CGImage scale:picture.scale orientation:UIImageOrientationLeftMirrored]; 



Edit: Added quick code

 let flippedImage = UIImage(CGImage: picture.CGImage, scale: picture.scale, orientation:.LeftMirrored) 
+74
Feb 13
source share

I had the same problem - and the solution above received only half the answer, because the user had to approve the mirror image before moving to the next page of my application - where I use the captured image after scrolling.

To solve this problem, I had to flip the camera view when I switch to the front camera:

 - (IBAction)flipCamera:(id)sender { if(cameraUI.cameraDevice == UIImagePickerControllerCameraDeviceFront) { cameraUI.cameraDevice = UIImagePickerControllerCameraDeviceRear; } else { cameraUI.cameraDevice = UIImagePickerControllerCameraDeviceFront; } cameraUI.cameraViewTransform = CGAffineTransformScale(cameraUI.cameraViewTransform, -1, 1); } 



Just to extend this excellent answer, some typical complete code, Dec2013, iOS7 / Xcode5. Does everything. You just need an icon (cameraToggle.PNG in the example).

 -(void)showTheDeviceCamera { if ( ! [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] ) return; // self.cameraController is a UIImagePickerController self.cameraController = [[UIImagePickerController alloc] init]; self.cameraController.delegate = (id)self; self.cameraController.mediaTypes = @[(NSString *)kUTTypeImage]; self.cameraController.allowsEditing = YES; self.cameraController.sourceType = UIImagePickerControllerSourceTypeCamera; [self presentViewController:self.cameraController animated:YES completion:NULL]; // Add front-rear toggle button MANUALLY, IF NECESSARY // (You seem to usually get it for free, on iPhone, but // need to add manually on an iPad.) UIView *buttonView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"cameraToggle"]]; [buttonView sizeToFit]; buttonView.userInteractionEnabled = YES; [self.cameraController.view addSubview:buttonView]; UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_frontRearButtonClicked) ]; tap.numberOfTapsRequired = 1; [buttonView addGestureRecognizer:tap]; // we'll add it at the top right .. could be anywhere you want buttonView.center = CGPointMake( self.cameraController.view.frame.size.width-buttonView.frame.size.width, 3.0 * buttonView.frame.size.height ); } -(void)_frontRearButtonClicked { [UIView transitionWithView:self.cameraController.view duration:1.0 options:UIViewAnimationOptionAllowAnimatedContent | UIViewAnimationOptionTransitionFlipFromLeft animations:^{ if ( self.cameraController.cameraDevice == UIImagePickerControllerCameraDeviceRear ) self.cameraController.cameraDevice = UIImagePickerControllerCameraDeviceFront; else self.cameraController.cameraDevice = UIImagePickerControllerCameraDeviceRear; } completion:NULL]; } 
+19
Aug 13 '12 at 20:29
source share

Like the other answers, I had the same problem. As Jonathan Betzer mentioned, just flipping the final image is only half the answer, because the preview image displayed by the UIPickerController, when you take a picture from the front camera, is still inverted (mirrored).

Yonatan Betzer anwser works fine, but he did not mention how and where the action could be placed to change the camera device.

Based on some codes from the Internet, I created Pod to get this desired behavior:

https://github.com/lucasecf/LEMirroredImagePicker

After installation, you just need to call these two lines of code along with your UIImagePickerController :

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

And that’s all, just like that. You can check the additional information in the readme links of github.

+9
Jul 21 '13 at 19:09
source share

Just add how I just achieved this, without subclassing the UIImagePickerController and without adding extra buttons to the camera view.

Just listen to this notification that fires several times each time the camera changes:

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cameraChanged:) name:@"AVCaptureDeviceDidStartRunningNotification" object:nil]; 

Then use this method to flip the camera view:

 - (void)cameraChanged:(NSNotification *)notification { if(imagePicker.cameraDevice == UIImagePickerControllerCameraDeviceFront) { imagePicker.cameraViewTransform = CGAffineTransformIdentity; imagePicker.cameraViewTransform = CGAffineTransformScale(imagePicker.cameraViewTransform, -1, 1); } else { imagePicker.cameraViewTransform = CGAffineTransformIdentity; } } 
+6
Dec 16 '13 at 10:01
source share

I know this question is really old, but it looks like this is another issue. Just set the CGAffineTransform in the CGAffineTransform property to the cameraViewTransform object.

 let picker = UIImagePickerController() picker.cameraViewTransform = CGAffineTransformScale(picker.cameraViewTransform, -1, 1) 
+4
Nov 22 '14 at 8:19
source share

A full working example in Swift that answers the initial question of this post (tested on iPhone 5c using iOS 8.2):

  import UIKit class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIActionSheetDelegate { @IBOutlet var myUIImageView: UIImageView! var myUIImagePickerController: UIImagePickerController! override func viewDidLoad() { super.viewDidLoad() } override func viewWillAppear(animated: Bool) { println("viewWillAppear(animated: Bool) method called.") super.viewWillAppear(animated) NSNotificationCenter.defaultCenter().removeObserver(self) } override func viewWillDisappear(animated: Bool) { println("viewWillDisappear(animated: Bool) method called.") super.viewWillDisappear(animated) NSNotificationCenter.defaultCenter().addObserver(self, selector: "cameraChanged:", name: "AVCaptureDeviceDidStartRunningNotification", object: nil) } /* UIImagePickerControllerDelegate Section */ func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) { if(self.myUIImagePickerController.sourceType == UIImagePickerControllerSourceType.Camera) { self.myUIImageView.image = info[UIImagePickerControllerEditedImage] as? UIImage } else { self.myUIImageView.image = info[UIImagePickerControllerOriginalImage] as? UIImage } self.dismissViewControllerAnimated(true, completion: nil) } func imagePickerControllerDidCancel(picker: UIImagePickerController) { self.dismissViewControllerAnimated(true, completion: nil) } /* You can choose to use one of the UIResponder methods: touchesBegan, touchesMoved, touchesEnded etc, in order to detect the touch on the UIImageView. */ override func touchesEnded(touches: NSSet, withEvent event: UIEvent) { let touch: UITouch? = touches.anyObject() as? UITouch if (touch?.view == myUIImageView) { println("myUIImageView has been tapped by the user.") self.takingAPictureUsingTheCamera() } } func takingAPictureUsingTheCamera() { self.myUIImagePickerController = UIImagePickerController() self.myUIImagePickerController.delegate = self // Set the delegate self.myUIImagePickerController.sourceType = UIImagePickerControllerSourceType.Camera self.myUIImagePickerController.cameraDevice = UIImagePickerControllerCameraDevice.Front // self.myUIImagePickerController.editing = true self.myUIImagePickerController.allowsEditing = true self.presentViewController(self.myUIImagePickerController, animated: true, completion: nil) } func cameraChanged(notification: NSNotification) { println("cameraChanged(notification: NSNotification) method called.") self.myUIImagePickerController.cameraViewTransform = CGAffineTransformIdentity if(self.myUIImagePickerController.cameraDevice == UIImagePickerControllerCameraDevice.Front){ self.myUIImagePickerController.cameraViewTransform = CGAffineTransformScale(self.myUIImagePickerController.cameraViewTransform, -1, 1) } } }// End class 
0
Mar 16 '15 at 3:23
source share

I tried all the answers described here, but none of them offered the result I was looking for. Eiter the whole UIImagePickerViewController was converted, so the camera was not intuitive, not like looking in the mirror, or only the image was converted afterwards, which was fine, but you have the wrong image viewing between them. So I ended up with this hack, it is definitely not the best, but it works on iOS8 and 9 and gives me the result I need.

Make sure you add an observer to receive a notification when you click the image capture button:

 NSNotificationCenter.defaultCenter().addObserver(self, selector: "photoTaken", name: "_UIImagePickerControllerUserDidCaptureItem", object: nil) 

In the potoTaken method potoTaken you can do something like this to find the preview image and convert it the way you expect:

 func photoTaken() { for subview in self.imagePicker.view.subviews { for subsubview in subview.subviews { for subsubsubview in subsubview.subviews { for subsubsubsubview in subsubsubview.subviews { for subsubsubsubsubview in subsubsubsubview.subviews { for subsubsubsubsubsubview in subsubsubsubsubview.subviews { for subsubsubsubsubsubsubview in subsubsubsubsubsubview.subviews { if subsubsubsubsubsubsubview.isKindOfClass(UIImageView) { subsubsubsubsubsubsubview.transform = CGAffineTransformScale(self.imagePicker.cameraViewTransform, -1, 1) } } } } } } } } } 

And in your delegate didFinishPickingMediaWithInfo , flip the image again before saving or displaying.

 func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) { if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage { let flippedImage = UIImage(CGImage: pickedImage.CGImage!, scale: pickedImage.scale, orientation: .LeftMirrored) myCustomPhotoAlbum.sharedInstance.saveImage(flippedImage) self.imageView.image = flippedImage } self.dismissViewControllerAnimated(true, completion: nil) } 
0
Jan 25 '16 at 13:07 on
source share

It seems that AVCaptureDeviceDidStartRunningNotification no longer used as a means of detecting changes in the camera device. In addition, the cameraDevice property on the UIImagePickerController does not work with KVO. However, it is still possible to detect camera device changes as shown below (although long-term support for this solution is not guaranteed, since we use KVO for a property that is not explicitly designated as KVO-compatible).

 import AVFoundation var context = 0 override func viewDidLoad() { super.viewDidLoad() // Register for notifications let notificationCenter = NSNotificationCenter.defaultCenter() notificationCenter.addObserver(self, selector: #selector(handleCaptureSessionDidStartRunning(_:)), name: AVCaptureSessionDidStartRunningNotification, object: nil) notificationCenter.addObserver(self, selector: #selector(handleCaptureSessionDidStopRunning(_:)), name: AVCaptureSessionDidStopRunningNotification, object: nil) } deinit { NSNotificationCenter.defaultCenter().removeObserver(self) } func handleCaptureSessionDidStartRunning(notification: NSNotification) { guard let session = notification.object as? AVCaptureSession else { return } session.addObserver(self, forKeyPath: "inputs", options: [ .Old, .New ], context: &context) } func handleCaptureSessionDidStopRunning(notification: NSNotification) { guard let session = notification.object as? AVCaptureSession else { return } session.removeObserver(self, forKeyPath: "inputs") } override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { if context == &self.context { if let inputs = change?[NSKeyValueChangeNewKey] as? [AnyObject], captureDevice = (inputs.first as? AVCaptureDeviceInput)?.device { switch captureDevice.position { case .Back: print("Switched to back camera") case .Front: print("Switched to front camera") case .Unspecified: break } } } else { super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context) } } 
0
Aug 15 '16 at 2:10
source share



All Articles