#import <AVFoundation/AVFoundation.h> //基于这个框架
#import <AssetsLibrary/AssetsLibrary.h> //用于写入相册
@interface ViewController ()<UIGestureRecognizerDelegate>
{
UIButton *_takePhotoBtn; //拍照
UIButton *_flashBtn; //闪光灯
UIButton *_switchCameraBtn; //切换摄像头
}
@property(nonatomic)dispatch_queue_t sessionQueue;
@property(nonatomic,strong)AVCaptureSession *session; //传递
@property(nonatomic,strong)AVCaptureDeviceInput *videoInput;
@property(nonatomic,strong)AVCaptureStillImageOutput *stillImageOut;
@property(nonatomic,strong)AVCaptureVideoPreviewLayer *previewLayer;
@property(nonatomic,assign)CGFloat beginGestureScale;
@property(nonatomic,assign)CGFloat effectiveScale;
@property(nonatomic,assign)BOOL isUsingFrontFacingCamera;
@end
@implementation ViewController
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.session startRunning];
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[self.session stopRunning];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor];
[self createUI];
[self initAVCaptureSession];
[self setUpGesture];
_isUsingFrontFacingCamera = NO;
self.effectiveScale = self.beginGestureScale = 1.0f;
}
- (void)createUI{
_takePhotoBtn = [[UIButton alloc]initWithFrame:CGRectMake(20, 20, 80, 35)];
_takePhotoBtn.backgroundColor = [UIColor redColor];
[_takePhotoBtn setTitle:@"拍照" forState:UIControlStateNormal];
[_takePhotoBtn addTarget:self action:@selector(takePhotoBtnClick:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_takePhotoBtn];
_flashBtn = [[UIButton alloc]initWithFrame:CGRectMake(20 + 80 + 20, 20, 80, 35)];
_flashBtn.backgroundColor = [UIColor redColor];
[_flashBtn setTitle:@"闪光灯" forState:UIControlStateNormal];
[_flashBtn addTarget:self action:@selector(flashBtnClick:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_flashBtn];
_switchCameraBtn = [[UIButton alloc]initWithFrame:CGRectMake(20 + 200, 20, 80, 35)];
_switchCameraBtn.backgroundColor = [UIColor redColor];
[_switchCameraBtn setTitle:@"切换" forState:UIControlStateNormal];
[_switchCameraBtn addTarget:self action:@selector(switchBtnClick:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_switchCameraBtn];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
// 这个是是否支持屏幕旋转的。
// 如果return yes,那就是支持4个屏幕方向的。
}
#pragma mark -- 初始化变量
- (void)initAVCaptureSession{
self.session = [[AVCaptureSession alloc]init];
NSError *error;
//设备
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//先锁定
[device lockForConfiguration:nil];
//闪光灯 自动
[device setFlashMode: AVCaptureFlashModeAuto];
[device unlockForConfiguration];
self.videoInput = [[AVCaptureDeviceInput alloc]initWithDevice:device error:&error];
if (error) {
NSLog(@"%@",error);
}
self.stillImageOut = [[AVCaptureStillImageOutput alloc]init];
//输出设置
NSDictionary *outputSetting = [[NSDictionary alloc]initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey, nil];
[self.stillImageOut setOutputSettings:outputSetting];
if ([self.session canAddInput:self.videoInput]) {
[self.session addInput:self.videoInput];
}
if ([self.session canAddOutput:self.stillImageOut]) {
[self.session addOutput:self.stillImageOut];
}
//预览层
self.previewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:self.session];
[self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];
self.previewLayer.frame = CGRectMake(0, 64, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 2*64);
self.view.layer.masksToBounds = YES;
[self.view.layer addSublayer:self.previewLayer];
}
#pragma mark 获取方向 的方法
- (AVCaptureVideoOrientation)avOrientationForDeviceOrientation:(UIDeviceOrientation) deviceOrientation{
AVCaptureVideoOrientation result = (AVCaptureVideoOrientation)deviceOrientation;
if (deviceOrientation == UIDeviceOrientationLandscapeLeft) {
result = AVCaptureVideoOrientationLandscapeRight;
}else if (deviceOrientation == UIDeviceOrientationLandscapeRight){
result = AVCaptureVideoOrientationLandscapeLeft;
}
return result;
}
#pragma mark --手势
- (void)setUpGesture{
UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinchGesture:)];
pinch.delegate = self;
[self.view addGestureRecognizer:pinch];
}
- (void)handlePinchGesture:(UIPinchGestureRecognizer *)recoginzer{
NSLog(@"缩放");
}
#pragma mark - 手势delegate
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
if ([gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]]) {
self.beginGestureScale = self.effectiveScale;
}
return YES;
}
#pragma mark btnClicke
#pragma mark 拍照
- (void)takePhotoBtnClick:(UIButton *)btn{
NSLog( @"拍照");
AVCaptureConnection *stillImageConnection = [self.stillImageOut connectionWithMediaType:AVMediaTypeVideo];
UIDeviceOrientation curDeviceOrientation = [[UIDevice currentDevice] orientation];
AVCaptureVideoOrientation avcaptureOrientation = [self avOrientationForDeviceOrientation:curDeviceOrientation];
[stillImageConnection setVideoOrientation: avcaptureOrientation];
[stillImageConnection setVideoScaleAndCropFactor:self.effectiveScale];
////写入相册
[self.stillImageOut captureStillImageAsynchronouslyFromConnection:stillImageConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
NSData *jpegData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
// UIImage *image = [UIImage imageWithData:jpegData];
// UIImageWriteToSavedPhotosAlbum(image, self, nil, nil); //此方法写入相册 太慢
CFDictionaryRef attachments = CMCopyDictionaryOfAttachments(kCFAllocatorDefault, imageDataSampleBuffer, kCMAttachmentMode_ShouldPropagate);
ALAuthorizationStatus author = [ALAssetsLibrary authorizationStatus];
if (author == ALAuthorizationStatusRestricted || author == ALAuthorizationStatusDenied) {
return ;
}
ALAssetsLibrary *library = [[ALAssetsLibrary alloc]init];
[library writeImageDataToSavedPhotosAlbum:jpegData metadata:(__bridge id)attachments completionBlock:^(NSURL *assetURL, NSError *error) {
}];
}];
//
}
#pragma mark 闪光灯
- (void)flashBtnClick:(UIButton *)btn{
NSLog(@"闪光灯");
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
[device lockForConfiguration:nil];
//必须先判断是否有闪光灯,否则崩溃
if ([device hasFlash]) {
if (device.flashMode == AVCaptureFlashModeOff) {
device.flashMode = AVCaptureFlashModeOn;
[btn setTitle:@"On" forState:UIControlStateNormal];
}else if (device.flashMode == AVCaptureFlashModeOn){
device.flashMode = AVCaptureFlashModeAuto;
[btn setTitle:@"Auto" forState:UIControlStateNormal];
}else if (device.flashMode == AVCaptureFlashModeAuto){
device.flashMode = AVCaptureFlashModeOff;
[btn setTitle:@"Off" forState:UIControlStateNormal];
}
}else{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"设备不支持闪光灯" preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:alert animated:YES completion:nil];
}
[device unlockForConfiguration];
}
#pragma mark 切换摄像头
- (void)switchBtnClick:(UIButton *)btn{
AVCaptureDevicePosition devicePositon;
if (_isUsingFrontFacingCamera) {
devicePositon = AVCaptureDevicePositionBack;
}else{
devicePositon = AVCaptureDevicePositionFront;
}
for (AVCaptureDevice *device in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) {
if ([device position] == devicePositon) {
[self.previewLayer.session beginConfiguration];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
for (AVCaptureInput *oldInput in self.previewLayer.session.inputs) {
[[self.previewLayer session] removeInput:oldInput];
}
[self.previewLayer.session addInput:input];
[self.previewLayer.session commitConfiguration];
break;
}
}
_isUsingFrontFacingCamera = !_isUsingFrontFacingCamera;
}