这是公司上上上一个项目的自定义相机界面,原来是swift2.0写的,今天改为swift3.0,记录一下.
效果图如下:
使用AVFoundation制作.
属性:
1 var device:AVCaptureDevice! //获取设备:如摄像头 2 var input:AVCaptureDeviceInput! //输入流 3 var photoOutput:AVCaptureStillImageOutput! //输出流 4 var output:AVCaptureMetadataOutput! //当启动摄像头开始捕获输入 5 var session:AVCaptureSession!//会话,协调着intput到output的数据传输,input和output的桥梁 6 var previewLayer:AVCaptureVideoPreviewLayer! //图像预览层,实时显示捕获的图像 7 8 var photoButton: UIButton? //拍照按钮 9 var imageView: UIImageView? //拍照后的成像 10 var image: UIImage? //拍照后的成像 11 var isJurisdiction: Bool? //是否获取了拍照标示 12 var flashBtn:UIButton? //闪光灯按钮
在viewDidLoad里面判断下权限,没给权限给个提示
isJurisdiction = canUserCamear() if isJurisdiction! { customCamera() //自定义相机 customUI() //自定义相机按钮 } else { return }
// MARK: - 检查相机权限 func canUserCamear() -> Bool { let authStatus: AVAuthorizationStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo) if authStatus == .denied { let alertView = UIAlertView(title: "请打开相机权限", message: "设置-隐私-相机", delegate: self, cancelButtonTitle: "确定", otherButtonTitles: "取消") alertView.tag = 100 alertView.show() return false } else { return true } return true }
自定义相机:
1 //MARK: 初始化自定义相机 2 func customCamera(){ 3 guard let devices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as? [AVCaptureDevice] else { return } //初始化摄像头设备 4 guard let device = devices.filter({ return $0.position == .back }).first else{ return} 5 self.device = device 6 //输入流初始化 7 self.input = try? AVCaptureDeviceInput(device: device) 8 //照片输出流初始化 9 self.photoOutput = AVCaptureStillImageOutput.init() 10 //输出流初始化 11 self.output = AVCaptureMetadataOutput.init() 12 //生成会话 13 self.session = AVCaptureSession.init() 14 if(self.session.canSetSessionPreset("AVCaptureSessionPreset1280x720")){ 15 self.session.sessionPreset = "AVCaptureSessionPreset1280x720" 16 } 17 if(self.session.canAddInput(self.input)){ 18 self.session.addInput(self.input) 19 } 20 if(self.session.canAddOutput(self.photoOutput)){ 21 self.session.addOutput(self.photoOutput) 22 } 23 //使用self.session,初始化预览层,self.session负责驱动input进行信息的采集,layer负责把图像渲染显示 24 self.previewLayer = AVCaptureVideoPreviewLayer.init(session: self.session) 25 self.previewLayer.frame = CGRect.init(x: 0, y: 0, width: kScreenWH.width, height: kScreenWH.height) 26 self.previewLayer.videoGravity = "AVLayerVideoGravityResizeAspectFill" 27 self.view.layer.addSublayer(self.previewLayer) 28 //启动 29 self.session.startRunning() 30 if ((try? device.lockForConfiguration()) != nil) { 31 if device.isFlashModeSupported(.auto) { 32 device.flashMode = .auto 33 } 34 //自动白平衡 35 if device.isWhiteBalanceModeSupported(.autoWhiteBalance) { 36 device.whiteBalanceMode = .autoWhiteBalance 37 } 38 device.unlockForConfiguration() 39 } 40 41 //闪光灯 42 do{ try device.lockForConfiguration() }catch{ } 43 if device.hasFlash == false { return } 44 device.flashMode = AVCaptureFlashMode.auto 45 device.unlockForConfiguration() 46 47 }
自定义相机界面按钮:拍照,取消,闪光灯,前后拍照切换按钮
1 //MARK: 添加自定义按钮等UI 2 func customUI(){ 3 //前后摄像头切换 4 let changeBtn = UIButton.init() 5 changeBtn.frame = CGRect.init(x: kScreenWH.width - 50, y: 20, width: 40, height: 40) 6 changeBtn.setImage(#imageLiteral(resourceName: "change"), for: .normal) 7 changeBtn.addTarget(self, action: #selector(self.changeCamera), for: .touchUpInside) 8 view.addSubview(changeBtn) 9 10 //拍照按钮 11 photoButton = UIButton(type: .custom) 12 photoButton?.frame = CGRect(x: kScreenWH.width * 1 / 2.0 - 30, y: kScreenWH.height - 100, width: 60, height: 60) 13 photoButton?.setImage(UIImage(named: "photograph"), for: .normal) 14 photoButton?.setImage(UIImage(named: "photograph_Select"), for: .normal) 15 photoButton?.addTarget(self, action: #selector(self.shutterCamera), for: .touchUpInside) 16 view.addSubview(photoButton!) 17 18 //闪光灯按钮 19 flashBtn = UIButton.init() 20 flashBtn?.frame = CGRect.init(x: 10, y: 20, width: 40, height: 40) 21 flashBtn?.addTarget(self, action: #selector(self.flashAction), for: .touchUpInside) 22 flashBtn?.setImage(#imageLiteral(resourceName: "flash-A"), for: .normal) 23 view.addSubview(flashBtn!) 24 25 //取消 26 let cancelBtn = UIButton.init() 27 cancelBtn.frame = CGRect.init(x: 10, y: kScreenWH.height - 100, width: 60, height: 60) 28 cancelBtn.setTitle("取消", for: .normal) 29 cancelBtn.addTarget(self, action: #selector(self.cancelActin), for: .touchUpInside) 30 view.addSubview(cancelBtn) 31 } 32 //MARK:前后摄像头更改事件 33 func changeCamera(){ 34 //获取之前的镜头 35 guard var position = input?.device.position else { return } 36 //获取当前应该显示的镜头 37 position = position == .front ? .back : .front 38 //创建新的device 39 guard let devices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as? [AVCaptureDevice] else { return } 40 // 1.2.取出获取前置摄像头 41 let d = devices.filter({ return $0.position == position }).first 42 device = d 43 //input 44 guard let videoInput = try? AVCaptureDeviceInput(device: d) else { return } 45 46 //切换 47 session.beginConfiguration() 48 session.removeInput(self.input!) 49 session.addInput(videoInput) 50 session.commitConfiguration() 51 self.input = videoInput 52 53 }
拍照按钮点击事件:
1 //MARK:拍照按钮点击事件 2 func shutterCamera(){ 3 let videoConnection: AVCaptureConnection? = photoOutput.connection(withMediaType: AVMediaTypeVideo) 4 if videoConnection == nil { 5 print("take photo failed!") 6 return 7 } 8 photoOutput.captureStillImageAsynchronously(from: videoConnection ?? AVCaptureConnection(), completionHandler: {(_ imageDataSampleBuffer: CMSampleBuffer?, _ error: Error?) -> Void in 9 if imageDataSampleBuffer == nil { 10 return 11 } 12 let imageData: Data? = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer) //照片数据流 13 self.image = UIImage(data: imageData!) 14 self.session.stopRunning() 15 self.imageView = UIImageView(frame: self.previewLayer.frame) 16 self.view.insertSubview(self.imageView!, belowSubview: self.photoButton!) 17 self.imageView?.layer.masksToBounds = true 18 self.imageView?.image = self.image 19 print("image size = \(NSStringFromCGSize((self.image?.size)!))") 20 }) 21 }
闪光灯切换事件:
1 //MARK: 闪光灯开关 2 func flashAction(){ 3 try? device.lockForConfiguration() 4 switch device.flashMode.rawValue { 5 case 0: 6 device!.flashMode = AVCaptureFlashMode.on 7 flashBtn?.setImage(#imageLiteral(resourceName: "flash-on"), for: .normal) 8 break 9 case 1: 10 device!.flashMode = AVCaptureFlashMode.auto 11 flashBtn?.setImage(#imageLiteral(resourceName: "flash-A"), for: .normal) 12 break 13 default: 14 device!.flashMode = AVCaptureFlashMode.off 15 flashBtn?.setImage(#imageLiteral(resourceName: "flash-off"), for: .normal) 16 } 17 device.unlockForConfiguration() 18 19 }
取消按钮点击事件:
//MARK:取消按钮 func cancelActin(){ self.imageView?.removeFromSuperview() self.session.startRunning() }
github源码地址:https://github.com/pheromone/swift_custom_camera