iOS: Capture image from front facing camera

前端 未结 5 2045
耶瑟儿~
耶瑟儿~ 2020-12-01 00:56

I am making an application where I would like to capture an image from the front facing camera, without presenting a capture screen of any kind. I want to take a picture com

5条回答
  •  难免孤独
    2020-12-01 01:08

    How to capture an image using the AVFoundation front-facing camera:

    Development Caveats:

    • Check your app and image orientation settings carefully
    • AVFoundation and its associated frameworks are nasty behemoths and very difficult to understand/implement. I've made my code as lean as possible, but please check out this excellent tutorial for a better explanation (website not available any more, link via archive.org): http://www.benjaminloulier.com/posts/ios4-and-direct-access-to-the-camera

    ViewController.h

    // Frameworks
    #import 
    #import 
    #import 
    #import 
    
    @interface CameraViewController : UIViewController 
    
    // Camera
    @property (weak, nonatomic) IBOutlet UIImageView* cameraImageView;
    @property (strong, nonatomic) AVCaptureDevice* device;
    @property (strong, nonatomic) AVCaptureSession* captureSession;
    @property (strong, nonatomic) AVCaptureVideoPreviewLayer* previewLayer;
    @property (strong, nonatomic) UIImage* cameraImage;
    
    @end
    

    ViewController.m

    #import "CameraViewController.h"
    
    @implementation CameraViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        [self setupCamera];
        [self setupTimer];
    }
    
    - (void)setupCamera
    {    
        NSArray* devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
        for(AVCaptureDevice *device in devices)
        {
            if([device position] == AVCaptureDevicePositionFront)
                self.device = device;
        }
    
        AVCaptureDeviceInput* input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
        AVCaptureVideoDataOutput* output = [[AVCaptureVideoDataOutput alloc] init];
        output.alwaysDiscardsLateVideoFrames = YES;
    
        dispatch_queue_t queue;
        queue = dispatch_queue_create("cameraQueue", NULL);
        [output setSampleBufferDelegate:self queue:queue];
    
        NSString* key = (NSString *) kCVPixelBufferPixelFormatTypeKey;
        NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];
        NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];
        [output setVideoSettings:videoSettings];
    
        self.captureSession = [[AVCaptureSession alloc] init];
        [self.captureSession addInput:input];
        [self.captureSession addOutput:output];
        [self.captureSession setSessionPreset:AVCaptureSessionPresetPhoto];
    
        self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
        self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    
        // CHECK FOR YOUR APP
        self.previewLayer.frame = CGRectMake(0, 0, self.view.frame.size.height, self.view.frame.size.width);
        self.previewLayer.orientation = AVCaptureVideoOrientationLandscapeRight;
        // CHECK FOR YOUR APP
    
        [self.view.layer insertSublayer:self.previewLayer atIndex:0];   // Comment-out to hide preview layer
    
        [self.captureSession startRunning];
    }
    
    - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
    {
        CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
        CVPixelBufferLockBaseAddress(imageBuffer,0);
        uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer);
        size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
        size_t width = CVPixelBufferGetWidth(imageBuffer);
        size_t height = CVPixelBufferGetHeight(imageBuffer);
    
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
        CGImageRef newImage = CGBitmapContextCreateImage(newContext);
    
        CGContextRelease(newContext);
        CGColorSpaceRelease(colorSpace);
    
        self.cameraImage = [UIImage imageWithCGImage:newImage scale:1.0f orientation:UIImageOrientationDownMirrored];
    
        CGImageRelease(newImage);
    
        CVPixelBufferUnlockBaseAddress(imageBuffer,0);
    }
    
    - (void)setupTimer
    {
        NSTimer* cameraTimer = [NSTimer scheduledTimerWithTimeInterval:2.0f target:self selector:@selector(snapshot) userInfo:nil repeats:YES];
    }
    
    - (void)snapshot
    {
        NSLog(@"SNAPSHOT");
        self.cameraImageView.image = self.cameraImage;  // Comment-out to hide snapshot
    }
    
    @end
    

    Connect this up to a UIViewController with a UIImageView for the snapshot and it'll work! Snapshots are taken programmatically at 2.0 second intervals without any user input. Comment out the selected lines to remove the preview layer and snapshot feedback.

    Any more questions/comments, please let me know!

提交回复
热议问题