当前位置: 首页 > 科技观察

30分钟搞定iOS自定义摄像头

时间:2023-03-22 02:00:45 科技观察

最近公司在项目中使用了摄像头。由于没有使用系统相机,所以必须自定义UI给出的相机切图。刚刚抽空简单研究了一下相机的定制。摄像头属于系统硬件,需要我们手动调用iPhone的摄像头硬件,分为以下步骤:1.首先声明如下对象#import//capturedevice,通常是前置摄像头、后置摄像头Camera、麦克风(音频输入)@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=[selfcameraWithPosition:AVCaptureDevicePositionFront];self.input=[[AVCapallDevice]initWithDevice:self.deviceerror:nil];self.imageOutput=[[AVCaptureStillImageOutputalloc]init];self.session=[[AVCaptureSessionalloc]init];//获取图片的大小可以自己设置//AVCaptureSessionPreset320x240//AVCaptureSessionPreset352x288//AVCaptureSessionPreset640x480//AVCaptureSessionPreset960x540//AVCaptureSessionPreset1280x720//AVCaptureSessionPreset1920x1080//AVCaptureSessionPreset3840x2160self.session.sessionPreset=AVCaptureSessionPreset640x480;//输入输出设备连接if([self.sessioncanAddInput:self.input]){[self.sessionaddInput:self.input];}if([self.sessioncanAddOutput:self.imageOutput]){[self.sessionaddOutput:self.imageOutput];}//预览层生成self.previewLayer=[[AVCaptureVideoPreviewLayeralloc]initWithSession:self.session];自己。previewLayer.frame=CGRectMake(0,64,SCREEN_WIDTH,SCREEN_HEIGHT-64);self.previewLayer.videoGravity=AVLayerVideoGravityResizeAspectFill;[self.view.layeraddSublayer:self.previewLayer];//设备框架启动[self.sessionstartRunning];if([_devicelockForConfiguration:nil]){//自动闪光,if([_deviceisFlashModeSupported:AVCaptureFlashModeAuto]){[_devicessetFlashMode:AVCaptureFlashModeAuto];}//自动白平衡,不过好像一直进不去if([_deviceisWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeAutoWhiteBalance]){[_devicessetWhiteBalanceMode:AVCaptureWhiteBalanceModeAutoWhiteBalance];}[_deviceunlockForConfiguration];}}根据前后位置获取对应的摄像头:-(AVCaptureDevice*)cameraWithPosition:(AVCaptureDevicePosition)position{NSArray*devicesdevices=[AV:CaptureDeviceDevicePosition]position{NSArray*devicesdevices=[AV:CaptureDeviceDevices]MediaforMediaAV(AVCaptureDevice*deviceindevices)if(device.position==position){returndevice;}返回零;}3。拍照并获取对应图片:-(void)photoBtnDidClick{AVCaptureConnection*conntion=[self.imageOutputconnectionWithMediaType:AVMediaTypeVideo];if(!conntion){NSLog(@"拍照失败!");返回;}[self.imageOutputcaptureStillImageAsynchronouslyFromConnection:conntioncompletionHandler:^(CMSampleBufferRefimageDataSampleBuffer,NSError*error){if(imageDataSampleBuffer==nil){返回;imageDataSampleBuffer];self.image=[UIImageimageWithData:imageData];[self.sessionstopRunning];[self.viewaddSubview:self.cameraI法师视图];}4。前后摄像头切换-(void)changeCamera{NSUIntegercameraCount=[[AVCaptureDevicedevicesWithMediaType:AVMediaTypeVideo]count];if(cameraCount>1){NSError*错误;//给相机切换动画添加翻转动画CATransition*animation=[CATransitionanimation];animation.duration=.5f;animation.timingFunction=[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseInEaseOut];animation.type=@"oglFlip";AVCaptureDevice*newCamera=无;AVCaptureDeviceInput*newInput=nil;//获取另外一个Camera位置AVCaptureDevicePositionposition=[[_inputdevice]position];如果(位置==AVCaptureDevicePositionFront){newCamera=[selfcameraWithPosition:AVCaptureDevicePositionBack];animation.subtype=kCATransitionFromLeft;//动画翻转方向}else{newCamera=[CapselfcameraWithPosition:AV.subtype=kCATransitionFromRight;//动画翻转方向}//生成新的输入newInput=[AVCaptureDeviceInputdeviceInputWithDevice:newCameraerror:nil];[self.previewLayeraddAnimation:animationforKey:nil];如果(新输入!=nil){[self.sessionbeginConfiguration];[self.sessionremoveInput:self.input];如果([self.sessioncanAddInput:newInput]){[self.sessionaddInput:newInput];self.input=新输入;}else{[self.sessionaddInput:self.input];}[self.sessioncommitConfiguration];}elseif(error){NSLog(@"togglecaremafailed,error=%@",error);}}}5。其他相机参数设置//AVCaptureFlashModeflash//AVCaptureFocusModefocus//AVCaptureExposureModeexposure//AVCaptureWhiteBalanceModewhitebalance//闪光灯和白平衡可以在生成相机的时候设置//Exposure要根据对焦点的光线情况来决定,所以和focus一起写//点就是点击位置-(void)focusAtPoint:(CGPoint)point{CGSizesize=self.view.bounds.size;CGPointfocusPoint=CGPointMake(point.y/size.height,1-point.x/size.width);NSError*错误;if([self.devicelockForConfiguration:&error]){//对焦模式和对焦点if([self.deviceisFocusModeSupported:AVCaptureFocusModeAutoFocus]){[self.devicesetFocusPointOfInterest:focusPoint];[self.devicesetFocusMode:AVCaptureFocusModeAutoFocus];}//曝光模式和曝光点if([self.deviceisExposureModeSupported:AVCaptureExposureModeAutoExpose]){[self.devicesetExposurePointOfInterest:focusPoint];[self.devicesetExposureMode:AVCaptureExposureModeAutoExpose];}[self.deviceunlockForConfiguration];//设置焦点动画_focusView.center=point;_focusView.hidden=否;[UIViewanimateWithDuration:0.3animations:^{_focusView.transform=CGAffineTransformMakeScale(1.25,1.25);}completion:^(BOOLfinished){[UIViewanimateWithDuration:0.5animations:^{_focusView.transform=CGAffineTransformIdentity;}completion:^(BOOLfinished){_focusView.hidden=YES;}];}];}}6。遇到的一些坑及解决办法1)前后摄像头的值不能前后切换。是1080P【self.sessioncanSetSessionPreset:AVCaptureSessionPreset1920x1080】,前置摄像头不支持这么大的尺寸,所以前置摄像头无法切换。我验证了前置摄像头最高支持720P,并且可以在720P内自由切换。当然,在前后摄像头切换时,可以根据前后摄像头设置不同的尺寸,这里不再赘述。2)焦点位置CGPointfocusPoint=CGPointMake(point.y/size.height,1-point.x/size.width);setExposurePointOfInterest:focusPoint函数后面Point的取值范围是从取景器左上角(0,0)到取景器右下角之间(1,1)。官方是这样写的:这个属性的值是一个CGPoint,它决定了接收者的焦点兴趣点,如果有的话。值(0,0)表示相机应该聚焦在图像的左上角,而值(1,1)表示它应该聚焦在图像的右下角。默认值为(0.5,0.5)。我也试过按这个,但是位置不对。我只能用上面的方法。前面是点击位置y/PreviewLayer的高度,后面是1-点击位置x/PreviewLayer的宽度3)对焦和曝光我在设置焦点的时候先设置模式setFocusMode,然后再设置焦点位置,这会导致很奇怪的现象,焦点位置就是你上次点击的位置。所以一定要先设置好位置,再设置对焦方式。曝光同上7.最后附上Demo:https://github.com/nanshanyi/photographDemo基本就这么多常用的,写的也不是很完美。如有不妥之处,欢迎大家批评指正,共同学习。

最新推荐
猜你喜欢