iOS自定义相机

来源:互联网 发布:sql server入门经典 编辑:程序博客网 时间:2024/05/22 08:19

  最近公司的项目中用到了相机,由于不用系统的相机,UI给的相机切图,必须自定义才可以。就花时间简单研究了一下相机的自定义。
  相机属于系统硬件,这就需要我们来手动调用iPhone的相机硬件,分为以下步骤:

2016-03-30 上午9.51.09.png
1、首先声明以下对象

#import <AVFoundation/AVFoundation.h>//捕获设备,通常是前置摄像头,后置摄像头,麦克风(音频输入)@property (nonatomic, strong) AVCaptureDevice *device;//AVCaptureDeviceInput 代表输入设备,他使用AVCaptureDevice 来初始化@property (nonatomic, strong) AVCaptureDeviceInput *input;//输出图片@property (nonatomic ,strong) AVCaptureStillImageOutput *imageOutput;//session:由他把输入输出结合在一起,并开始启动捕获设备(摄像头)@property (nonatomic, strong) AVCaptureSession *session;//图像预览层,实时显示捕获的图像@property (nonatomic ,strong) AVCaptureVideoPreviewLayer *previewLayer;

2、初始化各个对象

- (void)cameraDistrict{//    AVCaptureDevicePositionBack  后置摄像头//    AVCaptureDevicePositionFront 前置摄像头   self.device = [self cameraWithPosition:AVCaptureDevicePositionFront];    self.input = [[AVCaptureDeviceInput alloc] initWithDevice:self.device error:nil];    self.imageOutput = [[AVCaptureStillImageOutput alloc] init];    self.session = [[AVCaptureSession alloc] init];    //     拿到的图像的大小可以自行设定    //    AVCaptureSessionPreset320x240    //    AVCaptureSessionPreset352x288    //    AVCaptureSessionPreset640x480    //    AVCaptureSessionPreset960x540    //    AVCaptureSessionPreset1280x720    //    AVCaptureSessionPreset1920x1080    //    AVCaptureSessionPreset3840x2160    self.session.sessionPreset = AVCaptureSessionPreset640x480;    //输入输出设备结合    if ([self.session canAddInput:self.input]) {        [self.session addInput:self.input];    }    if ([self.session canAddOutput:self.imageOutput]) {        [self.session addOutput:self.imageOutput];    }    //预览层的生成    self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];    self.previewLayer.frame = CGRectMake(0, 64, SCREEN_WIDTH, SCREEN_HEIGHT-64);    self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;    [self.view.layer addSublayer:self.previewLayer];    //设备取景开始    [self.session startRunning];    if ([_device lockForConfiguration:nil]) {    //自动闪光灯,        if ([_device isFlashModeSupported:AVCaptureFlashModeAuto]) {            [_device setFlashMode:AVCaptureFlashModeAuto];        }        //自动白平衡,但是好像一直都进不去        if ([_device isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeAutoWhiteBalance]) {            [_device setWhiteBalanceMode:AVCaptureWhiteBalanceModeAutoWhiteBalance];        }        [_device unlockForConfiguration];    }}

根据前后置位置拿到相应的摄像头:

- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position{    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];    for ( AVCaptureDevice *device in devices )        if ( device.position == position ){            return device;        }    return nil;}3、拍照拿到相应图片:- (void)photoBtnDidClick{    AVCaptureConnection *conntion = [self.imageOutput connectionWithMediaType:AVMediaTypeVideo];      if (!conntion) {          NSLog(@"拍照失败!");          return;          }    [self.imageOutput captureStillImageAsynchronouslyFromConnection:conntion completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {        if (imageDataSampleBuffer == nil) {            return ;          }        NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];        self.image = [UIImage imageWithData:imageData];        [self.session stopRunning];        [self.view addSubview:self.cameraImageView];}

4、保存照片到相册:

#pragma - 保存至相册- (void)saveImageToPhotoAlbum:(UIImage*)savedImage{    UIImageWriteToSavedPhotosAlbum(savedImage, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL);}// 指定回调方法- (void)image: (UIImage *) image didFinishSavingWithError: (NSError *) error contextInfo: (void *) contextInfo{    NSString *msg = nil ;    if(error != NULL){        msg = @"保存图片失败" ;    }else{        msg = @"保存图片成功" ;    }    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"保存图片结果提示"                                            message:msg                                            delegate:self                                          cancelButtonTitle:@"确定"                                          otherButtonTitles:nil];    [alert show];}

5、前后置摄像头的切换

- (void)changeCamera{    NSUInteger cameraCount = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count];    if (cameraCount > 1) {        NSError *error;        //给摄像头的切换添加翻转动画        CATransition *animation = [CATransition animation];        animation.duration = .5f;        animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];        animation.type = @"oglFlip";        AVCaptureDevice *newCamera = nil;        AVCaptureDeviceInput *newInput = nil;  //拿到另外一个摄像头位置        AVCaptureDevicePosition position = [[_input device] position];        if (position == AVCaptureDevicePositionFront){            newCamera = [self cameraWithPosition:AVCaptureDevicePositionBack];            animation.subtype = kCATransitionFromLeft;//动画翻转方向        }        else {            newCamera = [self cameraWithPosition:AVCaptureDevicePositionFront];            animation.subtype = kCATransitionFromRight;//动画翻转方向        }        //生成新的输入        newInput = [AVCaptureDeviceInput deviceInputWithDevice:newCamera error:nil];        [self.previewLayer addAnimation:animation forKey:nil];        if (newInput != nil) {            [self.session beginConfiguration];            [self.session removeInput:self.input];            if ([self.session canAddInput:newInput]) {                [self.session addInput:newInput];                self.input = newInput;            } else {                [self.session addInput:self.input];            }            [self.session commitConfiguration];        } else if (error) {            NSLog(@"toggle carema failed, error = %@", error);        }    }}

6、相机的其它参数设置

//AVCaptureFlashMode  闪光灯//AVCaptureFocusMode  对焦//AVCaptureExposureMode  曝光//AVCaptureWhiteBalanceMode  白平衡//闪光灯和白平衡可以在生成相机时候设置//曝光要根据对焦点的光线状况而决定,所以和对焦一块写//point为点击的位置- (void)focusAtPoint:(CGPoint)point{    CGSize size = self.view.bounds.size;    CGPoint focusPoint = CGPointMake( point.y /size.height ,1-point.x/size.width );    NSError *error;    if ([self.device lockForConfiguration:&error]) {        //对焦模式和对焦点        if ([self.device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {            [self.device setFocusPointOfInterest:focusPoint];            [self.device setFocusMode:AVCaptureFocusModeAutoFocus];        }        //曝光模式和曝光点        if ([self.device isExposureModeSupported:AVCaptureExposureModeAutoExpose ]) {            [self.device setExposurePointOfInterest:focusPoint];            [self.device setExposureMode:AVCaptureExposureModeAutoExpose];        }        [self.device unlockForConfiguration];        //设置对焦动画        _focusView.center = point;        _focusView.hidden = NO;        [UIView animateWithDuration:0.3 animations:^{            _focusView.transform = CGAffineTransformMakeScale(1.25, 1.25);        }completion:^(BOOL finished) {            [UIView animateWithDuration:0.5 animations:^{                _focusView.transform = CGAffineTransformIdentity;            } completion:^(BOOL finished) {                _focusView.hidden = YES;            }];        }];    }}

7、遇到的一些坑和解决办法
1) 前后置摄像头的切换

  前后值不能切换,各种尝试找了半天没找到有原因。后来发现我在设置图片尺寸的时候设置为1080P [self.session canSetSessionPreset: AVCaptureSessionPreset1920x1080] ,前置摄像头并不支持这么大的尺寸,所以就不能切换前置摄像头。我验证了下 前置摄像头最高支持720P,720P以内可自由切换。  当然也可以在前后置摄像头切换的时候,根据前后摄像头来设置不同的尺寸,这里不在赘述。
2)焦点位置

  CGPoint focusPoint = CGPointMake( point.y /size.height ,1-point.x/size.width );
setExposurePointOfInterest:focusPoint 函数后面Point取值范围是取景框左上角(0,0)到取景框右下角(1,1)之间。官方是这么写的:
  The value of this property is a CGPoint that determines the receiver’s focus point of interest, if it has one. A value of (0,0) indicates that the camera should focus on the top left corner of the image, while a value of (1,1) indicates that it should focus on the bottom right. The default value is (0.5,0.5).
  我也试了按这个来但位置就是不对,只能按上面的写法才可以。前面是点击位置的y/PreviewLayer的高度,后面是1-点击位置的x/PreviewLayer的宽度
3)对焦和曝光

  我在设置对焦是 先设置了模式setFocusMode,后设置对焦位置,就会导致很奇怪的现象,对焦位置是你上次点击的位置。所以一定要先设置位置,再设置对焦模式。
  曝光同上
8、写在最后

  附上demo:https://github.com/nanshanyi/photographDemo
  常用到的基本就这么多,写的并不完善,有什么不对的,欢迎大家批评指正,共同学习。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机无法显示百度视频的视频怎么办 如果微信被盗号朋友钱被骗怎么办 绑定银行卡的电话号码换了怎么办办 银行卡绑定的手机号空号了怎么办 微信提示绑定银行卡次数超限怎么办 手机卡太久没用被注销了怎么办 电信宽带欠费缴费后上不了网怎么办 电信宽带欠费后缴费连不上网怎么办 电脑开不了机屏亮但不开机怎么办 手机信息探探链接点开了怎么办 买的钻戒的票丢掉了怎么办 如果我过户了原来的积分怎么办? 英雄联盟安装到了一半卡住了怎么办 微信登录不上怎么办一直在转圈 lol老是忘了放装备技能怎么办 英雄联盟屏幕出现红框锁定了怎么办 钢三开局修改对电脑有用怎么办 我的世界为什么一直黑屏闪退怎么办 苹果6plus玩游戏闪退怎么办 电脑重置开机黑屏了怎么办才好? 龟头有一小块和鱼鳞一样脱皮怎么办 海盗来了赠送碎片密码忘了怎么办 王者荣耀还差几百金币买英雄怎么办 英雄联盟更新后画面突然很卡怎么办 苹果手机微信登陆没反应怎么办 谷歌商店注册短信一直验证怎么办 英雄联盟开游戏退出来进不去怎么办 忘记了路由器和网关的密码怎么办 逆战无尽塔防71关没怪了怎么办 看香的师傅要钱特别多怎么办 电商企业有收入支出没发票怎么办 洗衣液没稀释把衣服染褪色了怎么办 衣服被洗衣液洗褪色了怎么办 b站不小心点了差评怎么办 c盘文件目录损坏且无法读取怎么办 打印发票时发票上的字体变大怎么办 淘宝店铺食品违法遇到打假人怎么办 搜狗输入法说我没有权限安装怎么办 申请移民美国期间护照到期了怎么办 自己申请的qq号账号忘了怎么办 苹果手机下完游戏找不到在哪怎么办