iOS taking photo programmatically

前端 未结 5 2009
执笔经年
执笔经年 2020-11-28 07:44

I know this is possible, saw this in some apps (iGotYa is I believe the most famous). I know how to set up everything for taking photos, saving it and everything. But how ca

相关标签:
5条回答
  • 2020-11-28 08:08

    This is very simple, just use the AVFoundation reference guide:

    https://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/04_MediaCapture.html

    If you don't want the user to see the preview input you can just skip the set preview layer part of the code.

    Edit: To be more detailed.

    1)You set your capture configuration using the AVFoundation.

    • Set the camera input to frontal, turn off flash etc etc.

    2)You SKIP the part where the video preview layer is set.

    3)You call the captureStillImageAsynchronouslyFromConnection:completionHandler: method whenever you want the picture to be taken.

    Note: If you want the flash to not be heard and such then you might be violating the user rights in some countries (japan for example). One workaround I know of to do so is by capturing a frame of a video (does not trigger flash).

    0 讨论(0)
  • 2020-11-28 08:08

    You can also do it without AVFoundation and it is in my opinion an easier way to implement it using only the UIImagePickerController. There are 3 conditions:

    1. Obviously the device needs to have a camera
    2. You must hide the camera controls
    3. Then simply use the takePicture method from UIImagePickerController

    Below is a simple example that you woul typically trigger after a button push

    - (IBAction)takePhoto:(id)sender 
    {
        UIImagePickerController *picker = [[UIImagePickerController alloc] init];
        picker.delegate = self;
        picker.sourceType = UIImagePickerControllerSourceTypeCamera;
        picker.cameraDevice = UIImagePickerControllerCameraDeviceFront;
        picker.showsCameraControls = NO;
        [self presentViewController:picker animated:YES
                         completion:^ {
                             [picker takePicture];
                         }];
    }
    
    0 讨论(0)
  • 2020-11-28 08:17

    Swift 5.2

    For reference https://gist.github.com/hadanischal/33054429b18287c12ed4f4b8d45a1701

    Info.plist

    <key>NSCameraUsageDescription</key>
    <string>Access camera</string>
    <key>NSPhotoLibraryUsageDescription</key>
    <string>Access PhotoLibrary</string>
    

    AVFoundationHelper

    import AVFoundation
    
    enum CameraStatus {
        case notDetermined
        case restricted
        case denied
        case authorized
    }
    
    protocol AVFoundationHelperProtocol: AnyObject {
        // MARK: - Check and Respond to Camera Authorization Status
    
        var authorizationStatus: CameraStatus { get }
    
        // MARK: - Request Camera Permission
    
        func requestAccess(completionHandler handler: @escaping (Bool) -> Void)
    }
    
    final class AVFoundationHelper: AVFoundationHelperProtocol {
        // MARK: - Check and Respond to Camera Authorization Status
    
        var authorizationStatus: CameraStatus {
            let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
            switch cameraAuthorizationStatus {
            case .notDetermined:
                return CameraStatus.notDetermined
            case .authorized:
                return CameraStatus.authorized
            case .restricted:
                return CameraStatus.restricted
            case .denied:
                return CameraStatus.denied
            @unknown default:
                return CameraStatus.notDetermined
            }
        }
    
        // MARK: - Request Camera Permission
    
        func requestAccess(completionHandler handler: @escaping (Bool) -> Void) {
            AVCaptureDevice.requestAccess(for: .video, completionHandler: { accessGranted in
                handler(accessGranted)
            })
        }
    }
    

    ViewController

    import UIKit
    
    final class ViewController: UIViewController {
        @IBOutlet var cameraAccessButton: UIButton!
        @IBOutlet var photoImageView: UIImageView!
    
        private var model: AVFoundationHelperProtocol = AVFoundationHelper()
    
        override func viewDidLoad() {
            super.viewDidLoad()
        }
    
        @IBAction func cameraButtonPressed(_: Any) {
            let status = model.authorizationStatus
            switch status {
            case .notDetermined:
                model.requestAccess { hasAccess in
                    if hasAccess {
                        DispatchQueue.main.async {
                            self.showCameraReader()
                        }
                    } else {
                        self.alertCameraAccessNeeded()
                    }
                }
            case .restricted, .denied:
                alertCameraAccessNeeded()
    
            case .authorized:
                showCameraReader()
            }
        }
    
        private func alertCameraAccessNeeded() {
            let appName = "This app Name"
    
            let alert = UIAlertController(title: "This feature requires Camera Access",
                                          message: "In iPhone settings, tap \(appName) and turn on Camera access",
                                          preferredStyle: UIAlertController.Style.alert)
    
            let actionSettings = UIAlertAction(title: "Settings", style: .default, handler: { _ -> Void in
                guard let settingsAppURL = URL(string: UIApplication.openSettingsURLString) else { return }
                UIApplication.shared.open(settingsAppURL)
            })
    
            let actionCancel = UIAlertAction(title: "Cancel", style: .destructive, handler: { _ -> Void in
            })
    
            alert.addAction(actionSettings)
            alert.addAction(actionCancel)
    
            present(alert, animated: true, completion: nil)
        }
    }
    
    extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
        private func showCameraReader() {
            if UIImagePickerController.isSourceTypeAvailable(.camera) {
                let imagePicker = UIImagePickerController()
                imagePicker.sourceType = .camera
                imagePicker.allowsEditing = true
                imagePicker.delegate = self
                present(imagePicker, animated: true)
    
            } else if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
                let imagePicker = UIImagePickerController()
                imagePicker.sourceType = .photoLibrary
                imagePicker.allowsEditing = true
                imagePicker.delegate = self
                present(imagePicker, animated: true)
    
            } else {
                // TODO: Implement proper alert
                alertCameraAccessNeeded()
            }
        }
    
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
            picker.dismiss(animated: true)
    
            guard let image = info[.editedImage] as? UIImage else {
                print("No image found")
                return
            }
            photoImageView.image = image
            // print out the image size as a test
            print(image.size)
        }
    }
    

    Objective C

    In .h file

    @interface ABCViewController : UIViewController
    
    @property (strong, nonatomic) IBOutlet UIImageView *imageView;
    
    - (IBAction)takePhoto:  (UIButton *)sender;
    - (IBAction)selectPhoto:(UIButton *)sender;
    
    @end
    

    In .m file

    @interface ABCViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
    
    - (IBAction)takePhoto:(UIButton *)sender {
    
    
    if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
        
            UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:@"Error"
                                                            message:@"Device has no camera"
                                                            delegate:nil
                                                            cancelButtonTitle:@"OK"
                                                            otherButtonTitles: nil];
            
            [myAlertView show];
            
        } else {
        
        UIImagePickerController *picker = [[UIImagePickerController alloc] init];
        picker.delegate = self;
        picker.allowsEditing = YES;
        picker.sourceType = UIImagePickerControllerSourceTypeCamera;
        
        [self presentViewController:picker animated:YES completion:NULL];
    
    }
        
    }
    
    - (IBAction)selectPhoto:(UIButton *)sender {
        
        UIImagePickerController *picker = [[UIImagePickerController alloc] init];
        picker.delegate = self;
        picker.allowsEditing = YES;
        picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        
        [self presentViewController:picker animated:YES completion:NULL];
    
        
    }
    
    - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
        
        UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
        self.imageView.image = chosenImage;
        
        [picker dismissViewControllerAnimated:YES completion:NULL];
        
    }
    
    
    - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    
        [picker dismissViewControllerAnimated:YES completion:NULL];
        
    }
    
    0 讨论(0)
  • 2020-11-28 08:20

    VLBCameraView is a library that uses AVFoundation to take photo.

    A preview is shown in the view, which you can then call the method VLBCameraView#takePicture programmatically to take a photo.

    Comes with CocoaPods.

    0 讨论(0)
  • 2020-11-28 08:24

    Here is the code for Objective -C Custom Camera. You can add features, buttons according to your wish.

    #import "CustomCameraVC.h"
    
    @interface CustomCameraVC ()  {
        BOOL frontCamera;
    }
    @property (strong,nonatomic) AVCaptureSession *captureSession;
    @property (strong,nonatomic) AVCaptureStillImageOutput *stillImageOutput;
    @property (strong,nonatomic) AVCaptureVideoPreviewLayer *videoPreviewLayer;
    @property (weak, nonatomic) IBOutlet UIView *viewCamera;
    
    
    @end
    
    @implementation CustomCameraVC
    
    - (void)viewDidLoad {
        [super viewDidLoad];        
    }
    
    -(void)viewWillAppear:(BOOL)animated  {
        [super viewWillAppear:YES];
        frontCamera = NO;
        [self showCameraWithFrontCamera:frontCamera];
    
    }
    
    -(void)showCameraWithFrontCamera:(BOOL)flag {
        self.captureSession = [[AVCaptureSession alloc]init];
        self.captureSession.sessionPreset = AVCaptureSessionPresetPhoto;
        AVCaptureDevice *captureDevice;
        if(flag)  {
          captureDevice= [self frontCamera];
        }
        else {
          captureDevice= [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        }
        NSError *error = nil;
        AVCaptureDeviceInput *input =   [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
    
        [self.captureSession addInput:input];
        self.stillImageOutput = [AVCaptureStillImageOutput new];
        self.stillImageOutput.outputSettings = @{AVVideoCodecKey:AVVideoCodecJPEG};
        [self.captureSession addOutput:_stillImageOutput];
        self.videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
    
        self.videoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
        self.videoPreviewLayer.connection.videoOrientation = AVCaptureVideoOrientationPortrait;
        [self.viewCamera.layer addSublayer:self.videoPreviewLayer];
        [self.captureSession startRunning];
        self.videoPreviewLayer.frame = self.viewCamera.bounds;
    }
    
    
    - (AVCaptureDevice *)frontCamera {
        NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
        for (AVCaptureDevice *device in devices) {
            if ([device position] == AVCaptureDevicePositionFront) {
                return device;
            }
        }
        return nil;
    }
    
    
    - (IBAction)btnCaptureImagePressed:(id)sender {
    
         AVCaptureConnection * videoConnection =  [_stillImageOutput connectionWithMediaType:AVMediaTypeVideo];
    
        [_stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef  _Nullable sampleBuffer, NSError * _Nullable error) {
           NSData *imageData =  [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:sampleBuffer];
            UIImage *image = [[UIImage alloc]initWithData: imageData];
            UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
        }];
    
    }
    
    @end
    
    0 讨论(0)
提交回复
热议问题