UIImagePickerController中的前置摄像头

我正在使用UIImagePickerController在iPad2上开发前置摄像头应用程序。

当我捕捉图像时,显示为从左到右翻转。

我该如何纠正?

 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]; } 

你可以使用这个从源图像翻转图像

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

编辑:添加了swift代码

 let flippedImage = UIImage(CGImage: picture.CGImage, scale: picture.scale, orientation:.LeftMirrored) 

我有同样的问题 – 上面的解决scheme只给了我一半的答案,因为用户必须批准镜像后才能进入我的应用程序的下一页 – 在翻转它之后使用捕获的图像。

为了解决这个问题,我不得不在每次切换到前置摄像头时翻转相机视图:

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

为了扩展这个伟大的答案,一些典型的完整代码,Dec2013,iOS7 / Xcode5。 做的一切。 你只需要一个图标(例如cameraToggle.PNG)。

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

作为其他答案,我有同样的问题。 正如Yonatan Betzer所提到的,只要翻转最后的图像只有一半的答案,因为当用前置摄像头拍照时,由UIPickerController显示的预览图像仍然是倒置的(镜像的)。

Yonatan Betzer的摄影师工作很好,但他没有提到如何或在哪里把行动改变摄像头设备。

基于互联网的一些代码,我创build了一个Pod来获得这个想要的行为:

https://github.com/lucasecf/LEMirroredImagePicker

安装完成后,您只需将这两行代码与您的UIImagePickerController一起调用即可:

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

那就是这样。 您可以在github链接的README中查看更多信息。

只是添加我刚刚实现这个没有UIImagePickerController的子类,并没有添加额外的button到相机视图。

只要监听相机发生变化时发出的多次通知即可:

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

然后用这个方法翻转相机视图:

 - (void)cameraChanged:(NSNotification *)notification { if(imagePicker.cameraDevice == UIImagePickerControllerCameraDeviceFront) { imagePicker.cameraViewTransform = CGAffineTransformIdentity; imagePicker.cameraViewTransform = CGAffineTransformScale(imagePicker.cameraViewTransform, -1, 1); } else { imagePicker.cameraViewTransform = CGAffineTransformIdentity; } } 

我知道这个问题真的很老,但似乎这仍然是一个普遍的问题。 只需在UIImagePickerController对象的cameraViewTransform属性上设置一个CGAffineTransform cameraViewTransform

 let picker = UIImagePickerController() picker.cameraViewTransform = CGAffineTransformScale(picker.cameraViewTransform, -1, 1) 

Swift中的完整工作示例,回答了本文最初的问题(使用iOS 8.2在iPhone 5c上testing):

  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 

我尝试了这里描述的所有答案,但没有一个提供了我正在寻找的结果。 整个UIImagePickerViewController被转换了,所以相机不是很直观,不像看镜子,或者只是图像被转换后,什么工作正常,但你有一个错误的图像预览中间。 所以我结束了这个黑客,这绝对不是最好的实践,但在iOS8和9的作品,并给我我需要的结果。

确保你添加了一个观察者,当按下捕捉图像button时得到通知:

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

potoTaken方法中,您可以执行类似这样的操作来查找预览图像,并将其转换为您期望的样子:

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

在您的didFinishPickingMediaWithInfo委托保存或显示之前再次翻转图像。

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

它看起来像AVCaptureDeviceDidStartRunningNotification不再作为检测摄像头设备变化的手段。 此外, UIImagePickerController上的cameraDevice属性不适用于KVO。 但是,仍然可以检测摄像头设备的变化,如下所示(虽然我们对未明确标记为KVO的属性使用KVO,但对此解决scheme的长期支持并不能保证)。

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