Przednia kamera w UIImagePickerController
Rozwijam aplikację przednia kamera w iPad2 za pomocą UIImagePickerController
.
Kiedy uchwycę obraz, jest on wyświetlany jako odwrócony od lewej do prawej.
Jak to poprawić?
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];
}
9 answers
Możesz odwrócić obraz z obrazu źródłowego użyj tego
UIImage *flippedImage = [UIImage imageWithCGImage:picture.CGImage scale:picture.scale orientation:UIImageOrientationLeftMirrored];
Edit: Dodano kod swift
let flippedImage = UIImage(CGImage: picture.CGImage, scale: picture.scale, orientation:.LeftMirrored)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-25 11:08:02
Miałem ten sam problem - a powyższe rozwiązanie dało mi tylko połowę odpowiedzi, ponieważ użytkownik musiał zatwierdzić obraz lustrzany przed przejściem do następnej strony mojej aplikacji - gdzie używam przechwyconego obrazu po przerzuceniu go.
Aby rozwiązać ten problem, musiałem przerzucić widok kamery za każdym razem, gdy przełączyłem się na przednią kamerę:
- (IBAction)flipCamera:(id)sender {
if(cameraUI.cameraDevice == UIImagePickerControllerCameraDeviceFront)
{
cameraUI.cameraDevice = UIImagePickerControllerCameraDeviceRear;
}
else {
cameraUI.cameraDevice = UIImagePickerControllerCameraDeviceFront;
}
cameraUI.cameraViewTransform = CGAffineTransformScale(cameraUI.cameraViewTransform, -1, 1);
}
Aby rozwinąć tę świetną odpowiedź, jakiś typowy kompletny kod, Dec2013, iOS7 / Xcode5. Robi wszystko. Potrzebujesz tylko ikony (cameraToggle.PNG w przykładzie).
-(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];
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-03 15:16:32
Jak Inne odpowiedzi, miałem ten sam problem. Jak wspomniał Yonatan Betzer, po prostu odwróć ostateczny obraz to tylko połowa odpowiedzi, ponieważ obraz podglądu, wyświetlany przez UIPickerController podczas robienia zdjęcia przednim aparatem, jest nadal odwrócony (lustrzany).
Anwser Yonatana Betzera działa świetnie, ale nie wspomniał, jak i gdzie umieścić akcję, aby zmienić urządzenie aparatu.
Na podstawie niektórych kodów z Internetu, stworzyłem Pod, aby uzyskać to pożądane zachowanie:
Https://github.com/lucasecf/LEMirroredImagePicker
Po zainstalowaniu wystarczy wywołać te dwie linijki kodu razem ze swoim UIImagePickerController
:
self.mirrorFrontPicker = [[LEMirroredImagePicker alloc] initWithImagePicker:pickerController];
[self.mirrorFrontPicker mirrorFrontCamera];
I to wszystko, po prostu tak. Możesz sprawdzić więcej informacji w README linku github.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-23 14:27:29
Tylko dodać, jak udało mi się to osiągnąć bez podklasowania UIImagePickerController i bez dodawania dodatkowych przycisków do widoku kamery.
Po prostu słuchaj tego powiadomienia, które jest uruchamiane kilka razy, gdy kamera jest zmieniana:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(cameraChanged:)
name:@"AVCaptureDeviceDidStartRunningNotification"
object:nil];
Następnie użyj tej metody, aby odwrócić widok kamery:
- (void)cameraChanged:(NSNotification *)notification
{
if(imagePicker.cameraDevice == UIImagePickerControllerCameraDeviceFront)
{
imagePicker.cameraViewTransform = CGAffineTransformIdentity;
imagePicker.cameraViewTransform = CGAffineTransformScale(imagePicker.cameraViewTransform, -1, 1);
} else {
imagePicker.cameraViewTransform = CGAffineTransformIdentity;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-16 10:01:19
Wiem, że to pytanie jest naprawdę stare, ale wydaje się, że jest to wciąż powszechny problem. Po prostu ustaw {[1] } na właściwości cameraViewTransform
na obiekcie UIImagePickerController
.
let picker = UIImagePickerController()
picker.cameraViewTransform = CGAffineTransformScale(picker.cameraViewTransform, -1, 1)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-22 08:19:09
Zaktualizowano odpowiedź "bandog" dla swift 4
let picker = UIImagePickerController()
picker.cameraViewTransform = picker.cameraViewTransform.scaledBy(x: -1, y: 1)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-13 00:55:33
Zajęło mi to kilka godzin, ale chyba dotarłem. Oto rozwiązanie dla Swift 5.2 Jak uzyskać poprawny obraz (zarówno w Podglądzie ImagePicker, jak i na wyjściu).
//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)
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-04 12:20:39
Wygląda na to, że AVCaptureDeviceDidStartRunningNotification
nie jest już dostępny jako sposób wykrywania zmian urządzenia kamery. Ponadto obiekt cameraDevice
na UIImagePickerController
nie działa z KVO. Jednak nadal możliwe jest wykrywanie zmian urządzeń kamery, jak pokazano poniżej (choć długoterminowa obsługa tego rozwiązania nie jest gwarantowana, ponieważ używamy KVO na właściwości, która nie jest wyraźnie oznaczona jako zgodna z 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)
}
}
Wersja Swift 4+:
import AVFoundation
var context = 0
override func viewDidLoad() {
super.viewDidLoad()
// Register for notifications
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "AVCaptureSessionDidStartRunningNotification"), object: nil, queue: nil) { (notification) in
self.handleCaptureSessionDidStartRunning(notification: notification)}
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "AVCaptureSessionDidStopRunningNotification"), object: nil, queue: nil) { (notification) in
self.handleCaptureSessionDidStopRunning(notification: notification)}
}
deinit {
NotificationCenter.default.removeObserver(self)
}
func handleCaptureSessionDidStartRunning(notification: Notification){
guard let session = notification.object as? AVCaptureSession else { return }
session.addObserver(self, forKeyPath: "inputs", options: [ .old, .new ], context: &context)
}
func handleCaptureSessionDidStopRunning(notification: Notification){
guard let session = notification.object as? AVCaptureSession else { return }
session.removeObserver(self, forKeyPath: "inputs")
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if context == &self.context {
if let inputs = change?[NSKeyValueChangeKey.newKey] as? [AnyObject], let 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.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-24 10:14:36
Pełny przykład pracy w Swift , który odpowiada na początkowe pytanie tego posta (testowane na iPhone 5c przy użyciu 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-16 05:56:36