Фронтальная камера в UIImagePickerController - PullRequest
64 голосов
/ 13 февраля 2012

Я занимаюсь разработкой приложения для камеры на передней панели iPad2 с помощью UIImagePickerController.

Когда я снимаю изображение, оно отображается как перевернутый слева направо.

Как исправитьэто?

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

Ответы [ 8 ]

75 голосов
/ 13 февраля 2012

Вы можете перевернуть изображение из исходного изображения, используя это

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

Редактировать: Добавлен код Swift

let flippedImage = UIImage(CGImage: picture.CGImage, scale: picture.scale, orientation:.LeftMirrored)
19 голосов
/ 14 августа 2012

У меня была та же проблема - и решение, приведенное выше, дало мне только половину ответа, потому что пользователь должен был утвердить зеркальное изображение, прежде чем перейти на следующую страницу моего приложения - где я использую захваченное изображение после его перелистывания.

Чтобы решить эту проблему, мне приходилось переворачивать изображение камеры всякий раз, когда я переключался на фронтальную камеру:

- (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];
    }
10 голосов
/ 21 июля 2013

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

Ответчик Йонатана Бетцера прекрасно работает, но он не упомянул, как и где выполнить действие, чтобы изменить устройство камеры.

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

https://github.com/lucasecf/LEMirroredImagePicker

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

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

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

6 голосов
/ 22 ноября 2014

Я знаю, что этот вопрос действительно старый, но кажется, что это все еще распространенная проблема.Просто установите CGAffineTransform для свойства cameraViewTransform объекта UIImagePickerController.

let picker = UIImagePickerController()
picker.cameraViewTransform = CGAffineTransformScale(picker.cameraViewTransform, -1, 1)
6 голосов
/ 16 декабря 2013

Просто чтобы добавить, как я только что достиг этого, не используя 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;
    }
}
2 голосов
/ 13 июля 2018

Обновлен ответ "бандог" для swift 4

let picker = UIImagePickerController()
picker.cameraViewTransform = picker.cameraViewTransform.scaledBy(x: -1, y: 1)
0 голосов
/ 15 августа 2016

Похоже, 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)
    }
}
0 голосов
/ 16 марта 2015

Полный рабочий пример в Swift , который отвечает на первоначальный вопрос этого поста (проверено на iPhone 5c с использованием 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
...