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
相关文章
|
17天前
|
开发工具 Swift 数据安全/隐私保护
移动应用开发之旅:从零到一的iOS系统探索
【9月更文挑战第16天】在数字时代的浪潮中,移动应用成为连接用户与数字世界的桥梁。本文将带你走进iOS移动操作系统的世界,了解其架构、设计理念以及开发环境。我们将通过Swift语言的简单示例,展示如何构建一个基本的iOS应用,并探讨移动应用开发的未来趋势。无论你是编程新手还是资深开发者,这篇文章都将为你提供宝贵的见解和知识。
|
10天前
|
监控 Android开发 iOS开发
深入探索安卓与iOS的系统架构差异:理解两大移动平台的技术根基在移动技术日新月异的今天,安卓和iOS作为市场上最为流行的两个操作系统,各自拥有独特的技术特性和庞大的用户基础。本文将深入探讨这两个平台的系统架构差异,揭示它们如何支撑起各自的生态系统,并影响着全球数亿用户的使用体验。
本文通过对比分析安卓和iOS的系统架构,揭示了这两个平台在设计理念、安全性、用户体验和技术生态上的根本区别。不同于常规的技术综述,本文以深入浅出的方式,带领读者理解这些差异是如何影响应用开发、用户选择和市场趋势的。通过梳理历史脉络和未来展望,本文旨在为开发者、用户以及行业分析师提供有价值的见解,帮助大家更好地把握移动技术发展的脉络。
|
2月前
|
存储 安全 编译器
我给 iOS 系统打了个补丁——修复 iOS 16 系统键盘重大 Crash
我给 iOS 系统打了个补丁——修复 iOS 16 系统键盘重大 Crash
我给 iOS 系统打了个补丁——修复 iOS 16 系统键盘重大 Crash
|
29天前
|
Swift iOS开发 UED
揭秘一款iOS应用中令人惊叹的自定义动画效果,带你领略编程艺术的魅力所在!
【9月更文挑战第5天】本文通过具体案例介绍如何在iOS应用中使用Swift与UIKit实现自定义按钮动画,当用户点击按钮时,按钮将从圆形变为椭圆形并从蓝色渐变到绿色,释放后恢复原状。文中详细展示了代码实现过程及动画平滑过渡的技巧,帮助读者提升应用的视觉体验与特色。
39 11
|
2月前
|
人工智能 自然语言处理 云计算
iOS迎来AI升级:揭秘Apple全新“智能”系统
iOS迎来AI升级:揭秘Apple全新“智能”系统
iOS迎来AI升级:揭秘Apple全新“智能”系统
|
2月前
|
Swift iOS开发 UED
【绝妙创意】颠覆你的视觉体验!揭秘一款iOS应用中令人惊叹的自定义动画效果,带你领略编程艺术的魅力所在!
【8月更文挑战第13天】本文通过一个具体案例,介绍如何使用Swift与UIKit在iOS应用中创建独特的按钮动画效果。当按钮被按下时,其形状从圆形变化为椭圆形,颜色则从蓝色渐变为绿色;释放后,动画反向恢复原状。利用UIView动画方法及弹簧动画效果,实现了平滑自然的过渡。通过调整参数,开发者可以进一步优化动画体验,增强应用的互动性和视觉吸引力。
40 7
|
2月前
|
iOS开发 开发者
iOS 16 系统键盘修复问题之汇编层面模拟两次返回操作的实现如何解决
iOS 16 系统键盘修复问题之汇编层面模拟两次返回操作的实现如何解决
|
2月前
|
存储 iOS开发
iOS 16 系统键盘修复问题之确定UIKeyboardTaskQueue类对_lock的加锁和解锁操作如何解决
iOS 16 系统键盘修复问题之确定UIKeyboardTaskQueue类对_lock的加锁和解锁操作如何解决
|
2月前
|
安全 Android开发 iOS开发
安卓与iOS的终极对决:哪个系统更适合你?
在智能手机的世界里,安卓和iOS两大操作系统如同两座巍峨的山峰,各自拥有庞大的用户群体。本文将深入浅出地探讨这两个系统的优缺点,并帮助你找到最适合自己的那一款。让我们一起揭开这场技术盛宴的序幕吧!
|
2月前
|
编译器 C语言 iOS开发
iOS 16 系统键盘修复问题之确定_lock是否用于保护对_deferredTasks的多线程读写如何解决
iOS 16 系统键盘修复问题之确定_lock是否用于保护对_deferredTasks的多线程读写如何解决