iOS使用视听媒体框架AVFoundation实现照片拍摄

iOS使用视听媒体框架AVFoundation实现照片拍摄,第1张

概述iOS使用视听媒体框架AVFoundation实现照片拍摄 用系统自带的视听媒体的框架,AVFoundation实现照片拍摄.相比UIKit框架(UIImagePickerController高度封装),AVFoundation框架让开发者有更大的发挥空间. 首先看一下效果图: 下面贴上核心控制器代码: #import "HWPhotoVC.h" #import <AVFoundation/AVFoundation.h> @interface HWPhotoVC () @property (nonatomic, stron ...

用系统自带的视听媒体的框架,AVFoundation实现照片拍摄。相比UIKit框架(UIImagePickerController高度封装),AVFoundation框架让开发者有更大的发挥空间。

首先看一下效果图:

下面贴上核心控制器代码:

#import "HWPhotoVC.h"#import <AVFoundation/AVFoundation.h>@interface HWPhotoVC ()@property (nonatomic,strong) AVCaptureSession *captureSession;//负责输入和输出设备之间的数据传递@property (nonatomic,strong) AVCaptureDeviceinput *captureDeviceinput;//负责从AVCaptureDevice获得输入数据@property (nonatomic,strong) AVCaptureStillimageOutput *captureStillimageOutput;//照片输出流@property (nonatomic,strong) AVCaptureVIDeoPrevIEwLayer *captureVIDeoPrevIEwLayer;//相机拍摄预览图层@property (nonatomic,weak) UIVIEw *containerVIEw;//内容视图@property (nonatomic,weak) UIImageVIEw *focusCursor;//聚焦按钮@property (nonatomic,weak) UIImageVIEw *imgVIEw;//拍摄照片@end@implementation HWPhotoVC- (voID)vIEwDIDLoad { [super vIEwDIDLoad]; self.navigationItem.Title = @"拍照"; self.vIEw.backgroundcolor = [UIcolor whitecolor]; //创建控件 [self creatControl];}- (voID)vIEwWillAppear:(BOol)animated{ [super vIEwWillAppear:animated]; //初始化信息 [self initPhotoInfo];}- (voID)vIEwDIDAppear:(BOol)animated{ [super vIEwDIDAppear:animated]; [self.captureSession startRunning];}- (voID)vIEwDIDdisappear:(BOol)animated{ [super vIEwDIDdisappear:animated]; [self.captureSession stopRunning];}- (voID)creatControl{ CGfloat btnW = 150.f; CGfloat btnH = 40.f; CGfloat marginY = 20.f; CGfloat w = [UIScreen mainScreen].bounds.size.wIDth; CGfloat h = [UIScreen mainScreen].bounds.size.height; //内容视图 CGfloat containerVIEwH = h - 64 - btnH - marginY * 3; UIVIEw *containerVIEw = [[UIVIEw alloc] initWithFrame:CGRectMake(10,64 + marginY,w - 20,containerVIEwH)]; containerVIEw.backgroundcolor = [UIcolor whitecolor]; containerVIEw.layer.borderWIDth = 1.f; containerVIEw.layer.bordercolor = [[UIcolor graycolor] CGcolor]; [self.vIEw addSubvIEw:containerVIEw]; _containerVIEw = containerVIEw; //摄像头切换按钮 CGfloat cameraSwitchBtnW = 50.f; CGfloat cameraSwitchBtnmargin = 10.f; UIbutton *cameraSwitchBtn = [[UIbutton alloc] initWithFrame:CGRectMake(containerVIEw.bounds.size.wIDth - cameraSwitchBtnW - cameraSwitchBtnmargin,64 + marginY + cameraSwitchBtnmargin,cameraSwitchBtnW,cameraSwitchBtnW)]; [cameraSwitchBtn setimage:[UIImage imagenamed:@"camera_switch"] forState:UIControlStatenormal]; [cameraSwitchBtn addTarget:self action:@selector(cameraSwitchBtnOnClick) forControlEvents:UIControlEventtouchUpInsIDe]; [self.vIEw addSubvIEw:cameraSwitchBtn]; //聚焦图片 UIImageVIEw *focusCursor = [[UIImageVIEw alloc] initWithFrame:CGRectMake(50,50,75,75)]; focusCursor.Alpha = 0; focusCursor.image = [UIImage imagenamed:@"camera_focus_red"]; [containerVIEw addSubvIEw:focusCursor]; _focusCursor = focusCursor; //拍摄照片容器 UIImageVIEw *imgVIEw = [[UIImageVIEw alloc] initWithFrame:containerVIEw.frame]; imgVIEw.hIDden = YES; imgVIEw.layer.borderWIDth = 1.f; imgVIEw.layer.bordercolor = [[UIcolor graycolor] CGcolor]; imgVIEw.contentMode = UIVIEwContentModeScaleAspectFill; imgVIEw.clipsToBounds = YES; [self.vIEw addSubvIEw:imgVIEw]; _imgVIEw = imgVIEw; //按钮 NSArray *TitleArray = @[@"拍摄照片",@"重新拍摄"]; CGfloat btnY = CGRectGetMaxY(containerVIEw.frame) + marginY; CGfloat margin = (w - btnW * TitleArray.count) / (TitleArray.count + 1); for (int i = 0; i < TitleArray.count; i++) {  CGfloat btnX = margin + (margin + btnW) * i;  UIbutton *btn = [[UIbutton alloc] initWithFrame:CGRectMake(btnX,btnY,btnW,btnH)];  btn.tag = 1000 + i;  [btn setTitle:TitleArray[i] forState:UIControlStatenormal];  btn.backgroundcolor = [UIcolor orangecolor];  btn.layer.cornerRadius = 2.0f;  btn.layer.masksToBounds = YES;  if (i == 1) {   btn.hIDden = YES;  }  [btn addTarget:self action:@selector(btnOnClick:) forControlEvents:UIControlEventtouchUpInsIDe];  [self.vIEw addSubvIEw:btn]; }}- (voID)initPhotoInfo{ //初始化会话 _captureSession = [[AVCaptureSession alloc] init]; //设置分辨率 if ([_captureSession canSetSessionPreset:AVCaptureSessionPreset1280x720]) {  _captureSession.sessionPreset = AVCaptureSessionPreset1280x720; } //获得输入设备,取得后置摄像头 AVCaptureDevice *captureDevice = [self getCameraDeviceWithposition:AVCaptureDevicepositionBack]; if (!captureDevice) {  NSLog(@"取得后置摄像头时出现问题");  return; } NSError *error = nil; //根据输入设备初始化设备输入对象,用于获得输入数据 _captureDeviceinput = [[AVCaptureDeviceinput alloc]initWithDevice:captureDevice error:&error]; if (error) {  NSLog(@"取得设备输入对象时出错,错误原因:%@",error.localizedDescription);  return; } //初始化设备输出对象,用于获得输出数据 _captureStillimageOutput = [[AVCaptureStillimageOutput alloc] init]; NSDictionary *outputSettings = @{AVVIDeoCodecKey:AVVIDeoCodecJPEG}; //输出设置 [_captureStillimageOutput setoutputSettings:outputSettings]; //将设备输入添加到会话中 if ([_captureSession canAddinput:_captureDeviceinput]) {  [_captureSession addinput:_captureDeviceinput]; } //将设备输出添加到会话中 if ([_captureSession canAddOutput:_captureStillimageOutput]) {  [_captureSession addOutput:_captureStillimageOutput]; } //创建视频预览层,用于实时展示摄像头状态 _captureVIDeoPrevIEwLayer = [[AVCaptureVIDeoPrevIEwLayer alloc] initWithSession:self.captureSession]; //摄像头方向 AVCaptureConnection *captureConnection = [self.captureVIDeoPrevIEwLayer connection]; captureConnection.vIDeoOrIEntation = AVCaptureVIDeoOrIEntationPortrait; CALayer *layer = _containerVIEw.layer; layer.masksToBounds = YES; _captureVIDeoPrevIEwLayer.frame = layer.bounds; //填充模式 _captureVIDeoPrevIEwLayer.vIDeoGravity = AVLayerVIDeoGravityResizeAspectFill; //将视频预览层添加到界面中 [layer insertSublayer:_captureVIDeoPrevIEwLayer below:self.focusCursor.layer]; [self addNotificationToCaptureDevice:captureDevice]; [self addGenstureRecognizer];}- (voID)btnOnClick:(UIbutton *)btn{ if (btn.tag == 1000) {  //拍摄照片  [self photoBtnOnClick]; }else if (btn.tag == 1001) {  //重新拍摄  [self resetPhoto]; }}#pragma mark 拍照- (voID)photoBtnOnClick{ //根据设备输出获得连接 AVCaptureConnection *captureConnection = [self.captureStillimageOutput connectionWithMediaType:AVMediaTypeVIDeo]; captureConnection.vIDeoOrIEntation = AVCaptureVIDeoOrIEntationPortrait; //根据连接取得设备输出的数据 [self.captureStillimageOutput captureStillimageAsynchronouslyFromConnection:captureConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer,NSError *error) {  if (imageDataSampleBuffer) {   NSData *imageData = [AVCaptureStillimageOutput jpegStillimageNSDataRepresentation:imageDataSampleBuffer];   UIImage *image = [UIImage imageWithData:imageData];   _imgVIEw.image = image;   _imgVIEw.hIDden = NO;  } }]; UIbutton *btn = (UIbutton *)[self.vIEw vIEwWithTag:1001]; btn.hIDden = NO;}//重新拍摄- (voID)resetPhoto{ _imgVIEw.hIDden = YES; UIbutton *btn = (UIbutton *)[self.vIEw vIEwWithTag:1001]; btn.hIDden = YES;}#pragma mark - 通知//给输入设备添加通知- (voID)addNotificationToCaptureDevice:(AVCaptureDevice *)captureDevice{ //注意添加区域改变捕获通知必须首先设置设备允许捕获 [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {  captureDevice.subjectAreaChangeMonitoringEnabled = YES; }]; //捕获区域发生改变 [[NSNotificationCenter defaultCenter] addobserver:self selector:@selector(areaChange:) name:AVCaptureDeviceSubjectAreaDIDChangeNotification object:captureDevice];}- (voID)removeNotificationFromCaptureDevice:(AVCaptureDevice *)captureDevice{ [[NSNotificationCenter defaultCenter] removeObserver:self name:AVCaptureDeviceSubjectAreaDIDChangeNotification object:captureDevice];}//移除所有通知- (voID)removeNotification{ [[NSNotificationCenter defaultCenter] removeObserver:self];}//设备连接成功- (voID)deviceConnected:(NSNotification *)notification{ NSLog(@"设备已连接...");}//设备连接断开- (voID)devicedisconnected:(NSNotification *)notification{ NSLog(@"设备已断开.");}//捕获区域改变- (voID)areaChange:(NSNotification *)notification{ NSLog(@"捕获区域改变...");}#pragma mark - 私有方法//取得指定位置的摄像头- (AVCaptureDevice *)getCameraDeviceWithposition:(AVCaptureDeviceposition )position{ NSArray *cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVIDeo]; for (AVCaptureDevice *camera in cameras) {  if ([camera position] == position) {   return camera;  } } return nil;}#pragma mark 切换前后摄像头- (voID)cameraSwitchBtnOnClick{ AVCaptureDevice *currentDevice = [self.captureDeviceinput device]; AVCaptureDeviceposition currentposition = [currentDevice position]; [self removeNotificationFromCaptureDevice:currentDevice]; AVCaptureDevice *tochangeDevice; AVCaptureDeviceposition tochangeposition = AVCaptureDevicepositionFront; if (currentposition == AVCaptureDevicepositionUnspecifIEd || currentposition == AVCaptureDevicepositionFront) {  tochangeposition = AVCaptureDevicepositionBack; } tochangeDevice = [self getCameraDeviceWithposition:tochangeposition]; [self addNotificationToCaptureDevice:tochangeDevice]; //获得要调整的设备输入对象 AVCaptureDeviceinput *tochangeDeviceinput = [[AVCaptureDeviceinput alloc] initWithDevice:tochangeDevice error:nil]; //改变会话的配置前一定要先开启配置,配置完成后提交配置改变 [self.captureSession beginConfiguration]; //移除原有输入对象 [self.captureSession removeinput:self.captureDeviceinput]; //添加新的输入对象 if ([self.captureSession canAddinput:tochangeDeviceinput]) {  [self.captureSession addinput:tochangeDeviceinput];  self.captureDeviceinput = tochangeDeviceinput; } //提交会话配置 [self.captureSession commitConfiguration];}//改变设备属性的统一 *** 作方法- (voID)changeDeviceProperty:(voID (^)(AVCaptureDevice *))propertyChange{ AVCaptureDevice *captureDevice = [self.captureDeviceinput device]; NSError *error; //注意改变设备属性前一定要首先调用lockForConfiguration:调用完之后使用unlockForConfiguration方法解锁 if ([captureDevice lockForConfiguration:&error]) {  propertyChange(captureDevice);  [captureDevice unlockForConfiguration]; }else {  NSLog(@"设置设备属性过程发生错误,错误信息:%@",error.localizedDescription); }}//设置闪光灯模式- (voID)setFlashMode:(AVCaptureFlashMode)flashMode{ [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {  if ([captureDevice isFlashModeSupported:flashMode]) {   [captureDevice setFlashMode:flashMode];  } }];}//设置聚焦模式- (voID)setFocusMode:(AVCaptureFocusMode)focusMode{ [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {  if ([captureDevice isFocusModeSupported:focusMode]) {   [captureDevice setFocusMode:focusMode];  } }];}//设置曝光模式- (voID)setExposureMode:(AVCaptureExposureMode)exposureMode{ [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {  if ([captureDevice isExposureModeSupported:exposureMode]) {   [captureDevice setExposureMode:exposureMode];  } }];}//设置聚焦点- (voID)focusWithMode:(AVCaptureFocusMode)focusMode exposureMode:(AVCaptureExposureMode)exposureMode atPoint:(CGPoint)point{ [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {  if ([captureDevice isFocusModeSupported:focusMode]) {   [captureDevice setFocusMode:AVCaptureFocusModeautoFocus];  }  if ([captureDevice isFocusPointOfInterestSupported]) {   [captureDevice setFocusPointOfInterest:point];  }  if ([captureDevice isExposureModeSupported:exposureMode]) {   [captureDevice setExposureMode:AVCaptureExposureModeautoExpose];  }  if ([captureDevice isExposurePointOfInterestSupported]) {   [captureDevice setExposurePointOfInterest:point];  } }];}//添加点按手势,点按时聚焦- (voID)addGenstureRecognizer{ [self.containerVIEw addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapScreen:)]];}- (voID)tapScreen:(UITapGestureRecognizer *)tapGesture{ CGPoint point = [tapGesture locationInVIEw:self.containerVIEw]; //将UI坐标转化为摄像头坐标 CGPoint cameraPoint = [self.captureVIDeoPrevIEwLayer captureDevicePointOfInterestForPoint:point]; [self setFocusCursorWithPoint:point]; [self focusWithMode:AVCaptureFocusModeautoFocus exposureMode:AVCaptureExposureModeautoExpose atPoint:cameraPoint];}//设置聚焦光标位置- (voID)setFocusCursorWithPoint:(CGPoint)point{ self.focusCursor.center = point; self.focusCursor.transform = CGAffinetransformMakeScale(1.5,1.5); self.focusCursor.Alpha = 1.0; [UIVIEw animateWithDuration:1.0 animations:^{  self.focusCursor.transform = CGAffinetransformIDentity; } completion:^(BOol finished) {  self.focusCursor.Alpha = 0; }];}- (voID)dealloc{ [self removeNotification];}@end

Demo下载链接

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

总结

以上是内存溢出为你收集整理的iOS使用视听媒体框架AVFoundation实现照片拍摄全部内容,希望文章能够帮你解决iOS使用视听媒体框架AVFoundation实现照片拍摄所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/web/1108008.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-29
下一篇 2022-05-29

发表评论

登录后才能评论

评论列表(0条)

保存