iOS自定義相機(jī)

1、首先聲明以下對象

#import//捕獲設(shè)備,通常是前置攝像頭,后置攝像頭,麥克風(fēng)(音頻輸入)@property(nonatomic,strong)AVCaptureDevice*device;//AVCaptureDeviceInput 代表輸入設(shè)備,他使用AVCaptureDevice 來初始化@property(nonatomic,strong)AVCaptureDeviceInput*input;//輸出圖片@property(nonatomic,strong)AVCaptureStillImageOutput*imageOutput;//session:由他把輸入輸出結(jié)合在一起,并開始啟動捕獲設(shè)備(攝像頭)@property(nonatomic,strong)AVCaptureSession*session;//圖像預(yù)覽層,實時顯示捕獲的圖像@property(nonatomic,strong)AVCaptureVideoPreviewLayer*previewLayer;

2、初始化各個對象

- (void)cameraDistrict{//? ? AVCaptureDevicePositionBack? 后置攝像頭//? ? AVCaptureDevicePositionFront 前置攝像頭self.device= [selfcameraWithPosition:AVCaptureDevicePositionFront];self.input= [[AVCaptureDeviceInputalloc] initWithDevice:self.deviceerror:nil];self.imageOutput= [[AVCaptureStillImageOutputalloc] init];self.session= [[AVCaptureSessionalloc] init];//? ? 拿到的圖像的大小可以自行設(shè)定//? ? AVCaptureSessionPreset320x240//? ? AVCaptureSessionPreset352x288//? ? AVCaptureSessionPreset640x480//? ? AVCaptureSessionPreset960x540//? ? AVCaptureSessionPreset1280x720//? ? AVCaptureSessionPreset1920x1080//? ? AVCaptureSessionPreset3840x2160self.session.sessionPreset=AVCaptureSessionPreset640x480;//輸入輸出設(shè)備結(jié)合if([self.sessioncanAddInput:self.input]) {? ? ? ? [self.sessionaddInput:self.input];? ? }if([self.sessioncanAddOutput:self.imageOutput]) {? ? ? ? [self.sessionaddOutput:self.imageOutput];? ? }//預(yù)覽層的生成self.previewLayer= [[AVCaptureVideoPreviewLayeralloc] initWithSession:self.session];self.previewLayer.frame=CGRectMake(0,64, SCREEN_WIDTH, SCREEN_HEIGHT-64);self.previewLayer.videoGravity=AVLayerVideoGravityResizeAspectFill;? ? [self.view.layeraddSublayer:self.previewLayer];//設(shè)備取景開始[self.sessionstartRunning];if([_device lockForConfiguration:nil]) {//自動閃光燈,if([_device isFlashModeSupported:AVCaptureFlashModeAuto]) {? ? ? ? ? ? [_device setFlashMode:AVCaptureFlashModeAuto];? ? ? ? }//自動白平衡,但是好像一直都進(jìn)不去if([_device isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeAutoWhiteBalance]) {? ? ? ? ? ? [_device setWhiteBalanceMode:AVCaptureWhiteBalanceModeAutoWhiteBalance];? ? ? ? }? ? ? ? [_device unlockForConfiguration];? ? }}

根據(jù)前后置位置拿到相應(yīng)的攝像頭:

- (AVCaptureDevice*)cameraWithPosition:(AVCaptureDevicePosition)position{NSArray*devices = [AVCaptureDevicedevicesWithMediaType:AVMediaTypeVideo];for(AVCaptureDevice*deviceindevices )if( device.position== position ){returndevice;? ? ? ? }returnnil;}

3、拍照拿到相應(yīng)圖片:

- (void)photoBtnDidClick{AVCaptureConnection*conntion = [self.imageOutputconnectionWithMediaType:AVMediaTypeVideo];if(!conntion) {NSLog(@"拍照失敗!");return;? ? ? ? ? }? ? [self.imageOutputcaptureStillImageAsynchronouslyFromConnection:conntion completionHandler:^(CMSampleBufferRef imageDataSampleBuffer,NSError*error) {if(imageDataSampleBuffer ==nil) {return;? ? ? ? ? }NSData*imageData = [AVCaptureStillImageOutputjpegStillImageNSDataRepresentation:imageDataSampleBuffer];self.image= [UIImageimageWithData:imageData];? ? ? ? [self.sessionstopRunning];? ? ? ? [self.viewaddSubview:self.cameraImageView];}

4、保存照片到相冊:

#pragma - 保存至相冊- (void)saveImageToPhotoAlbum:(UIImage*)savedImage{UIImageWriteToSavedPhotosAlbum(savedImage,self,@selector(image:didFinishSavingWithError:contextInfo:),NULL);}// 指定回調(diào)方法- (void)image: (UIImage*) image didFinishSavingWithError: (NSError*) error contextInfo: (void*) contextInfo{NSString*msg =nil;if(error !=NULL){? ? ? ? msg =@"保存圖片失敗";? ? }else{? ? ? ? msg =@"保存圖片成功";? ? }UIAlertView*alert = [[UIAlertViewalloc] initWithTitle:@"保存圖片結(jié)果提示"message:msg? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? delegate:selfcancelButtonTitle:@"確定"otherButtonTitles:nil];? ? [alert show];}

5、前后置攝像頭的切換

- (void)changeCamera{NSUIntegercameraCount = [[AVCaptureDevicedevicesWithMediaType:AVMediaTypeVideo] count];if(cameraCount >1) {NSError*error;//給攝像頭的切換添加翻轉(zhuǎn)動畫CATransition*animation = [CATransitionanimation];? ? ? ? animation.duration=.5f;? ? ? ? animation.timingFunction= [CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseInEaseOut];? ? ? ? animation.type=@"oglFlip";AVCaptureDevice*newCamera =nil;AVCaptureDeviceInput*newInput =nil;//拿到另外一個攝像頭位置AVCaptureDevicePositionposition = [[_input device] position];if(position ==AVCaptureDevicePositionFront){? ? ? ? ? ? newCamera = [selfcameraWithPosition:AVCaptureDevicePositionBack];? ? ? ? ? ? animation.subtype= kCATransitionFromLeft;//動畫翻轉(zhuǎn)方向}else{? ? ? ? ? ? newCamera = [selfcameraWithPosition:AVCaptureDevicePositionFront];? ? ? ? ? ? animation.subtype= kCATransitionFromRight;//動畫翻轉(zhuǎn)方向}//生成新的輸入newInput = [AVCaptureDeviceInputdeviceInputWithDevice:newCamera error:nil];? ? ? ? [self.previewLayeraddAnimation:animation forKey:nil];if(newInput !=nil) {? ? ? ? ? ? [self.sessionbeginConfiguration];? ? ? ? ? ? [self.sessionremoveInput:self.input];if([self.sessioncanAddInput:newInput]) {? ? ? ? ? ? ? ? [self.sessionaddInput:newInput];self.input= newInput;? ? ? ? ? ? }else{? ? ? ? ? ? ? ? [self.sessionaddInput:self.input];? ? ? ? ? ? }? ? ? ? ? ? [self.sessioncommitConfiguration];? ? ? ? }elseif(error) {NSLog(@"toggle carema failed, error = %@", error);? ? ? ? }? ? }}

6、相機(jī)的其它參數(shù)設(shè)置

//AVCaptureFlashMode? 閃光燈//AVCaptureFocusMode? 對焦//AVCaptureExposureMode? 曝光//AVCaptureWhiteBalanceMode? 白平衡//閃光燈和白平衡可以在生成相機(jī)時候設(shè)置//曝光要根據(jù)對焦點的光線狀況而決定,所以和對焦一塊寫//point為點擊的位置- (void)focusAtPoint:(CGPoint)point{CGSizesize =self.view.bounds.size;CGPointfocusPoint =CGPointMake( point.y/size.height,1-point.x/size.width);NSError*error;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];//設(shè)置對焦動畫_focusView.center= point;? ? ? ? _focusView.hidden=NO;? ? ? ? [UIViewanimateWithDuration:0.3animations:^{? ? ? ? ? ? _focusView.transform=CGAffineTransformMakeScale(1.25,1.25);? ? ? ? }completion:^(BOOLfinished) {? ? ? ? ? ? [UIViewanimateWithDuration:0.5animations:^{? ? ? ? ? ? ? ? _focusView.transform=CGAffineTransformIdentity;? ? ? ? ? ? } completion:^(BOOLfinished) {? ? ? ? ? ? ? ? _focusView.hidden=YES;? ? ? ? ? ? }];? ? ? ? }];? ? }}

7、遇到的一些坑和解決辦法

1) 前后置攝像頭的切換

前后值不能切換,各種嘗試找了半天沒找到有原因。后來發(fā)現(xiàn)我在設(shè)置圖片尺寸的時候設(shè)置為1080P [self.session canSetSessionPreset: AVCaptureSessionPreset1920x1080]? ,前置攝像頭并不支持這么大的尺寸,所以就不能切換前置攝像頭。我驗證了下 前置攝像頭最高支持720P,720P以內(nèi)可自由切換?! ‘?dāng)然也可以在前后置攝像頭切換的時候,根據(jù)前后攝像頭來設(shè)置不同的尺寸,這里不在贅述。

2)焦點位置

CGPoint focusPoint = CGPointMake( point.y /size.height ,1-point.x/size.width );

setExposurePointOfInterest:focusPoint 函數(shù)后面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)對焦和曝光

我在設(shè)置對焦是 先設(shè)置了模式setFocusMode,后設(shè)置對焦位置,就會導(dǎo)致很奇怪的現(xiàn)象,對焦位置是你上次點擊的位置。所以一定要先設(shè)置位置,再設(shè)置對焦模式。

曝光同上

8、寫在最后

附上demo:https://github.com/nanshanyi/photographDemo

常用到的基本就這么多,寫的并不完善,有什么不對的,歡迎大家批評指正,共同學(xué)習(xí)。

文/_南山憶(簡書作者)

原文鏈接:http://www.itdecent.cn/p/8b28892bae5a

著作權(quán)歸作者所有,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),并標(biāo)注“簡書作者”。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容