iOS中 自定义系统相机

简介:
需要框架:

#import <AVFoundation/AVFoundation.h>

#import <AssetsLibrary/AssetsLibrary.h>

布局如下:


相关属性:

[objc]  view plain  copy
  1. #import "ViewController.h"  
  2. #import <AVFoundation/AVFoundation.h>  
  3. #import <AssetsLibrary/AssetsLibrary.h>  
  4. typedef void(^PropertyChangeBlock)(AVCaptureDevice *captureDevice);  
  5.   
  6. @interface ViewController ()  
  7.   
  8. @property (strong,nonatomicAVCaptureSession *captureSession;//负责输入和输出设置之间的数据传递  
  9. @property (strong,nonatomicAVCaptureDeviceInput *captureDeviceInput;//负责从AVCaptureDevice获得输入数据  
  10. @property (strong,nonatomicAVCaptureStillImageOutput *captureStillImageOutput;//照片输出流  
  11. @property (strong,nonatomicAVCaptureVideoPreviewLayer *captureVideoPreviewLayer;//相机拍摄预览图层  
  12. @property (weak, nonatomic) IBOutlet UIView *viewContainer;  
  13. @property (weak, nonatomic) IBOutlet UIButton *takeButton;//拍照按钮  
  14. @property (weak, nonatomic) IBOutlet UIButton *flashAutoButton;//自动闪光灯按钮  
  15. @property (weak, nonatomic) IBOutlet UIButton *flashOnButton;//打开闪光灯按钮  
  16. @property (weak, nonatomic) IBOutlet UIButton *flashOffButton;//关闭闪光灯按钮  
  17. @property (weak, nonatomic) IBOutlet UIImageView *focusCursor; //聚焦光标  
  18.   
  19.   
  20.   
  21. @end  
  22.   
  23. @implementation ViewController  


[objc]  view plain  copy
  1. #pragma mark - 控制器视图方法  
  2. - (void)viewDidLoad {  
  3.     [super viewDidLoad];  
  4.       
  5. }  
  6.   
  7. -(void)viewWillAppear:(BOOL)animated{  
  8.     [super viewWillAppear:animated];  
  9.     //初始化会话  
  10.     _captureSession=[[AVCaptureSession alloc]init];  
  11.     if ([_captureSession canSetSessionPreset:AVCaptureSessionPreset1280x720]) {//设置分辨率  
  12.         _captureSession.sessionPreset=AVCaptureSessionPreset1280x720;  
  13.     }  
  14.     //获得输入设备  
  15.     AVCaptureDevice *captureDevice=[self getCameraDeviceWithPosition:AVCaptureDevicePositionBack];//取得后置摄像头  
  16.     if (!captureDevice) {  
  17.         NSLog(@"取得后置摄像头时出现问题.");  
  18.         return;  
  19.     }  
  20.       
  21.     NSError *error=nil;  
  22.     //根据输入设备初始化设备输入对象,用于获得输入数据  
  23.     _captureDeviceInput=[[AVCaptureDeviceInput alloc]initWithDevice:captureDevice error:&error];  
  24.     if (error) {  
  25.         NSLog(@"取得设备输入对象时出错,错误原因:%@",error.localizedDescription);  
  26.         return;  
  27.     }  
  28.     //初始化设备输出对象,用于获得输出数据  
  29.     _captureStillImageOutput=[[AVCaptureStillImageOutput alloc]init];  
  30.     NSDictionary *outputSettings = @{AVVideoCodecKey:AVVideoCodecJPEG};  
  31.     [_captureStillImageOutput setOutputSettings:outputSettings];//输出设置  
  32.       
  33.     //将设备输入添加到会话中  
  34.     if ([_captureSession canAddInput:_captureDeviceInput]) {  
  35.         [_captureSession addInput:_captureDeviceInput];  
  36.     }  
  37.       
  38.     //将设备输出添加到会话中  
  39.     if ([_captureSession canAddOutput:_captureStillImageOutput]) {  
  40.         [_captureSession addOutput:_captureStillImageOutput];  
  41.     }  
  42.       
  43.     //创建视频预览层,用于实时展示摄像头状态  
  44.     _captureVideoPreviewLayer=[[AVCaptureVideoPreviewLayer alloc]initWithSession:self.captureSession];  
  45.       
  46.     CALayer *layer=self.viewContainer.layer;  
  47.     layer.masksToBounds=YES;  
  48.       
  49.     _captureVideoPreviewLayer.frame=layer.bounds;  
  50.     _captureVideoPreviewLayer.videoGravity=AVLayerVideoGravityResizeAspectFill;//填充模式  
  51.     //将视频预览层添加到界面中  
  52.     //[layer addSublayer:_captureVideoPreviewLayer];  
  53.     [layer insertSublayer:_captureVideoPreviewLayer below:self.focusCursor.layer];  
  54.       
  55.     [self addNotificationToCaptureDevice:captureDevice];  
  56.     [self addGenstureRecognizer];  
  57.     [self setFlashModeButtonStatus];  
  58. }  
  59.   
  60. -(void)viewDidAppear:(BOOL)animated{  
  61.     [super viewDidAppear:animated];  
  62.     [self.captureSession startRunning];  
  63. }  
  64.   
  65. -(void)viewDidDisappear:(BOOL)animated{  
  66.     [super viewDidDisappear:animated];  
  67.     [self.captureSession stopRunning];  
  68. }  
  69.   
  70. -(void)dealloc{  
  71.     [self removeNotification];  
  72. }  

[objc]  view plain  copy
  1. #pragma mark - UI方法  
  2. #pragma mark 拍照  
  3. - (IBAction)takeButtonClick:(UIButton *)sender {  
  4.     //根据设备输出获得连接  
  5.     AVCaptureConnection *captureConnection=[self.captureStillImageOutput connectionWithMediaType:AVMediaTypeVideo];  
  6.     //根据连接取得设备输出的数据  
  7.     [self.captureStillImageOutput captureStillImageAsynchronouslyFromConnection:captureConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {  
  8.         if (imageDataSampleBuffer) {  
  9.             NSData *imageData=[AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];  
  10.             UIImage *image=[UIImage imageWithData:imageData];  
  11.             UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);  
  12. //            ALAssetsLibrary *assetsLibrary=[[ALAssetsLibrary alloc]init];  
  13. //            [assetsLibrary writeImageToSavedPhotosAlbum:[image CGImage] orientation:(ALAssetOrientation)[image imageOrientation] completionBlock:nil];  
  14.         }  
  15.           
  16.     }];  
  17. }  
  18. #pragma mark 切换前后摄像头  
  19. - (IBAction)toggleButtonClick:(UIButton *)sender {  
  20.     AVCaptureDevice *currentDevice=[self.captureDeviceInput device];  
  21.     AVCaptureDevicePosition currentPosition=[currentDevice position];  
  22.     [self removeNotificationFromCaptureDevice:currentDevice];  
  23.     AVCaptureDevice *toChangeDevice;  
  24.     AVCaptureDevicePosition toChangePosition=AVCaptureDevicePositionFront;  
  25.     if (currentPosition==AVCaptureDevicePositionUnspecified||currentPosition==AVCaptureDevicePositionFront) {  
  26.         toChangePosition=AVCaptureDevicePositionBack;  
  27.     }  
  28.     toChangeDevice=[self getCameraDeviceWithPosition:toChangePosition];  
  29.     [self addNotificationToCaptureDevice:toChangeDevice];  
  30.     //获得要调整的设备输入对象  
  31.     AVCaptureDeviceInput *toChangeDeviceInput=[[AVCaptureDeviceInput alloc]initWithDevice:toChangeDevice error:nil];  
  32.       
  33.     //改变会话的配置前一定要先开启配置,配置完成后提交配置改变  
  34.     [self.captureSession beginConfiguration];  
  35.     //移除原有输入对象  
  36.     [self.captureSession removeInput:self.captureDeviceInput];  
  37.     //添加新的输入对象  
  38.     if ([self.captureSession canAddInput:toChangeDeviceInput]) {  
  39.         [self.captureSession addInput:toChangeDeviceInput];  
  40.         self.captureDeviceInput=toChangeDeviceInput;  
  41.     }  
  42.     //提交会话配置  
  43.     [self.captureSession commitConfiguration];  
  44.       
  45.     [self setFlashModeButtonStatus];  
  46. }  

[objc]  view plain  copy
  1. #pragma mark 自动闪光灯开启  
  2. - (IBAction)flashAutoClick:(UIButton *)sender {  
  3.     [self setFlashMode:AVCaptureFlashModeAuto];  
  4.     [self setFlashModeButtonStatus];  
  5. }  

[objc]  view plain  copy
  1. #pragma mark 打开闪光灯  
  2. - (IBAction)flashOnClick:(UIButton *)sender {  
  3.     [self setFlashMode:AVCaptureFlashModeOn];  
  4.     [self setFlashModeButtonStatus];  
  5. }  

[objc]  view plain  copy
  1. #pragma mark 关闭闪光灯  
  2. - (IBAction)flashOffClick:(UIButton *)sender {  
  3.     [self setFlashMode:AVCaptureFlashModeOff];  
  4.     [self setFlashModeButtonStatus];  
  5. }  

[objc]  view plain  copy
  1. #pragma mark - 通知  
  2. /** 
  3.  *  给输入设备添加通知 
  4.  */  
  5. -(void)addNotificationToCaptureDevice:(AVCaptureDevice *)captureDevice{  
  6.     //注意添加区域改变捕获通知必须首先设置设备允许捕获  
  7.     [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {  
  8.         captureDevice.subjectAreaChangeMonitoringEnabled=YES;  
  9.     }];  
  10.     NSNotificationCenter *notificationCenter= [NSNotificationCenter defaultCenter];  
  11.     //捕获区域发生改变  
  12.     [notificationCenter addObserver:self selector:@selector(areaChange:) name:AVCaptureDeviceSubjectAreaDidChangeNotification object:captureDevice];  
  13. }  

[objc]  view plain  copy
  1. /** 
  2.  *  移除所有通知 
  3.  */  
  4. -(void)removeNotification{  
  5.     NSNotificationCenter *notificationCenter= [NSNotificationCenter defaultCenter];  
  6.     [notificationCenter removeObserver:self];  
  7. }  

[objc]  view plain  copy
  1. -(void)addNotificationToCaptureSession:(AVCaptureSession *)captureSession{  
  2.     NSNotificationCenter *notificationCenter= [NSNotificationCenter defaultCenter];  
  3.     //会话出错  
  4.     [notificationCenter addObserver:self selector:@selector(sessionRuntimeError:) name:AVCaptureSessionRuntimeErrorNotification object:captureSession];  
  5. }  

[objc]  view plain  copy
  1. /** 
  2.  *  设备连接成功 
  3.  * 
  4.  *  @param notification 通知对象 
  5.  */  
  6. -(void)deviceConnected:(NSNotification *)notification{  
  7.     NSLog(@"设备已连接...");  
  8. }  

[objc]  view plain  copy
  1. /** 
  2.  *  设备连接断开 
  3.  * 
  4.  *  @param notification 通知对象 
  5.  */  
  6. -(void)deviceDisconnected:(NSNotification *)notification{  
  7.     NSLog(@"设备已断开.");  
  8. }  

[objc]  view plain  copy
  1. /** 
  2.  *  捕获区域改变 
  3.  * 
  4.  *  @param notification 通知对象 
  5.  */  
  6. -(void)areaChange:(NSNotification *)notification{  
  7.     NSLog(@"捕获区域改变...");  
  8. }  

[objc]  view plain  copy
  1. /** 
  2.  *  会话出错 
  3.  * 
  4.  *  @param notification 通知对象 
  5.  */  
  6. -(void)sessionRuntimeError:(NSNotification *)notification{  
  7.     NSLog(@"会话发生错误.");  
  8. }  

[objc]  view plain  copy
  1. #pragma mark - 私有方法  
  2.   
  3. /** 
  4.  *  取得指定位置的摄像头 
  5.  * 
  6.  *  @param position 摄像头位置 
  7.  * 
  8.  *  @return 摄像头设备 
  9.  */  
  10. -(AVCaptureDevice *)getCameraDeviceWithPosition:(AVCaptureDevicePosition )position{  
  11.     NSArray *cameras= [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];  
  12.     for (AVCaptureDevice *camera in cameras) {  
  13.         if ([camera position]==position) {  
  14.             return camera;  
  15.         }  
  16.     }  
  17.     return nil;  
  18. }  

[objc]  view plain  copy
  1. /** 
  2.  *  改变设备属性的统一操作方法 
  3.  * 
  4.  *  @param propertyChange 属性改变操作 
  5.  */  
  6. -(void)changeDeviceProperty:(PropertyChangeBlock)propertyChange{  
  7.     AVCaptureDevice *captureDevice= [self.captureDeviceInput device];  
  8.     NSError *error;  
  9.     //注意改变设备属性前一定要首先调用lockForConfiguration:调用完之后使用unlockForConfiguration方法解锁  
  10.     if ([captureDevice lockForConfiguration:&error]) {  
  11.         propertyChange(captureDevice);  
  12.         [captureDevice unlockForConfiguration];  
  13.     }else{  
  14.         NSLog(@"设置设备属性过程发生错误,错误信息:%@",error.localizedDescription);  
  15.     }  
  16. }  

[objc]  view plain  copy
  1. /** 
  2.  *  设置闪光灯模式 
  3.  * 
  4.  *  @param flashMode 闪光灯模式 
  5.  */  
  6. -(void)setFlashMode:(AVCaptureFlashMode )flashMode{  
  7.     [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {  
  8.         if ([captureDevice isFlashModeSupported:flashMode]) {  
  9.             [captureDevice setFlashMode:flashMode];  
  10.         }  
  11.     }];  
  12. }  

[objc]  view plain  copy
  1. /** 
  2.  *  设置聚焦模式 
  3.  * 
  4.  *  @param focusMode 聚焦模式 
  5.  */  
  6. -(void)setFocusMode:(AVCaptureFocusMode )focusMode{  
  7.     [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {  
  8.         if ([captureDevice isFocusModeSupported:focusMode]) {  
  9.             [captureDevice setFocusMode:focusMode];  
  10.         }  
  11.     }];  
  12. }  

[objc]  view plain  copy
  1. /** 
  2.  *  设置曝光模式 
  3.  * 
  4.  *  @param exposureMode 曝光模式 
  5.  */  
  6. -(void)setExposureMode:(AVCaptureExposureMode)exposureMode{  
  7.     [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {  
  8.         if ([captureDevice isExposureModeSupported:exposureMode]) {  
  9.             [captureDevice setExposureMode:exposureMode];  
  10.         }  
  11.     }];  
  12. }  

[objc]  view plain  copy
  1. /** 
  2.  *  设置聚焦点 
  3.  * 
  4.  *  @param point 聚焦点 
  5.  */  
  6. -(void)focusWithMode:(AVCaptureFocusMode)focusMode exposureMode:(AVCaptureExposureMode)exposureMode atPoint:(CGPoint)point{  
  7.     [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {  
  8.         if ([captureDevice isFocusModeSupported:focusMode]) {  
  9.             [captureDevice setFocusMode:AVCaptureFocusModeAutoFocus];  
  10.         }  
  11.         if ([captureDevice isFocusPointOfInterestSupported]) {  
  12.             [captureDevice setFocusPointOfInterest:point];  
  13.         }  
  14.         if ([captureDevice isExposureModeSupported:exposureMode]) {  
  15.             [captureDevice setExposureMode:AVCaptureExposureModeAutoExpose];  
  16.         }  
  17.         if ([captureDevice isExposurePointOfInterestSupported]) {  
  18.             [captureDevice setExposurePointOfInterest:point];  
  19.         }  
  20.     }];  
  21. }  

[objc]  view plain  copy
  1. /** 
  2.  *  添加点按手势,点按时聚焦 
  3.  */  
  4. -(void)addGenstureRecognizer{  
  5.     UITapGestureRecognizer *tapGesture=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapScreen:)];  
  6.     [self.viewContainer addGestureRecognizer:tapGesture];  
  7. }  
  8. -(void)tapScreen:(UITapGestureRecognizer *)tapGesture{  
  9.     CGPoint point= [tapGesture locationInView:self.viewContainer];  
  10.     //将UI坐标转化为摄像头坐标  
  11.     CGPoint cameraPoint= [self.captureVideoPreviewLayer captureDevicePointOfInterestForPoint:point];  
  12.     [self setFocusCursorWithPoint:point];  
  13.     [self focusWithMode:AVCaptureFocusModeAutoFocus exposureMode:AVCaptureExposureModeAutoExpose atPoint:cameraPoint];  
  14. }  

[objc]  view plain  copy
  1. /** 
  2.  *  设置闪光灯按钮状态 
  3.  */  
  4. -(void)setFlashModeButtonStatus{  
  5.     AVCaptureDevice *captureDevice=[self.captureDeviceInput device];  
  6.     AVCaptureFlashMode flashMode=captureDevice.flashMode;  
  7.     if([captureDevice isFlashAvailable]){  
  8.         self.flashAutoButton.hidden=NO;  
  9.         self.flashOnButton.hidden=NO;  
  10.         self.flashOffButton.hidden=NO;  
  11.         self.flashAutoButton.enabled=YES;  
  12.         self.flashOnButton.enabled=YES;  
  13.         self.flashOffButton.enabled=YES;  
  14.         switch (flashMode) {  
  15.             case AVCaptureFlashModeAuto:  
  16.                 self.flashAutoButton.enabled=NO;  
  17.                 break;  
  18.             case AVCaptureFlashModeOn:  
  19.                 self.flashOnButton.enabled=NO;  
  20.                 break;  
  21.             case AVCaptureFlashModeOff:  
  22.                 self.flashOffButton.enabled=NO;  
  23.                 break;  
  24.             default:  
  25.                 break;  
  26.         }  
  27.     }else{  
  28.         self.flashAutoButton.hidden=YES;  
  29.         self.flashOnButton.hidden=YES;  
  30.         self.flashOffButton.hidden=YES;  
  31.     }  
  32. }  

[objc]  view plain  copy
  1. /** 
  2.  *  设置聚焦光标位置 
  3.  * 
  4.  *  @param point 光标位置 
  5.  */  
  6. -(void)setFocusCursorWithPoint:(CGPoint)point{  
  7.     self.focusCursor.center=point;  
  8.     self.focusCursor.transform=CGAffineTransformMakeScale(1.51.5);  
  9.     self.focusCursor.alpha=1.0;  
  10.     [UIView animateWithDuration:1.0 animations:^{  
  11.         self.focusCursor.transform=CGAffineTransformIdentity;  
  12.     } completion:^(BOOL finished) {  
  13.         self.focusCursor.alpha=0;  
  14.           
  15.     }];  

关注博主微博每日更新技术:http://weibo.com/hanjunqiang

原文地址:http://blog.csdn.net/qq_31810357/article/details/49942327
相关文章
|
2月前
|
安全 Android开发 数据安全/隐私保护
深入探讨iOS与Android系统安全性对比分析
在移动操作系统领域,iOS和Android无疑是两大巨头。本文从技术角度出发,对这两个系统的架构、安全机制以及用户隐私保护等方面进行了详细的比较分析。通过深入探讨,我们旨在揭示两个系统在安全性方面的差异,并为用户提供一些实用的安全建议。
|
2月前
|
安全 Android开发 数据安全/隐私保护
深入探索Android与iOS系统安全性的对比分析
在当今数字化时代,移动操作系统的安全已成为用户和开发者共同关注的重点。本文旨在通过比较Android与iOS两大主流操作系统在安全性方面的差异,揭示两者在设计理念、权限管理、应用审核机制等方面的不同之处。我们将探讨这些差异如何影响用户的安全体验以及可能带来的风险。
88 21
|
2月前
|
传感器 iOS开发 UED
探索iOS生态系统:从App Store优化到用户体验提升
本文旨在深入探讨iOS生态系统的多个方面,特别是如何通过App Store优化(ASO)和改进用户体验来提升应用的市场表现。不同于常规摘要仅概述文章内容的方式,我们将直接进入主题,首先介绍ASO的重要性及其对开发者的意义;接着分析当前iOS平台上用户行为的变化趋势以及这些变化如何影响应用程序的设计思路;最后提出几点实用建议帮助开发者更好地适应市场环境,增强自身竞争力。
|
2月前
|
安全 Android开发 iOS开发
深入探讨Android与iOS系统的差异及未来发展趋势
本文旨在深入分析Android和iOS两大移动操作系统的核心技术差异、用户体验以及各自的市场表现,进一步探讨它们在未来技术革新中可能的发展方向。通过对比两者的开放性、安全性、生态系统等方面,本文揭示了两大系统在移动设备市场中的竞争态势和潜在变革。
|
2月前
|
存储 安全 算法
深入探索iOS系统安全机制:保护用户隐私的前沿技术
本文旨在探讨苹果公司在其广受欢迎的iOS操作系统中实施的先进安全措施,这些措施如何共同作用以保护用户的隐私和数据安全。我们将深入了解iOS的安全架构,包括其硬件和软件层面的创新,以及苹果如何通过持续的软件更新来应对新兴的安全威胁。此外,我们还将讨论iOS系统中的一些关键安全功能,如Face ID、加密技术和沙箱环境,以及它们如何帮助防止未经授权的访问和数据泄露。
|
2月前
|
安全 数据安全/隐私保护 Android开发
深入探索iOS系统安全机制:从基础到高级
本文旨在全面解析iOS操作系统的安全特性,从基础的权限管理到高级的加密技术,揭示苹果如何构建一个既开放又安全的移动平台。我们将通过实例和分析,探讨iOS系统如何保护用户数据免受恶意软件、网络攻击的威胁,并对比Android系统在安全性方面的差异。
|
2月前
|
安全 搜索推荐 Android开发
揭秘安卓与iOS系统的差异:技术深度对比
【10月更文挑战第27天】 本文深入探讨了安卓(Android)与iOS两大移动操作系统的技术特点和用户体验差异。通过对比两者的系统架构、应用生态、用户界面、安全性等方面,揭示了为何这两种系统能够在市场中各占一席之地,并为用户提供不同的选择。文章旨在为读者提供一个全面的视角,理解两种系统的优势与局限,从而更好地根据自己的需求做出选择。
166 2
|
2月前
|
Swift iOS开发 UED
如何使用Swift和UIKit在iOS应用中实现自定义按钮动画
本文通过一个具体案例,介绍如何使用Swift和UIKit在iOS应用中实现自定义按钮动画。当用户点击按钮时,按钮将从圆形变为椭圆形,颜色从蓝色渐变到绿色;释放按钮时,动画以相反方式恢复。通过UIView的动画方法和弹簧动画效果,实现平滑自然的过渡。
81 1
|
3月前
|
安全 搜索推荐 Android开发
揭秘iOS与Android系统的差异:一场技术与哲学的较量
在当今数字化时代,智能手机操作系统的选择成为了用户个性化表达和技术偏好的重要标志。iOS和Android,作为市场上两大主流操作系统,它们之间的竞争不仅仅是技术的比拼,更是设计理念、用户体验和生态系统构建的全面较量。本文将深入探讨iOS与Android在系统架构、应用生态、用户界面及安全性等方面的本质区别,揭示这两种系统背后的哲学思想和市场策略,帮助读者更全面地理解两者的优劣,从而做出更适合自己的选择。
|
2月前
|
安全 Android开发 iOS开发
深入探索iOS与Android系统的差异性及优化策略
在当今数字化时代,移动操作系统的竞争尤为激烈,其中iOS和Android作为市场上的两大巨头,各自拥有庞大的用户基础和独特的技术特点。本文旨在通过对比分析iOS与Android的核心差异,探讨各自的优势与局限,并提出针对性的优化策略,以期为用户提供更优质的使用体验和为开发者提供有价值的参考。

热门文章

最新文章