iOS自定義相機功能
大多數(shù)app都會涉及到上傳照片這個功能,圖片來源無非是從相冊獲取或者相機拍攝。如果不是特別要求,調(diào)用系統(tǒng)已經(jīng)滿足需求。但對于特殊需求,就需要自定義相機拍攝界面了。
對于無需定制的相機,使用系統(tǒng)的UIKit庫里的UIImagePickerController類,幾行代碼,幾個代理方法就可滿足所需。但如果要深度定制,就要系統(tǒng)庫AVFoundation內(nèi)部的相關(guān)類。
創(chuàng)建自己的相機管理類CameraManager(繼承于NSObject)
.h文件
#import <Foundation/Foundation.h> #import <AVFoundation/AVFoundation.h> //拍照后的回調(diào),傳遞拍攝的照片 typedef void(^DidCapturePhotoBlock)(UIImage *stillImage); @interface PXCameraManager : NSObject @property (nonatomic, strong) AVCaptureSession *session;//AVCaptureSession對象來執(zhí)行輸入設(shè)備和輸出設(shè)備之間的數(shù)據(jù)傳遞 @property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;//預(yù)覽圖層,來顯示照相機拍攝到的畫面 @property (nonatomic, strong) AVCaptureDeviceInput *deviceInput;//AVCaptureDeviceInput對象是輸入流 @property (nonatomic, strong) AVCaptureStillImageOutput *stillImageOutput;//照片輸出流對象 @property (nonatomic, assign) CGRect previewLayerFrame;//拍照區(qū)域 /* 為其他類提供的自定義接口 */ //設(shè)置拍照區(qū)域 (其中targetView為要展示拍照界面的view) - (void)configureWithtargetViewLayer:(UIView *)targetView previewRect:(CGRect)preivewRect; //拍照成功回調(diào) - (void)takePicture:(DidCapturePhotoBlock)block; //添加/移除相機浮層(如果有需求要在相機拍照區(qū)域添加浮層的時候使用) - (void)addCoverImageWithImage:(UIImage *)image; - (void)removeCoverImageWithImage:(UIImage *)image; //前后攝像頭切換 - (void)switchCameras; //閃光燈切換 - (void)configCameraFlashlight; @end
.m文件
@property (nonatomic, strong) UIView *preview;//展現(xiàn)拍照區(qū)域的view @property (nonatomic, strong) UIImageView *coverImageView;//拍照區(qū)域浮層 @property (nonatomic, assign) BOOL isCaremaBack; @property (nonatomic, assign) AVCaptureFlashMode flashMode; //初始化的時候設(shè)置自己想要的默認屬性 - (instancetype)init{ ? ? self = [super init]; ? ? if (self) { ? ? ? ? self.isCaremaBack = YES;//默認后置攝像頭 ? ? ? ? self.flashMode = AVCaptureFlashModeAuto;//默認自動閃光燈 ? ? } ? ? return ?self; }
實現(xiàn)接口的方法
1、準備相關(guān)硬件
- (void)configureWithTargetViewLayer:(UIView *)targetView previewRect:(CGRect)preivewRect{ ? ? self.preview = targetView; ? ? //開始一些相機相關(guān)硬件配置 ? ? ? ? [self addSession];//創(chuàng)建session ? ? [self addVideoPreviewLayerWithRect:preivewRect];//用session 創(chuàng)建 創(chuàng)建layer ? ? [self addvideoInputBackCamera:self.isCaremaBack];//給session 配置攝像頭 ? ? [self addVideoFlashlightWithFlashModel:self.flashMode];//配置閃光燈 ? ? [self addStillImageOutput];//給session 配置輸出 }
2、拍照
#pragma mark -? - (void)takePicture:(DidCapturePhotoBlock)block{ ? ? AVCaptureConnection *captureConnection = [self findCaptureConnection]; ? ? [captureConnection setVideoScaleAndCropFactor:1.0f]; ? ? [_stillImageOutput captureStillImageAsynchronouslyFromConnection:captureConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { ? ? ? ? NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]; ? ? ? ? UIImage *image = [UIImage imageWithData:imageData]; ? ? ? ? //這里可以根據(jù)不同需求對拍攝到的照片做一些壓縮或者裁剪的處理,這里我就偷懶不弄了。 ? ? ? ? if (block) { ? ? ? ? ? ? block(image); ? ? ? ? } ? ? }]; }
3、切換攝像頭
- (void)switchCameras{ ? ? if (!_deviceInput) { ? ? ? ? return; ? ? } ? ? [_session beginConfiguration]; ? ? [_session removeInput:_deviceInput]; ? ? self.isCaremaBack = !self.isCaremaBack; ? ? [self addvideoInputBackCamera:self.isCaremaBack]; ? ? [_session commitConfiguration]; }
4、切換閃光燈
- (void)configCameraFlashlight{ ? ? switch (self.flashMode) { ? ? ? ? case AVCaptureFlashModeAuto: ? ? ? ? { ? ? ? ? ? ? self.flashMode = AVCaptureFlashModeOff; ? ? ? ? } ? ? ? ? ? ? break; ? ? ? ? case AVCaptureFlashModeOff: ? ? ? ? { ? ? ? ? ? ? self.flashMode = AVCaptureFlashModeOn; ? ? ? ? } ? ? ? ? ? ? break; ? ? ? ? case AVCaptureFlashModeOn: ? ? ? ? { ? ? ? ? ? ? self.flashMode = AVCaptureFlashModeAuto; ? ? ? ? } ? ? ? ? ? ? break; ? ? ? ? default: ? ? ? ? ? ? break; ? ? } ? ? [self addVideoFlashlightWithFlashModel:self.flashMode]; ?}
添加/移除 浮層
- (void)addCoverImageWithImage:(UIImage *)image{ ? ? _coverImageView.image = image; } - (void)removeCoverImageWithImage:(UIImage *)image{ ? ? _coverImageView.image = nil; }
下面是配置硬件里的幾個方法實現(xiàn)
- (void)addSession{ ? ? if (!self.session) { ? ? ? ? AVCaptureSession *session = [[AVCaptureSession alloc]init]; ? ? ? ? self.session = session; ? ? } }
- (void)addVideoPreviewLayerWithRect:(CGRect)previewRect{ ? ? if (!self.previewLayer) { ? ? ? ? AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:_session]; ? ? ? ? previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; ? ? ? ? self.previewLayer = previewLayer; ? ? ? ? [self.preview.layer addSublayer:self.previewLayer]; ? ? } ? ? self.previewLayer.frame = previewRect; }
- (void)addvideoInputBackCamera:(BOOL)back{ ? ? NSArray *devices = [AVCaptureDevice devices]; ? ? AVCaptureDevice *frontCamera; ? ? AVCaptureDevice *backCamera; ? ? //獲取 前、后 攝像頭 ? ? for (AVCaptureDevice *device in devices) { ? ? ? ? if ([device hasMediaType:AVMediaTypeVideo]) { ? ? ? ? ? ? if ([device position] == AVCaptureDevicePositionBack) { ? ? ? ? ? ? ? ? backCamera = device; ? ? ? ? ? ? }else if([device position] == AVCaptureDevicePositionFront){ ? ? ? ? ? ? ? ? frontCamera = device; ? ? ? ? ? ? } ? ? ? ? } ? ? } ? ? NSError *error = nil; ? ? if(back){ ? ? ? ? AVCaptureDeviceInput *backCameraDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:backCamera error:&error]; ? ? ? ? if (!error) { ? ? ? ? ? ? if ([_session canAddInput:backCameraDeviceInput]) { ? ? ? ? ? ? ? ? [_session addInput:backCameraDeviceInput]; ? ? ? ? ? ? ? ? ?self.deviceInput = backCameraDeviceInput; ? ? ? ? ? ? }else{ ? ? ? ? ? ? ? ? NSLog(@"出錯啦"); ? ? ? ? ? ? } ? ? ? ? } ? ? }else{ ? ? ? ? AVCaptureDeviceInput *frontCameraDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:frontCamera error:&error]; ? ? ? ? if (!error) { ? ? ? ? ? ? if ([_session canAddInput:frontCameraDeviceInput]) { ? ? ? ? ? ? ? ? [_session addInput:frontCameraDeviceInput]; ? ? ? ? ? ? ? ? ?self.deviceInput = frontCameraDeviceInput; ? ? ? ? ? ? }else{ ? ? ? ? ? ? ? ? NSLog(@"出錯啦"); ? ? ? ? ? ? } ? ? ? ? } ? ? } }
- (void)addVideoFlashlightWithFlashModel:(AVCaptureFlashMode )flashModel{ ? ? AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; ? ? [device lockForConfiguration:nil]; ? ? if ([device hasFlash]) { ? ? ? ? device.flashMode = self.flashMode; ? ? } ? ? [device unlockForConfiguration]; }
- (void)addStillImageOutput{ ? ? if (!self.stillImageOutput) { ? ? ? ? AVCaptureStillImageOutput *stillImageOutput = [[AVCaptureStillImageOutput alloc]init]; ? ? ? ? NSDictionary *outPutSettingDict = [[NSDictionary alloc]initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey, nil]; ? ? ? ? stillImageOutput.outputSettings = outPutSettingDict; ? ? ? ? [_session addOutput:stillImageOutput]; ? ? ? ? self.stillImageOutput = stillImageOutput; ? ? } }
- (AVCaptureConnection *)findCaptureConnection{ ? ? AVCaptureConnection *videoConnection; ? ? for (AVCaptureConnection *connection in _stillImageOutput.connections ) { ? ? ? ? for (AVCaptureInputPort *port in connection.inputPorts) { ? ? ? ? ? ? if ([[port mediaType] isEqual:AVMediaTypeVideo]) { ? ? ? ? ? ? ? ? videoConnection = connection; ? ? ? ? ? ? ? ? return videoConnection; ? ? ? ? ? ? } ? ? ? ? } ? ? } ? ? return nil; }
到此,一個自定義相機的類就有了,要使用的時候,盡管調(diào)用吧。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
解決ios h5 input輸入框被輸入法彈出一塊區(qū)域的問題
今天小編就為大家分享一篇解決ios h5 input輸入框被輸入法彈出一塊區(qū)域的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08iOS實現(xiàn)卡片式滾動效果 iOS實現(xiàn)電影選片效果
這篇文章主要為大家詳細介紹了iOS實現(xiàn)卡片式滾動效果,實現(xiàn)電影選片效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-02-02深入理解Objective-C中類的數(shù)據(jù)結(jié)構(gòu)
最近發(fā)現(xiàn)用Objective-C確實好容易,下面這篇文章主要給大家介紹了關(guān)于Objective-C中類的數(shù)據(jù)結(jié)構(gòu)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-05-05iOS利用NSMutableAttributedString實現(xiàn)富文本的方法小結(jié)
這篇文章主要給大家介紹了關(guān)于iOS利用NSMutableAttributedString如何實現(xiàn)富文本的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-05-05iOS App連續(xù)閃退時上報crash日志的方法詳解
iOS App 有時可能遇到啟動必 crash 的絕境:每次打開 App 都閃退,無法正常使用App。下面這篇文章主要給大家介紹了iOS App連續(xù)閃退時上報crash日志的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面來一起看看吧。2018-04-04