很常

iOS调用相机无感抓拍

2021-03-24  本文已影响0人  倪大头

UIImagePickerController虽然有takePicture方法,但会弹出拍照界面,直接用AVCaptureDevice调用摄像头就可以进行无感抓拍

导入AVFoundation框架

#import <AVFoundation/AVFoundation.h>

需要的几个类:

// 摄像头
@property (nonatomic, strong) AVCaptureDevice *device;

// 输入
@property (nonatomic, strong) AVCaptureDeviceInput *input;

// 输出图片
@property (nonatomic, strong) AVCaptureStillImageOutput *imgOutput;

// session
@property (nonatomic, strong) AVCaptureSession *session;

用AVCaptureSession启动采集设备AVCaptureDevice拍照并输出图片AVCaptureStillImageOutput

初始化采集设备,这里我调用的前置摄像头:

self.device = [self getCameraWithPosition:AVCaptureDevicePositionFront];

获取摄像头的方法:

- (AVCaptureDevice *)getCameraWithPosition:(AVCaptureDevicePosition)position {
    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for (AVCaptureDevice *device in devices) {
        if (device.position == position) {
            return device;
        }
    }
    return nil;
}

初始化输入类:

self.input = [[AVCaptureDeviceInput alloc]initWithDevice:self.device error:nil];

初始化图片输出类:

self.imgOutput = [[AVCaptureStillImageOutput alloc]init];

初始化session:

self.session = [[AVCaptureSession alloc]init];
// 获取的图片大小
self.session.sessionPreset = AVCaptureSessionPreset1280x720;
// 绑定输入输出类
if ([self.session canAddInput:self.input]) {
    [self.session addInput:self.input];
}
if ([self.session canAddOutput:self.imgOutput]) {
    [self.session addOutput:self.imgOutput];
}

关闭闪光灯:

if ([self.device lockForConfiguration:nil]) {
    // 关闭闪光灯
    self.device.flashMode = AVCaptureFlashModeOff;
    [self.device unlockForConfiguration];
}

开始采集:

// 开始采集
[self.session startRunning];

拍照:

AVCaptureConnection *connection = [self.imgOutput connectionWithMediaType:AVMediaTypeVideo];
if (connection) {
    [self.imgOutput captureStillImageAsynchronouslyFromConnection:connection completionHandler:^(CMSampleBufferRef  _Nullable imageDataSampleBuffer, NSError * _Nullable error) {
        if (imageDataSampleBuffer) {
            NSData *imgData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
            UIImage *image = [UIImage imageWithData:imgData];
            self.imageView.image = image;
        }
    }];
}

停止采集:

if ([self.session isRunning]) {
    [self.session stopRunning];
}

完整代码:

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>

@interface ViewController ()

// 摄像头
@property (nonatomic, strong) AVCaptureDevice *device;

// 输入
@property (nonatomic, strong) AVCaptureDeviceInput *input;

// 输出图片
@property (nonatomic, strong) AVCaptureStillImageOutput *imgOutput;

// session
@property (nonatomic, strong) AVCaptureSession *session;

// 图片展示
@property (nonatomic, strong) UIImageView *imageView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.backgroundColor = UIColor.whiteColor;
    
    [self configCamera];
    [self initSubviews];
}

- (void)configCamera {
    self.device = [self getCameraWithPosition:AVCaptureDevicePositionFront];
    self.input = [[AVCaptureDeviceInput alloc]initWithDevice:self.device error:nil];
    
    self.imgOutput = [[AVCaptureStillImageOutput alloc]init];
    
    self.session = [[AVCaptureSession alloc]init];
    // 获取的图片大小
    self.session.sessionPreset = AVCaptureSessionPreset1280x720;
    if ([self.session canAddInput:self.input]) {
        [self.session addInput:self.input];
    }
    if ([self.session canAddOutput:self.imgOutput]) {
        [self.session addOutput:self.imgOutput];
    }
    
    if ([self.device lockForConfiguration:nil]) {
        // 关闭闪光灯
        self.device.flashMode = AVCaptureFlashModeOff;
        [self.device unlockForConfiguration];
    }
    
    // 开始采集
    [self.session startRunning];
}

- (AVCaptureDevice *)getCameraWithPosition:(AVCaptureDevicePosition)position {
    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for (AVCaptureDevice *device in devices) {
        if (device.position == position) {
            return device;
        }
    }
    return nil;
}

- (void)initSubviews {
    UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(50, 100, 290, 50)];
    button.backgroundColor = UIColor.blueColor;
    [button setTitle:@"拍照" forState:UIControlStateNormal];
    [button setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
    [self.view addSubview:button];
    [button addTarget:self action:@selector(takePhoto) forControlEvents:UIControlEventTouchUpInside];
    
    self.imageView = [[UIImageView alloc]initWithFrame:CGRectMake(50, CGRectGetMaxY(button.frame) + 50, 290, 300)];
    self.imageView.contentMode = UIViewContentModeScaleAspectFill;
    self.imageView.clipsToBounds = YES;
    [self.view addSubview:self.imageView];
}

// 拍照
- (void)takePhoto {
    AVCaptureConnection *connection = [self.imgOutput connectionWithMediaType:AVMediaTypeVideo];
    if (connection) {
        [self.imgOutput captureStillImageAsynchronouslyFromConnection:connection completionHandler:^(CMSampleBufferRef  _Nullable imageDataSampleBuffer, NSError * _Nullable error) {
            if (imageDataSampleBuffer) {
                NSData *imgData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
                UIImage *image = [UIImage imageWithData:imgData];
                self.imageView.image = image;
            }
        }];
    }
}

- (void)dealloc {
    if ([self.session isRunning]) {
        [self.session stopRunning];
    }
}

@end
上一篇下一篇

猜你喜欢

热点阅读