AV-自定義相機(jī)

最近重新梳理AVFoundation框架,遂將之前的oc版本自定義相機(jī)重構(gòu)為swift版本

使用到的類主要有:

AVCaptureDevice 設(shè)備類,有許多設(shè)置,比如位置Position,聚焦模式FocusMode,曝光模式ExposureMode,閃光燈模式FlashMode。。。。。。

AVCaptureDeviceInput 輸入類,用于配置相機(jī),相對(duì)應(yīng)的有AVCaptureOutput輸出類

AVCaptureStillImageOutput 照片輸出類

AVCaptureSession 會(huì)話類,開啟和停止相機(jī)

AVCaptureVideoPreviewLayer 預(yù)覽層


文后有鏈接


使用:

1.相機(jī)搭建

1)懶加載各種相機(jī)配置

? ? lazy var captureSession :AVCaptureSession= {

? ? ? ? let captureSessionTmp =AVCaptureSession()

? ? ? ? if captureSessionTmp.canSetSessionPreset(AVCaptureSession.Preset.photo) {

? ? ? ? ? ? captureSessionTmp.sessionPreset = AVCaptureSession.Preset.photo

? ? ? ? }

? ? ? ? return captureSessionTmp

? ? }()

? ? lazy var captureDeviceInput :AVCaptureDeviceInput? = {

? ? ? ? let captureDevice =getCameraDeviceWithPosition(position:AVCaptureDevice.Position.back)

? ? ? ? do{

? ? ? ? ? ? let captureDeviceInputTmp =try AVCaptureDeviceInput.init(device: captureDevice!)

? ? ? ? ? ? return captureDeviceInputTmp

? ? ? ? }catch{

? ? ? ? ? ? print(error)

? ? ? ? }

? ? ? ? return nil

? ? }()

? ? lazy var captureStillImageOutput :AVCaptureStillImageOutput= {

? ? ? ? let captureStillImageOutputTmp =AVCaptureStillImageOutput()

? ? ? ? captureStillImageOutputTmp.outputSettings = [AVVideoCodecKey:AVVideoCodecJPEG]

? ? ? ? return captureStillImageOutputTmp

? ? }()

? ? lazy var captureVideoPreviewLayer :AVCaptureVideoPreviewLayer= {

? ? ? ? let captureVideoPreviewLayerTmp =AVCaptureVideoPreviewLayer.init(session:captureSession)

? ? ? ? return captureVideoPreviewLayerTmp

? ? }()

2)配置相機(jī)

? if captureSession.canAddInput(captureDeviceInput!) {

? ? ? ? ? ? captureSession.addInput(captureDeviceInput!)

? ? }

? if captureSession.canAddOutput(captureStillImageOutput) {

? ? ? ? ? ? captureSession.addOutput(captureStillImageOutput)

? ? }


? ? let layer =ViewContainer.layer

? ? layer.masksToBounds=true

? ? captureVideoPreviewLayer.frame = layer.bounds

? ? captureVideoPreviewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill

? ? layer.insertSublayer(captureVideoPreviewLayer, below: focusCursor.layer)

3)添加手勢(shì)監(jiān)聽,閃光燈按鈕狀態(tài)

? ? private func addNotificationToCaptureDevice(captureDevice :AVCaptureDevice) {

? ? ? ? changeDeviceProperty{ (captureDevice)in

? ? ? ? ? ? captureDevice.isSubjectAreaChangeMonitoringEnabled = true

? ? ? ? }

? ? ? ? NotificationCenter.default.addObserver(self, selector: #selector(areaChange(noti:)), name: Notification.Name.AVCaptureDeviceSubjectAreaDidChange, object: captureDevice)

? ? }

注:func changeDeviceProperty(propertyChange :PropertyChangeBlock)方法為設(shè)備加鎖,改變相機(jī)屬性必須,為自定義方法

private func addGenstureRecognizer() {

? ? ? ? let tap =UITapGestureRecognizer.init(target:self, action:#selector(tapScreen(tapGesture:)))

? ? ? ? ViewContainer.addGestureRecognizer(tap)

}

2.拍照

? ? ? ? let captureConnection =captureStillImageOutput.connection(with:AVMediaType.video)

? ? ? ? captureStillImageOutput.captureStillImageAsynchronously(from: captureConnection!) { (imageDataSampleBuffer, error)in

? ? ? ? ? ? if imageDataSampleBuffer !=nil{

? ? ? ? ? ? ? ? let imageData =AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer!)

? ? ? ? ? ? ? ? let image =UIImage.init(data: imageData!)

? ? ? ? ? ? ? ? UIImageWriteToSavedPhotosAlbum(image!,self,#selector(self.imageDidFinishSavingWithError(image:error:contextInfo:)),nil)

? ? ? ? ? ? }

? ? ? ? }

注:imageDidFinishSavingWithError(image:error:contextInfo:)為自定義方法,為保存照片回調(diào)函數(shù),使用toast提示用戶是否成功

3.前置/后置攝像頭切換

? ? @IBAction func toggleButtonClick(_sender:UIButton) {

? ? ? ? let currentDevice =captureDeviceInput?.device

? ? ? ? let currentPosition = currentDevice?.position

? ? ? ? removeNotificationFromCaptureDevice(captureDevice: currentDevice!)

? ? ? ? var toChangeDevice :AVCaptureDevice?

? ? ? ? var toChangePosition =AVCaptureDevice.Position.front

? ? ? ? if currentPosition ==AVCaptureDevice.Position.unspecified|| currentPosition ==AVCaptureDevice.Position.front{

? ? ? ? ? ? toChangePosition =AVCaptureDevice.Position.back

? ? ? ? }

? ? ? ? toChangeDevice =getCameraDeviceWithPosition(position: toChangePosition)

? ? ? ? addNotificationToCaptureDevice(captureDevice: toChangeDevice!)

? ? ? ? do{

? ? ? ? ? ? let toChangeDeviceInput =tryAVCaptureDeviceInput.init(device: toChangeDevice!)

? ? ? ? ? ? captureSession.beginConfiguration()

? ? ? ? ? ? captureSession.removeInput(captureDeviceInput!)

? ? ? ? ? ? if captureSession.canAddInput(toChangeDeviceInput) {

? ? ? ? ? ? ? ? captureSession.addInput(toChangeDeviceInput)

? ? ? ? ? ? ? ? captureDeviceInput= toChangeDeviceInput

? ? ? ? ? ? }

? ? ? ? ? ? captureSession.commitConfiguration()

? ? ? ? ? ? setFlashModeButtonStatus()

? ? ? ? }catch{

? ? ? ? ? ? print(error)

? ? ? ? }

? ? }

注:需要先移除設(shè)備監(jiān)聽,再重新添加

4.閃光燈設(shè)置

? ? @IBAction func flashOffClick(_sender:UIButton) {

? ? ? ? setFlashMode(flashMode: AVCaptureDevice.FlashMode.off)

? ? ? ? setFlashModeButtonStatus()

? ? }

? ? @IBAction func flashOnClick(_sender:UIButton) {

? ? ? ? setFlashMode(flashMode: AVCaptureDevice.FlashMode.on)

? ? ? ? setFlashModeButtonStatus()

? ? }

? ? @IBAction func flashAutoClick(_sender:UIButton) {

? ? ? ? setFlashMode(flashMode: AVCaptureDevice.FlashMode.auto)

? ? ? ? setFlashModeButtonStatus()

? ? }

? ? private func setFlashMode(flashMode :AVCaptureDevice.FlashMode) {

? ? ? ? changeDeviceProperty{ (captureDevice)in

? ? ? ? ? ? if captureDevice.isFlashModeSupported(flashMode) {

? ? ? ? ? ? ? ? captureDevice.flashMode= flashMode

? ? ? ? ? ? }

? ? ? ? }

? ? }

5.聚焦模式,曝光模式

private func setFocusMode(focusMode :AVCaptureDevice.FocusMode) {

? ? ? ? changeDeviceProperty{ (captureDevice)in

? ? ? ? ? ? if captureDevice.isFocusModeSupported(focusMode) {

? ? ? ? ? ? ? ? captureDevice.focusMode= focusMode

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? private func setExposureMode(exposureMode :AVCaptureDevice.ExposureMode) {

? ? ? ? changeDeviceProperty{ (captureDevice)in

? ? ? ? ? ? if captureDevice.isExposureModeSupported(exposureMode) {

? ? ? ? ? ? ? ? captureDevice.exposureMode= exposureMode

? ? ? ? ? ? }

? ? ? ? }

? ? }

6.點(diǎn)擊屏幕時(shí),對(duì)焦的動(dòng)畫

? ? @objc private func tapScreen(tapGesture :UITapGestureRecognizer) {

? ? ? ? let pointTap = tapGesture.location(in:ViewContainer)

? ? ? ? let pointCamera =captureVideoPreviewLayer.captureDevicePointConverted(fromLayerPoint: pointTap)

? ? ? ? setFocusCursorWithPoint(point: pointTap)

? ? ? ? focusWithMode(focusMode:AVCaptureDevice.FocusMode.autoFocus, exposureMode:AVCaptureDevice.ExposureMode.autoExpose, point: pointCamera)

? ? }


demo 鏈接:https://github.com/licl19/CustomCameraDemo.git

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

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

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