Front facing camera in UIImagePickerController - ios

I am developing the front facing camera app in iPad2 by using the UIImagePickerController.
When I capture the image it's shows as flipped from left to right.
How do I correct this?
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];
}

You can flip the image from the source image use this
UIImage *flippedImage = [UIImage imageWithCGImage:picture.CGImage scale:picture.scale orientation:UIImageOrientationLeftMirrored];
Edit: Added swift code
let flippedImage = UIImage(CGImage: picture.CGImage, scale: picture.scale, orientation:.LeftMirrored)

I had the same problem - and the solution above only got me half the answer, because the user had to approve the mirrored image before getting to the next page of my app - where I use the captured image after flipping it.
To solve this I had to flip the camera view whenever I switch to the front facing 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 expand on this great 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];
}

As the other answers, I had the same problem. As Yonatan Betzer mentioned, just flip the final image is only half the answer, because the preview image, displayed by the UIPickerController when you take a picture with the front camera, it's still inverted (mirrored).
Yonatan Betzer's anwser works great, but he did not mentioned how or where to put the action to change the camera device.
Based in some codes from internet, I created a Pod to get this wanted behavior:
https://github.com/lucasecf/LEMirroredImagePicker
After installed, you just have to call this two lines of code together with your UIImagePickerController:
self.mirrorFrontPicker = [[LEMirroredImagePicker alloc] initWithImagePicker:pickerController];
[self.mirrorFrontPicker mirrorFrontCamera];
And thats it, simply as that. You can check for more informations in the README of the github link.

Just to add how I have just achieved this without subclassing UIImagePickerController and without adding extra buttons to the camera view.
Simply listen for this notification which is fired several times whenever the camera is changed:
[[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;
}
}

I know this question is really old but it seems like this is a still a common problem. Just set a CGAffineTransform on the cameraViewTransform property on a UIImagePickerController object.
let picker = UIImagePickerController()
picker.cameraViewTransform = CGAffineTransformScale(picker.cameraViewTransform, -1, 1)

Updated "bandog" answer for swift 4
let picker = UIImagePickerController()
picker.cameraViewTransform = picker.cameraViewTransform.scaledBy(x: -1, y: 1)

It took me few hours, but I think I got there. Here is a working solution for Swift 5.2 of how to get correct image (both in ImagePicker preview and in output).
//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)
}
}
}

It looks like AVCaptureDeviceDidStartRunningNotification is no longer available as a means of detecting camera device changes. Also, the cameraDevice property on UIImagePickerController doesn't work with KVO. However, it's still possible to detect camera device changes, as shown below (though long-term support for this solution isn't guaranteed as we're using KVO on a property that isn't explicitly marked as KVO-compliant).
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)
}
}
Swift 4+ version:
import AVFoundation
var context = 0
override func viewDidLoad() {
super.viewDidLoad()
// Register for notifications
let notificationCenter = NSNotificationCenter.defaultCenter()
notificationCenter.addObserver(forName: NSNotification.Name(rawValue: "AVCaptureSessionDidStartRunningNotification"), object: nil, queue: nil) { [weak self] notification in
self?.handleCaptureSessionDidStartRunning(notification: notification)
}
notificationCenter.addObserver(forName: NSNotification.Name(rawValue: "AVCaptureSessionDidStopRunningNotification"), object: nil, queue: nil) { [weak self] 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)
}
}

Full Working Example in Swift, which answers to the initial question of this post (tested on an 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

Related

How to sent imagedata with ImagePicker Controller using swift 4

I have tabbarController and CameraViewController. I want to show the camera after clicking on camera tab. I have done it. after open the camera i want to show that particular image selected to the next viewController, but unable to do it. i am using UIImagePickerController, please help
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
let tabBarIndex = tabBarController.selectedIndex
if tabBarIndex == 0 {
//do your stuff
print("First Tab")
} else if tabBarIndex == 1 {
print("Second Tab")
} else if tabBarIndex == 2 {
//do the camera stuff here
let imagePickerController1 = ImagePickerController()
imagePickerController1.delegate = self
imagePickerController1.imageLimit = 2
present(imagePickerController1,animated: true,completion: nil)
print("camera")
print("Third Tab")
}
}
Done button pressed code.
func doneButtonDidPress(_ imagePicker: ImagePickerController, images: [UIImage]) {
let firstVC = self.storyboard!.instantiateViewController(withIdentifier: "CameraVC") as! CameraVC
show(firstVC, sender: nil)
dismiss(animated: true, completion: nil)
print("done")
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info["UIImagePickerControllerOriginalImage"] as? UIImage {
}
dismiss(animated: true, completion: nil)
}
Your doneButtonDidPress method is implemented in TabBarController and you want selected Images in CameraVC so do 1 thing add NotificationCenter in CameraVC and Post that notification with Images array once you done with Image pick. and load selected images from that array in CameraVC.
CameraVC
NotificationCenter.default.addObserver(self, selector: #selector(updateSelectedImages(_:)), name: NSNotification.Name(rawValue: "updateSelectedImages"), object: nil)
#objc func updateSelectedImages(_ notification: Notification) {
let imagesInfo = notification.object as? NSDictionary
self.arrImages = imagesInfo?.value(forKey: "selectedIamges") as! [UIImage]
self.imageView.image = self.arrImages[0]
self.imageView1.image = self.arrImages[1]
}
UITabBarController
let dict = NSMutableDictionary()
dict.setValue(images, forKey: "selectedIamges")
NotificationCenter.default.post(name: NSNotification.Name("updateSelectedImages"), object: dict)

iOS camera freezes when previewing video when there is a camera overlay

I am attempting to overlay a view over a video capture session in UIImagePicker. The overlay works fine but when the app gets to the screen where the user can "retake", "play" or "use video", the app crashes and gives the error:
2017-04-16 21:33:04.129212-0400 ChugMug[429:59833] libMobileGestalt
MobileGestalt.c:2690: statfs(/mnt4): No such file or directory
2017-04-16 21:33:04.129871-0400 ChugMug[429:59833] libMobileGestalt
MobileGestalt.c:2587: SInt64 NANDSize(): No kIOMediaSizeKey found for
disk0! 2017-04-16 21:33:09.352085-0400 ChugMug[429:60065]
[MediaRemote] Error Operation requires a client callback to have been
registered. requesting playback queue
The code is quite simple, when the overlay is commented out, the video preview screen and buttons work fine, but when the overlay is present the app freezes at the following screen:
Here is the code for the camera and the overlay:
func startMediaBrowserFromViewController(viewController: UIViewController, usingDelegate delegate: UINavigationControllerDelegate & UIImagePickerControllerDelegate) -> Bool {
// 1
if UIImagePickerController.isSourceTypeAvailable(.savedPhotosAlbum) == false {
return false
}
// 2
let mediaUI = UIImagePickerController()
mediaUI.sourceType = .savedPhotosAlbum
mediaUI.mediaTypes = [kUTTypeMovie as NSString as String]
mediaUI.allowsEditing = true
mediaUI.delegate = delegate
// 3
present(mediaUI, animated: true, completion: nil)
return true
}
func startCameraFromViewController(viewController: UIViewController, withDelegate delegate: UIImagePickerControllerDelegate & UINavigationControllerDelegate) -> Bool {
if UIImagePickerController.isSourceTypeAvailable(.camera) == false {
return false
}
cameraController.sourceType = .camera
cameraController.mediaTypes = [kUTTypeMovie as NSString as String]
cameraController.allowsEditing = false
cameraController.delegate = delegate
cameraController.showsCameraControls = true
//customView stuff
let customViewController = CustomOverlayViewController(
nibName:"CustomOverlayViewController",
bundle: nil
)
let customView = customViewController.view //as! CustomOverlayView
customView?.frame = cameraController.view.frame
present(cameraController, animated: true, completion: {
self.cameraController.cameraOverlayView = customView
customViewController.cameraLabel.text = "Camera Label"
self.cameraController.startVideoCapture()
})
return true
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let mediaType = info[UIImagePickerControllerMediaType] as! NSString
dismiss(animated: true, completion: nil)
// Handle a movie capture
if mediaType == kUTTypeMovie {
guard let path = (info[UIImagePickerControllerMediaURL] as! NSURL).path else { return }
if UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(path) {
UISaveVideoAtPathToSavedPhotosAlbum(path, self, nil, nil)
}
}
}
I have no clue what is causing this strange error and cant find anything similar. I hope someone can help me.

Auto capture video using Swift

I'm working on this piece of code responsible for starting video recording on button click.
When I click the button camera view is opening but .startVideoCapture() function doesn't start recording.
I get this strange output every time button is pressed:
2015-08-19 16:48:09.588 Record Video With Swift[922:227442]
Snapshotting a view that has not been rendered results in an empty
snapshot. Ensure your view has been rendered at least once before
snapshotting or snapshot after screen updates.
Also, is there any way to hide the camera view and instead of it place there some progress bar or something?
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIGestureRecognizerDelegate
{
let captureSession = AVCaptureSession()
var previewLayer : AVCaptureVideoPreviewLayer?
var captureDevice : AVCaptureDevice?
var imagePicker = UIImagePickerController()
override func viewDidAppear(animated: Bool)
{
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera) {
println("captureVideoPressed and camera available.")
imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .Camera;
imagePicker.mediaTypes = [kUTTypeMovie!]
imagePicker.allowsEditing = false
imagePicker.showsCameraControls = true
}
else
{
println("Camera not available.")
}
}
#IBAction func rec(sender: AnyObject)
{
self.presentViewController(imagePicker, animated: true, completion: nil)
imagePicker.startVideoCapture()
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject])
{
let tempImage = info[UIImagePickerControllerMediaURL] as! NSURL!
let pathString = tempImage.relativePath
self.dismissViewControllerAnimated(true, completion: {})
UISaveVideoAtPathToSavedPhotosAlbum(pathString, self, nil, nil)
}
}
I recently had this problem and in my case I was using Swift 3 with iOS 10. There are couple of ways to solve it:
You can call the startVideoCapture() in the completion block of present viewcontroller as following:
self.present(self.cameraController, animated: true, completion: {
self.cameraController.startVideoCapture()
if #available(iOS 10.0, *) {
Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { _ in
self.stopMovementsCapture()
}
} else {
// Fallback on earlier versions
Timer.scheduledTimer(timeInterval: 5,
target: self,
selector: #selector(self.stopMovementsCapture),
userInfo: nil,
repeats: false)
}
})
Another way to do is, is by calling startVideoCapture() only after the AVCaptureSessionDidStartRunning notification is fired.
Following is the code to observe the notification:
NotificationCenter.default.addObserver(self, selector: #selector(self.cameraIsReady), name: .AVCaptureSessionDidStartRunning, object: nil)
Following is function called by the above notification:
func cameraIsReady(notification: NSNotification) {
DispatchQueue.main.async {
self.cameraController.startVideoCapture()
if #available(iOS 10.0, *) {
Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { _ in
self.stopMovementsCapture()
}
} else {
// Fallback on earlier versions
Timer.scheduledTimer(timeInterval: 5,
target: self,
selector: #selector(self.stopMovementsCapture),
userInfo: nil,
repeats: false)
}
}
}
Basically make sure that your device is ready to capture the video. Hope this is helpful!
Try to change following:
1.
imagePicker.mediaTypes = NSArray(object: kUTTypeMovie) as! [String]
2.
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
let tempImage = info[UIImagePickerControllerMediaURL] as! NSURL!
let pathString = tempImage.relativePath
self.dismissViewControllerAnimated(true, completion: {})
UISaveVideoAtPathToSavedPhotosAlbum(pathString!, self, nil, nil)
}

UIImage not saving to Camera Roll

I'm currently writing a photo app for iOS in Swift. I'm using the CoreImage Framework to generate a pixel effect on a UIImageView selected by the user. However, I'm having trouble saving the "pixeled" image to the iPhone's Camera Roll. Normally I use
UIImageWriteToSavedPhotosAlbum(pixeledImage,nil,nil,nil)
but it's not saving the UIImage. I have given the app full access to the photo library on the device. It will be helpful if someone could help me figure this out. My image picker:
class ViewController: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate {
var imagetobepassed: UIImage!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func Cameratapped(sender: AnyObject) {
var camera = UIImagePickerController()
dispatch_async(dispatch_get_main_queue()) {
camera.delegate = self
camera.sourceType = UIImagePickerControllerSourceType.Camera
camera.allowsEditing = false
self.presentViewController(camera, animated: true, completion: nil)
}
}
#IBAction func photolib(sender: AnyObject) {
var photo = UIImagePickerController()
dispatch_async(dispatch_get_main_queue()) {
photo.delegate = self
photo.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
photo.allowsEditing = false
self.presentViewController(photo, animated: true, completion: nil)
}
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
imagetobepassed = image
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func editorPressed(sender: AnyObject) {
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "image" {
var editorview = segue.destinationViewController as! EditorViewController
editorview.imagerecived = imagetobepassed
}
}
}
And my editor:
import UIKit
class EditorViewController: UIViewController {
var imagerecived:UIImage!
var pixeledImage:UIImage!
var savedImage:UIImage!
#IBOutlet var imageview: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
pixel()
}
// this function will prduce the pixel effect
func pixel() {
var regularImage = CIImage(image: imagerecived)
var filter = CIFilter(name: "CIPixellate")
filter.setDefaults()
filter.setValue(regularImage, forKey: kCIInputImageKey)
var output = filter.outputImage
pixeledImage = UIImage(CIImage: output)
imageview.image = pixeledImage
}
#IBAction func SaveTapped(sender: AnyObject) {
println(pixeledImage)
UIImageWriteToSavedPhotosAlbum(pixeledImage,nil,nil,nil) // not saving image
}
How can I make this work? I do see this error:
2015-05-16 23:40:05.416 Pixelate2[21579:3341726] Connection to assetsd
was interrupted or assetsd died
First use this line to save image:-
UIImageWriteToSavedPhotosAlbum(pixeledImage, self, "image:didFinishSavingWithError:contextInfo:", nil)
Now implement this method,to catch the error you are getting:-
func image(image: UIImage, didFinishSavingWithError error: NSError?, contextInfo:UnsafePointer<Void>) {
if error == nil {
}
else
{
//log the error out here ,if any
}
}
There is another work around, if you are getting memory warning !
ALAssetsLibrary* lib = [[ALAssetsLibrary alloc] init];
[lib writeImageDataToSavedPhotosAlbum:imageData metadata:nil
completionBlock:^(NSURL *assetURL, NSError *error)
{
// do whatever in the completion handler
}];
I was able to solve the issue using this code:
#IBAction func SaveTapped(sender: AnyObject) {
let softwareContext = CIContext(options: [kCIContextUseSoftwareRenderer:true])
let cgimg = softwareContext.createCGImage(savedImage,
fromRect: savedImage.extent())
let libary = ALAssetsLibrary()
libary.writeImageToSavedPhotosAlbum(cgimg, metadata: savedImage.properties(),
completionBlock: nil)
}

Capture picture automatically in IOS

My requirement is to write a sample IOS app that would automatically capture a camera picture. Using the various S.O links provided I did implement the below code -
My CameraViewController.h class is defined as follows :
#interface CameraViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
#property (strong, nonatomic) IBOutlet UIImageView *ImageView;
#end
And CameraViewController.m has the below code :
-(void)viewDidAppear:(BOOL)animated
{
NSLog(#"Setting the background now");
UIImagePickerController *picker = [[UIImagePickerController alloc] init];picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
picker.cameraDevice = UIImagePickerControllerCameraDeviceRear;
picker.showsCameraControls = NO;
picker.navigationBarHidden = NO;
picker.toolbarHidden = NO;
[self presentViewController:picker animated:YES completion:NULL];
NSLog(#"Taking the picture now");
[picker takePicture];
}
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSLog(#"Entered the case of finishing pictures");
}
- (void) imagePickerControllerDidCancel: (UIImagePickerController *) picker
{
NSLog(#"Entered the case of cancel");
}
What the above code does is successfully launch the camera app , however I am not sure if the takePicture API is able to successfully click a picture . I do not see any saved pictures in the Photos app inside my Ipad so I assume that the picture has not been clicked .
Can someone please tell me if my code above is correct or what do I need to do to automate the part of clicking the capture button once the Camera controls are displayed
[Please go to 'Using UIImagePickerController to Select Pictures and Take Photos' in the Apple documentation for the property cameraOverlayView of class UIImagePickerController for a complete example application that does what you need, and more.]
You specified your CameraViewController as adopting the UIImagePickerControllerDelegate protocol and thus you must implement two messages:
- (void) imagePickerController: (UIImagePickerController *) picker
didFinishPickingMediaWithInfo: (NSDictionary *) info;
and
- (void) imagePickerControllerDidCancel: (UIImagePickerController *) picker;
As the iOS documentation describes, the NSDictionary* info has a key UIImagePickerControllerOriginalImage which will return the UIImage. Access it as something like:
UIImage *snapshot = (UIImage *) [info objectForKey: UIImagePickerControllerOriginalImage];
Since your plan is to take a picture automatically (w/o user interaction) using takePicture then be sure to specify
picker.showsCameraControls = NO;
You need to implement the UIImagePIckerControllerDelegate's imagePickerController:didFinishPickingMediaWithInfo: method.
After that, look inside the mediaInfo dictionary and there's a UIImage inside it you can use.
I know this is old, but a better alternative to using a timer (see the comments from the accepted answer) would be to implement the completion handler instead of passing in NULL.
[self presentViewController:picker animated:YES completion:^{
NSLog(#"Taking the picture now");
[picker takePicture];
}];
That way, the picture is taken consistently every time, and you don't waste time adding an unnecessary delay.
**You can auto capturing both camera image and video recording by use this code.**
import UIKit
import AVFoundation
import MobileCoreServices
class ViewController: UIViewController, UIGestureRecognizerDelegate {
let captureSession = AVCaptureSession()
var captureDevice : AVCaptureDevice?
var imagePicker = UIImagePickerController()
var flagVideoRecording = false
var arrImages = [UIImage]()
var countVideoRecording = 0
var labelTime = UILabel()
var timer: Timer?
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(actionRepeatCapturing), name: .AVCaptureSessionDidStartRunning, object: nil)
}
#objc func actionRepeatCapturing() {
flagVideoRecording = false
startCapturingBothImageAndRecordView()
}
//MARK:- UIButton's Action
#IBAction func actionCaptureImage(_ sender: UIButton) {
flagVideoRecording = false
if AVCaptureDevice.authorizationStatus(for: AVMediaType.video) == AVAuthorizationStatus.authorized {
startCapturingBothImageAndRecordView()
} else {
AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler: { (granted: Bool) -> Void in
if granted == true {
self.startCapturingBothImageAndRecordView()
} else {
DispatchQueue.main.async {
self.alertToEncourageAccessInitially("Camera access required for capturing photos!", actionTitle: "Allow Camera")
}
}
})
}
}
#IBAction func actionCaptureVideo(_ sender: UIButton) {
flagVideoRecording = true
if AVCaptureDevice.authorizationStatus(for: AVMediaType.video) == AVAuthorizationStatus.authorized {
switch AVAudioSession.sharedInstance().recordPermission {
case AVAudioSession.RecordPermission.granted:
self.startCapturingBothImageAndRecordView()
case AVAudioSession.RecordPermission.denied:
self.alertToEncourageAccessInitially("Microphone access required for record your voice!", actionTitle: "Allow Microphone")
case AVAudioSession.RecordPermission.undetermined:
AVAudioSession.sharedInstance().requestRecordPermission({ (granted) in
if granted {
self.startCapturingBothImageAndRecordView()
} else {
self.alertToEncourageAccessInitially("Microphone access required for record your voice!", actionTitle: "Allow Microphone")
}
})
default:
break
}
} else {
AVCaptureDevice.requestAccess(for: AVMediaType.video, completionHandler: { (granted: Bool) -> Void in
if granted == true {
switch AVAudioSession.sharedInstance().recordPermission {
case AVAudioSession.RecordPermission.granted:
self.startCapturingBothImageAndRecordView()
case AVAudioSession.RecordPermission.denied:
self.alertToEncourageAccessInitially("Microphone access required for record your voice!", actionTitle: "Allow Microphone")
case AVAudioSession.RecordPermission.undetermined:
AVAudioSession.sharedInstance().requestRecordPermission({ (granted) in
if granted {
self.startCapturingBothImageAndRecordView()
} else {
self.alertToEncourageAccessInitially("Microphone access required for record your voice!", actionTitle: "Allow Microphone")
}
})
default:
break
}
} else {
DispatchQueue.main.async {
self.alertToEncourageAccessInitially("Camera access required for record video", actionTitle: "Allow Camera")
}
}
})
}
}
}
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func startCapturingBothImageAndRecordView() {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.camera) {
debugPrint("captureVideoPressed and camera available.")
imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .camera
if flagVideoRecording {
imagePicker.mediaTypes = [kUTTypeMovie as String]
imagePicker.allowsEditing = false
imagePicker.showsCameraControls = false
let viewTime = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 40))
viewTime.backgroundColor = .black
viewTime.alpha = 0.1
labelTime = UILabel(frame: CGRect(x: self.view.frame.width/2-50, y: 10, width: 100, height: 25))
labelTime.font = UIFont.boldSystemFont(ofSize: 17)
labelTime.text = "00.00:00"
labelTime.textColor = .white
labelTime.textAlignment = .center
labelTime.backgroundColor = .red
imagePicker.view.addSubview(viewTime)
imagePicker.view.addSubview(labelTime)
self.timer = Timer.scheduledTimer(timeInterval: 1,
target: self,
selector: #selector(self.actionStopVideoRecording),
userInfo: nil,
repeats: true)
} else {
imagePicker.allowsEditing = false
imagePicker.showsCameraControls = false
}
} else {
debugPrint("Camera not available.")
}
self.present(self.imagePicker, animated: true, completion: {
if self.flagVideoRecording {
self.imagePicker.startVideoCapture()
} else {
self.imagePicker.takePicture()
}
})
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if flagVideoRecording {
if let videoFileURL = info[UIImagePickerController.InfoKey.mediaURL] as? URL {
debugPrint(videoFileURL)
// let data = try Data(contentsOf: videoFileURL, options: .mappedIfSafe)
// debugPrint(data)
}
self.dismiss(animated: true, completion: nil)
} else {
if let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage{
arrImages.append(pickedImage)
}
sleep(1)
if arrImages.count >= 5 {
self.dismiss(animated: true, completion: nil)
} else {
NotificationCenter.default.post(name: .AVCaptureSessionDidStartRunning, object: nil, userInfo: nil)
}
}
}
#objc func actionStopVideoRecording() {
countVideoRecording += 1
labelTime.text = countVideoRecording == 10 ? "00:00:\(countVideoRecording)":"00:00:0\(countVideoRecording)"
if countVideoRecording == 10 {
imagePicker.stopVideoCapture()
timer?.invalidate()
timer = nil
}
}
}
extension ViewController {
func alertToEncourageAccessInitially(_ msgString: String, actionTitle: String) {
let alert = UIAlertController(
title: "IMPORTANT",
message: msgString,
preferredStyle: UIAlertController.Style.alert
)
alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
alert.addAction(UIAlertAction(title: actionTitle, style: .destructive, handler: { (alert) -> Void in
let myUrl = URL(string: UIApplication.openSettingsURLString)!
if let url = URL(string: "\(myUrl)"), !url.absoluteString.isEmpty {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
// or outside scope use this
guard let url = URL(string: "\(myUrl)"), !url.absoluteString.isEmpty else {
return
}
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}))
present(alert, animated: true, completion: nil)
}
}

Resources