我正在使用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];
}
答案 0 :(得分:75)
您可以使用此
翻转源图像中的图像UIImage *flippedImage = [UIImage imageWithCGImage:picture.CGImage scale:picture.scale orientation:UIImageOrientationLeftMirrored];
修改:添加了快速代码
let flippedImage = UIImage(CGImage: picture.CGImage, scale: picture.scale, orientation:.LeftMirrored)
答案 1 :(得分:19)
我遇到了同样的问题 - 上面的解决方案只给我一半的答案,因为用户必须先批准镜像后才能进入我的应用程序的下一页 - 我在翻转后使用捕获的图像。 / p>
要解决此问题,每当我切换到前置摄像头时,我都必须翻转摄像机视图:
- (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];
}
答案 2 :(得分:10)
正如其他答案,我遇到了同样的问题。正如Yonatan Betzer所提到的,只是翻转最终图像只有答案的一半,因为预览图像由UIPickerController在用前置摄像头拍照时显示,它仍然是倒置的(镜像)。
Yonatan Betzer的anwser效果很好,但他没有提到如何或在何处采取行动来改变相机设备。
基于互联网的一些代码,我创建了一个Pod来获得这种想要的行为:
https://github.com/lucasecf/LEMirroredImagePicker
安装完成后,您只需要将这两行代码与UIImagePickerController
:
self.mirrorFrontPicker = [[LEMirroredImagePicker alloc] initWithImagePicker:pickerController];
[self.mirrorFrontPicker mirrorFrontCamera];
就是这样,就像那样。您可以在github链接的README中查看更多信息。
答案 3 :(得分:6)
添加UIImagePickerController的子类并且不向摄像机视图添加额外的按钮,只是为了添加我刚刚实现的目的。
只需更改相机更改时多次触发此通知:
[[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;
}
}
答案 4 :(得分:6)
我知道这个问题真的很旧但似乎这仍是一个常见的问题。只需在CGAffineTransform
对象的cameraViewTransform
属性上设置UIImagePickerController
即可。
let picker = UIImagePickerController()
picker.cameraViewTransform = CGAffineTransformScale(picker.cameraViewTransform, -1, 1)
答案 5 :(得分:2)
更新了“ bandog”答案,以实现快速4
let picker = UIImagePickerController()
picker.cameraViewTransform = picker.cameraViewTransform.scaledBy(x: -1, y: 1)
答案 6 :(得分:2)
我花了几个小时,但我想我到了。这是 Swift 5.2 的有效解决方案,该解决方案说明了如何获取正确的图像(在ImagePicker预览和输出中)。
//Registering to get notification when users takes a picture
override func viewDidLoad() {
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "_UIImagePickerControllerUserDidCaptureItem"), object: nil, queue: nil) { (notification) in
self.changePhotoOrientation()
}
//Changing image orientation for ImagePicker preview
func changePhotoOrientation() {
var subviews: [UIView] = [imagePicker.view]
while (!subviews.isEmpty) {
let subview = subviews.removeFirst()
subviews += subview.subviews
if (subview.isKind(of: UIImageView.self)) {
subview.transform = self.imagePicker.cameraViewTransform.scaledBy(x: -1, y: 1)
}
}
}
//Changing image orientation for the output image
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let userPickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
image = UIImage(cgImage: userPickedImage.cgImage!, scale: userPickedImage.scale, orientation: .leftMirrored)
}
}
}
答案 7 :(得分:0)
Swift 中的完整工作示例,它回答了这篇文章的初始问题(使用iOS 8.2在iPhone 5c上测试过):
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
答案 8 :(得分:0)
看起来AVCaptureDeviceDidStartRunningNotification
不再可用作检测相机设备更改的方法。此外,cameraDevice
上的UIImagePickerController
属性不适用于KVO。但是,仍然可以检测到摄像机设备的更改,如下所示(尽管我们在未明确标记为符合KVO标准的属性上使用KVO,因此无法保证对此解决方案的长期支持。)
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)
}
}