// // CameraViewController.swift // Twear // // Created by yangbin on 2021/12/22. // import UIKit import AVFoundation import Photos //let rect = CGRect(x: 30, y: 100, width: SCREEN_WIDTH-60, height: SCREEN_HEIGHT-100-100-100)// 底部工具栏 高度100 距离上面 下面都是100 class CameraViewController: UIViewController, BluetoothSyncDelegate { let WIDTH = UIScreen.main.bounds.width let HEIGHT = UIScreen.main.bounds.height // 音视频采集会话 let captureSession = AVCaptureSession() // 后置摄像头 @IBOutlet weak var backButton: UIButton! @IBOutlet weak var toggleButton: UIButton! var backFacingCamera: AVCaptureDevice? // 前置摄像头 var frontFacingCamera: AVCaptureDevice? // 当前正在使用的设备 var currentDevice: AVCaptureDevice? // 静止图像输出端 var stillImageOutput: AVCaptureStillImageOutput? // 相机预览图层 var cameraPreviewLayer:AVCaptureVideoPreviewLayer? //照片拍摄后预览视图 var photoImageview:UIImageView! override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.navigationController?.setNavigationBarHidden(true, animated: true) } override func viewDidLoad() { super.viewDidLoad() let authStatus = AVCaptureDevice.authorizationStatus(for: AVMediaType.video) if authStatus == AVAuthorizationStatus.notDetermined { AVCaptureDevice.requestAccess(for: AVMediaType.video) { (granted) in if granted { self.setupUI() } else { self.back(1) } } } else if authStatus == AVAuthorizationStatus.restricted || authStatus == AVAuthorizationStatus.denied { self.cameraAccessAlert() } else { self.setupUI() } } func saveImageToPhotoLibrary() { // 判断权限 switch PHPhotoLibrary.authorizationStatus() { case .authorized: break // self.saveImage(image: stillImage) case .notDetermined: PHPhotoLibrary.requestAuthorization { [weak self] (status) in if status == .authorized { // self?.saveImage(image: stillImage) } else { // self?.back(1) print("User denied") } } case .restricted, .denied: let alert = UIAlertController(title: LocString("提示"), message: LocString("请在“设置-隐私-照片“选项中,允许'HDF wear'访问你的照片"), preferredStyle: .alert) let confirm = UIAlertAction(title: LocString("确定"), style: .default) alert.addAction(confirm) default: break } } func cameraAccessAlert() { let alertVC = UIAlertController(title: LocString("提示"), message: LocString("请在“设置-隐私-相机”选项中,允许'HDF wear'访问你的相机"), preferredStyle: .alert) let confirm = UIAlertAction(title: LocString("确定"), style: .destructive) { [weak self] (action) in self?.back(1) } let cancel = UIAlertAction(title: LocString("取消"), style: .default) { [weak self] (action) in self?.back(1) } alertVC.addAction(cancel) alertVC.addAction(confirm) present(alertVC, animated: true, completion: nil) } func setupUI() { createUI() view.bringSubviewToFront(backButton) view.bringSubviewToFront(toggleButton) BluetoothManager.shared.registerSyncDelegate(self) BluetoothManager.shared.openCamera(true) } //MARK: - 获取设备,创建自定义视图 func createUI(){ // 将音视频采集会话的预设设置为高分辨率照片--选择照片分辨率 self.captureSession.sessionPreset = AVCaptureSession.Preset.hd1280x720 // 获取设备 let devices = AVCaptureDevice.devices(for: AVMediaType.video) for device in devices { if device.position == AVCaptureDevice.Position.back { self.backFacingCamera = device } else if device.position == AVCaptureDevice.Position.front { self.frontFacingCamera = device } } //设置当前设备为前置摄像头 self.currentDevice = self.backFacingCamera do { // 当前设备输入端 let captureDeviceInput = try AVCaptureDeviceInput(device: currentDevice!) self.stillImageOutput = AVCaptureStillImageOutput() // 输出图像格式设置 self.stillImageOutput?.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG] self.captureSession.addInput(captureDeviceInput) self.captureSession.addOutput(self.stillImageOutput!) } catch { // let alert = UIAlertController(title: "提示", message: "请打开相机权限: 设置-隐私-相机", preferredStyle: .alert) // let confirm = UIAlertAction(title: "确定", style: .default) // alert.addAction(confirm) // return } // 创建预览图层 self.cameraPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession) self.cameraPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill self.cameraPreviewLayer?.frame = view.layer.bounds self.view.layer.addSublayer(cameraPreviewLayer!) // Entry point / (_main) undefined. for architecture arm64 // 启动音视频采集的会话 self.captureSession.startRunning() } @objc func pinchCamera(_ recognizer: UIPinchGestureRecognizer) { // if let zoomFactor = currentDevice?.videoZoomFactor { // // if zoomFactor < 5.0 { // let newZoomFactor = min(zoomFactor + 1.0, 5.0) do { try currentDevice?.lockForConfiguration() currentDevice?.ramp(toVideoZoomFactor: recognizer.scale, withRate: 1.0) currentDevice?.unlockForConfiguration() } catch { print(error) } // } // } } func didReceiveCameraCommand(status: SetCmd) { switch status { case .takePicture: photoAction() case .exitCamera: back(1) default: break } } //照相按钮 @objc func photoAction(){ // 获得音视频采集设备的连接 let videoConnection = stillImageOutput?.connection(with: AVMediaType.video) // 输出端以异步方式采集静态图像 stillImageOutput?.captureStillImageAsynchronously(from: videoConnection!, completionHandler: { (imageDataSampleBuffer, error) -> Void in if imageDataSampleBuffer == nil { return } // 获得采样缓冲区中的数据 let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer!) // 将数据转换成UIImage if let stillImage = UIImage(data: imageData!) { // func saveImageToPhotoLibrary() { // 判断权限 switch PHPhotoLibrary.authorizationStatus() { case .authorized: self.saveImage(image: stillImage) case .notDetermined: PHPhotoLibrary.requestAuthorization { [weak self](status) in if status == .authorized { self?.saveImage(image: stillImage) } else { // self?.back(1) print("User denied") } } case .restricted, .denied: let alert = UIAlertController(title: LocString("提示"), message: LocString("请在“设置-隐私-照片“选项中,允许'HDF wear'访问你的照片"), preferredStyle: .alert) let confirm = UIAlertAction(title: LocString("确定"), style: .default) alert.addAction(confirm) default: break } // } //显示当前拍摄照片 // UIImageWriteToSavedPhotosAlbum(stillImage, nil, nil, nil) // self.photoImageview.isHidden = false // // self.photoImageview.image = stillImage } }) } private func saveImage(image: UIImage) { PHPhotoLibrary.shared().performChanges({ PHAssetChangeRequest.creationRequestForAsset(from: image) }, completionHandler: { (isSuccess, error) in DispatchQueue.main.async { if isSuccess {// 成功 // MBProgressHUD.showh("已保存到系统相册") } } }) } @IBAction func toggleCamera(_ sender: Any) { captureSession.beginConfiguration() // 在前置和后置之间切换摄像头 let newDevice = (currentDevice?.position == AVCaptureDevice.Position.back) ? frontFacingCamera : backFacingCamera // 移除之前所有的输入会话 for input in captureSession.inputs { captureSession.removeInput(input as! AVCaptureDeviceInput) } // 将输入端切换到新的采集设备 let cameraInput: AVCaptureDeviceInput do { cameraInput = try AVCaptureDeviceInput(device: newDevice!) } catch { print(error) return } // 添加输入端 if captureSession.canAddInput(cameraInput) { captureSession.addInput(cameraInput) } currentDevice = newDevice // 提交配置 captureSession.commitConfiguration() } @IBAction func back(_ sender: Any) { BluetoothManager.shared.unRegisterSyncDelegate(self) BluetoothManager.shared.openCamera(false) IsCameraOpen = false self.dismiss(animated: true) // navigationController?.popViewController(animated: true) } //取消按钮/重拍 @objc func cancelAction(){ //隐藏Imageview self.photoImageview.isHidden = true } //保存按钮-保存到相册 @objc func saveAction(){ //保存照片到相册 UIImageWriteToSavedPhotosAlbum(self.photoImageview.image!, nil, nil, nil) self.cancelAction() } } extension CameraViewController { //MARK: - 放大方法 @objc func zoomIn() { if let zoomFactor = currentDevice?.videoZoomFactor { if zoomFactor < 5.0 { let newZoomFactor = min(zoomFactor + 1.0, 5.0) do { try currentDevice?.lockForConfiguration() currentDevice?.ramp(toVideoZoomFactor: newZoomFactor, withRate: 1.0) currentDevice?.unlockForConfiguration() } catch { print(error) } } } } //MARK: - 缩小方法 @objc func zoomOut() { if let zoomFactor = currentDevice?.videoZoomFactor { if zoomFactor > 1.0 { let newZoomFactor = max(zoomFactor - 1.0, 1.0) do { try currentDevice?.lockForConfiguration() currentDevice?.ramp(toVideoZoomFactor: newZoomFactor, withRate: 1.0) currentDevice?.unlockForConfiguration() } catch { print(error) } } } } //MARK: - 切换摄像头 @objc func toggleCamera1() { captureSession.beginConfiguration() // 在前置和后置之间切换摄像头 let newDevice = (currentDevice?.position == AVCaptureDevice.Position.back) ? frontFacingCamera : backFacingCamera // 移除之前所有的输入会话 for input in captureSession.inputs { captureSession.removeInput(input as! AVCaptureDeviceInput) } // 将输入端切换到新的采集设备 let cameraInput: AVCaptureDeviceInput do { cameraInput = try AVCaptureDeviceInput(device: newDevice!) } catch { print(error) return } // 添加输入端 if captureSession.canAddInput(cameraInput) { captureSession.addInput(cameraInput) } currentDevice = newDevice // 提交配置 captureSession.commitConfiguration() } }