1.工具類(CameraManager)
一個自定義照相機(jī)的工具類你可能需要以下功能:
這個工具類看起來可能是這樣的:
- 用戶相機(jī)授權(quán)檢測
+ (BOOL)checkAuthority;
- 通過一個自定義視圖初始化
- (instancetype)initWithCameraCustomView:(UIView *)customView;
- 拍照結(jié)束的照片返回可以是代理或者block
- (void)takePhotoWithImageBlock:(void(^)(UIImage *originImg, NSError *error))imageBlock;
- 開始/結(jié)束拍照
- (void)startCamera;
- (void)stopCamera;
- 閃光燈、聚焦、縮放、前后攝像頭切換、照片裁剪加工等等
自定義相機(jī)的實現(xiàn)基于AVFoundation框架


1.AVCaptureSession
自定義相機(jī)的核心類,主要用于建立輸入流和輸出流之間的聯(lián)系。
你需要實現(xiàn)以下基本方法:
- (void)addInput:(AVCaptureInput *)input; // 添加輸入設(shè)備
- (void)addOutput:(AVCaptureOutput *)output; // 添加輸出設(shè)備
- (void)startRunning; // 開始拍照
- (void)stopRunning; // 結(jié)束拍照
再添加設(shè)備之前以下方法應(yīng)該對你會有幫助
- (BOOL)canAddInput:(AVCaptureInput *)input
- (BOOL)canAddOutput:(AVCaptureOutput *)output;
同上,調(diào)用拍照方法前請檢查相機(jī)連接設(shè)備,可能是這樣的
- (AVCaptureConnection *)findVideoConnection { /**< 相機(jī)連接設(shè)備*/
AVCaptureConnection *videoConnection = nil;
for (AVCaptureConnection *connection in self.stillImageOutput.connections) {
for (AVCaptureInputPort *port in connection.inputPorts) {
if ([[port mediaType] isEqual:AVMediaTypeVideo]) {
videoConnection = connection;
break;
}
}
if (videoConnection) {
break;
}
}
return videoConnection;
}
2.AVCaptureVideoPreviewLayer
照相視圖顯示的layer,繼承與CALayer
你需要做以下基本設(shè)置:
- (instancetype)initWithSession:(AVCaptureSession *)session; // 關(guān)聯(lián)AVCaptureSession
@property CGRect frame; // 設(shè)置frame
- (void)addSublayer:(CALayer *)layer; // 添加sublayer
3.AVCaptureDeviceInput
照相輸入設(shè)備
你需要做以下基本設(shè)置:
+ (instancetype)deviceInputWithDevice:(AVCaptureDevice *)device error:(NSError **)outError; // 初始化
以下代碼可能對你有所幫助
NSArray *devices = [AVCaptureDevice devices];
AVCaptureDevice *backCamera;
AVCaptureDevice *frontCamera;
for (AVCaptureDevice *device in devices) {
if ([device hasMediaType:AVMediaTypeVideo]) {
if ([device position] == AVCaptureDevicePositionBack) {
backCamera = device;
} else if ([device position] == AVCaptureDevicePositionFront) {
frontCamera = device;
}
}
}
4.AVCaptureStillImageOutput
照片輸出設(shè)備
你需要做以下基本設(shè)置:
- (instancetype)init; // 初始化
@property(nonatomic, copy) NSDictionary *outputSettings; // 設(shè)置輸出類型它可能是這樣的@{AVVideoCodecKey : AVVideoCodecJPEG}
- (void)captureStillImageAsynchronouslyFromConnection:(AVCaptureConnection *)connection completionHandler:(void (^)(CMSampleBufferRef imageDataSampleBuffer, NSError *error))handler; // 實現(xiàn)這個異步的方法,就可以拿到照片了,在這個方法中可以對照片進(jìn)行修改,并且把照片回調(diào)出去
以下代碼可能對你有所幫助
NSData *imgData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
UIImage *originImg = [UIImage imageWithData:imgData];
至此一個相機(jī)的基本拍照功能已經(jīng)全部完成
In order to set hardware properties on an AVCaptureDevice, such as focusMode and exposureMode, clients must first acquire a lock on the device. Clients should only hold the device lock if they require settable device propertiesto remain unchanged.
參考以上說明,你在對相機(jī)做對焦,閃光燈,縮放等等功能時候必須給AVCaptureDevice上鎖,像這樣
- (BOOL)lockForConfiguration:(NSError **)outError; // 操作之前
- (void)unlockForConfiguration; // 操作完成之后
1.對焦
if ([device lockForConfiguration:nil]) {
CGPoint pointOfInterest = [self pointOfInterestWithTouchPoint:touchPoint];// 點(diǎn)擊point在屏幕中的坐標(biāo)
if (device.focusPointOfInterestSupported) { // 聚焦
device.focusPointOfInterest = pointOfInterest;
}
if (device.exposurePointOfInterestSupported) { // 曝光
device.exposurePointOfInterest = pointOfInterest;
}
if ([device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) {
device.focusMode = AVCaptureFocusModeContinuousAutoFocus;
}
if ([device isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) {
device.exposureMode = AVCaptureExposureModeContinuousAutoExposure;
}
[device unlockForConfiguration];
}
2.縮放,請參考
@property(nonatomic) CGFloat videoZoomFactor
建議關(guān)聯(lián)pan手勢的代理
3.閃光燈,請參考
@property(nonatomic) AVCaptureFlashMode flashMode
默認(rèn)是AVCaptureFlashModeAuto
設(shè)置AVCaptureFlashModeOn和AVCaptureFlashModeOff切換
4.前后攝像頭切換,請參考
@property(nonatomic, readonly) AVCaptureDevicePosition position
可以通過移除輸入設(shè)備后再添加的方式
2.視圖類
自定義照相界面,你需要一個可愛的產(chǎn)品和設(shè)計,如果你的產(chǎn)品足夠仔細(xì),或者對原生相機(jī)功能情有獨(dú)鐘,他可能有這樣的需求
1.照片時候閃屏的效果,它可能是通過這樣實現(xiàn)
CABasicAnimation *twinkleAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];
twinkleAnim.fromValue = @(1);
twinkleAnim.toValue = @(0);
twinkleAnim.duration = 0.2;
[self.view.layer addAnimation:twinkleAnim forKey:nil];
2.外接物理按鍵,比如聲音的放大縮小按鍵,它可能是這樣實現(xiàn)的
NSError *error;
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[[AVAudioSession sharedInstance] setActive:YES error:&error];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(volumeClick) name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil];
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
監(jiān)聽系統(tǒng)音量通知,在volumeClick的方法中調(diào)用拍照的方法
如果你通過音量鍵拍照的時候看到了這個令你感到不愉快的東西,請繼續(xù)往下看
導(dǎo)入庫
MediaPlayer.framework導(dǎo)入頭文件
#import <MediaPlayer/MediaPlayer.h>自定義這個視圖,并把它放到屏幕外面,像這樣:
MPVolumeView *volumeView = [[MPVolumeView alloc]initWithFrame:CGRectMake(-20, -40, 10, 10)];
volumeView.hidden = NO;
[self.view addSubview:volumeView];
如果有更好的方法或者建議,以及文中的缺陷,希望大家可以留言告知,虛心求教
如果轉(zhuǎn)載本文,請注明本文出處,感謝