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,nonatomic) AVCaptureSession *captureSession;//负责输入和输出设置之间的数据传递  
  9. @property (strong,nonatomic) AVCaptureDeviceInput *captureDeviceInput;//负责从AVCaptureDevice获得输入数据  
  10. @property (strong,nonatomic) AVCaptureStillImageOutput *captureStillImageOutput;//照片输出流  
  11. @property (strong,nonatomic) AVCaptureVideoPreviewLayer *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.5, 1.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

时间: 2024-11-08 20:19:17

iOS中 自定义系统相机的相关文章

iOS中 自定义系统相机 作者:韩俊强

需要框架: #import <AVFoundation/AVFoundation.h> #import <AssetsLibrary/AssetsLibrary.h> 布局如下: 相关属性: #import "ViewController.h" #import <AVFoundation/AVFoundation.h> #import <AssetsLibrary/AssetsLibrary.h> typedef void(^Proper

iOS中获取系统相册中的图片实例_IOS

本文介绍了iOS中获取系统相册中的图片,在很多应用中都能用到,可以获取单张图片,也可以同时获取多张图片,废话不多说了,看下面吧. 一.获取单张图片 思路: 1.利用UIImagePickerController可以从系统自带的App(照片\相机)中获得图片 2.设置代理,遵守代理协议 注意这个UIImagePickerController类比较特殊,需要遵守两个代理协议 @interface ViewController () <UIImagePickerControllerDelegate,

设计iOS中随系统键盘弹收和内容文字长度自适应高度的文本框

设计iOS中随系统键盘弹收和内容文字长度自适应高度的文本框     文本输入框是多数与社交相关的app中不可或缺的一个控件,这些文本输入框应该具备如下的功能: 1.在键盘为弹起时,输入框悬浮在界面底部. 2.当键盘弹起时,输入框位置上移至键盘上方,并且动画应与键盘同步. 3.当输入的文字超出一行时,输入框应想用的进行高度扩展. 4.当输入框的高度达到某一极限值时,输入框高度不应继续扩展,文字区域应该支持滑动.     使用autolayout布局技术加上对键盘的相关监听,可以十分方便的实现上述效

IOS中调用系统拨打电话与发送短信

IOS中调用系统拨打电话发送短信 一.调用打电话界面 [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"tel://%@",_phoneNumber]]]; 二.发送短消息界面 调用系统的发送短信的界面,需要引入以下头文件: #import <MessageUI/MessageUI.h> 系统短信界面的调用很简单,只需下面几句代码: ? 1

android-Fragment中调用系统相机拍照获取照片后跳转问题,求大神···急急急··

问题描述 Fragment中调用系统相机拍照获取照片后跳转问题,求大神···急急急·· 在Fragment中调用系统相机拍照获取照片后,先跳到前一个activity或者桌面,然后再回到调用相机的Activity,这是啥原因呢?急急急·······在线等,求大神帮忙··· 解决方案 http://download.csdn.net/detail/zhai56565/5094196 解决方案二: 转来的··调用系统相机拍照和调用相册

详解ios中自定义cell,自定义UITableViewCell_IOS

通过继承UITableViewCell来自定义cell 1.创建一个空的项目.命名: 2.创建一个UITableViewController 并且同时创建xib: 3.设置AppDelegate.m中window的根控制器为刚刚创建的TableViewController: - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { s

iOS中 自定义cell分割线/分割线偏移 韩俊强的博客

在项目开发中我们会常常遇到tableView 的cell分割线显示不全,左边会空出一截像素,更有甚者想改变系统的分割线,并且只要上下分割线的一个等等需求,今天重点解决以上需求,仅供参考: 1.cell 分割线不全: 解决方案1: 补全分割线 -(void)viewDidLayoutSubviews { if ([_listTableView respondsToSelector:@selector(setSeparatorInset:)]) { [_listTableView setSepara

iOS中 自定义cell升级版 (高级)

接上次分享的自定义cell进行了优化:http://blog.csdn.net/qq_31810357/article/details/49611255 指定根视图: [objc] view plain copy self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[RootTableViewController alloc] initWithStyle:UITa

代码-android关于调用系统相机拍照后APP闪退的问题

问题描述 android关于调用系统相机拍照后APP闪退的问题 最近在写一个小APP,就是调用系统相机拍照,然后保存在本地相册,代码没有显示bug,但是在调试时出现了拍照后闪退的问题,我的测试机是小米2S,MIUI 7系统,android5.0.X的,拍照的照片能保存在本地,但是在拍照后点击确定后软件就闪退了,这是我的代码 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState)