- This topic has 2개 답변, 2명 참여, and was last updated 4 years, 6 months 전에 by 광현.
1 답변 글타래를 보이고 있습니다
-
글쓴이글
-
-
광현참가자
- 글작성 : 15
- 답글작성 : 26
오늘은
0. 기본적인 AVCaptureSession 생성하기
1. 전면 카메라와 후면 카메라 전환
2. 사진 찍기 및 저장 기능 구현
3. previewView 만들기 (MTKView를 이용하는 방법은 추후에 다루겠습니다.)기본적인 AVCaptureSession 생성하기
- AVCaptureSession
- capture activity 를 다루며 input device 에서 outputs을 capture 할 수 있도록 데이터의 흐름을 관리하는 object 이다.
let captureSession = AVCaptureSession() // captureSession에 대한 설정. captureSession.beginConfiguration() captureSession.sessionPreset = AVCaptureSession.Preset.photo
- AVCaptureDevice
- 물리적인 capture device와 그와 관계 속성을 나타내는 object
- capture device는 AVCaptureSession object에 연결할 수 있는 input data(audio나 video)를 제공
class func default(for:)
와class func default(_:for:position)
을 사용해서 device object를 생성
guard let captureDevice = AVCaptureDevice.default(.default) else { return } //후면 카메라 guard let backCamera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) // 전면 카메라 guard let frontCamera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .front)
- AVCaptureDeviceInput
- capture session에 input data를 제공하는 object 입니다.
- AVCapturePhotoOutput
- 스틸 이미지, 라이브 포토, 기타 사진 워크 플로우에 대한 capture output
- AVCapturePhotoSettings
- 단일 사진 캡쳐 요청에 사용할 기능 및 설정의 사양을 정의하는 object 입니다.
// 생성된 captureSession에 device input을 생성 및 연결하고, // device output을 연결하는 코드입니다. var photoOutput : AVCapturePhotoOutput = { let output = AVCapturePhotoOutput() // 고해상도의 이미지 캡쳐 가능 설정 output.isHighResolutionCaptureEnabled = true return output }() var photoSetting : AVCapturePhotoSettings? do{ let backCameraInput = try AVCaptureDeviceInput(device: backCamera) let frontCameraInput = try AVCaptureDevice(device: frontCamera) // captureSession에 camearInput을 받도록 설정. captureSession.addInput(backCameraInput) captureSession.addOutput(photoOutput) // photoOutput 의 codec의 hevc 가능시 photoSettings의 codec을 hevc 로 설정하는 코드입니다. // hevc 불가능한 경우에는 jpeg codec을 사용하도록 합니다. if photoOutput.availablePhotoCodecTypes.contains(.hevc) photoSettings = AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.hevc]) }else{ photoSettings = AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg]) } } catch { print(error) } // captureSession 을 시작시킵니다. captureSession.startRunning()
카메라 방향 전환( 전면 및 후면 카메라)
@IBOutlet func changeCameraPosition(_ sender: UIButton) { // beginConfiguration : captureSession의 설정 변경의 시작을 알리는 함수. captureSession.beginConfiguration() if captureSession.inputs[0] == backCameraInput { // 후면에서 전면으로 전환 captureSession.removeInput(backCameraInput) captureSession.addInput(frontCameraInput) }else if captureSession.inputs[0] == frontCameraInput { // 전면에서 후면으로 전환 captureSession.removeInput(frontCameraInput) captureSession.addInput(backCameraInput) } // commitConfiguration : captureSession 의 설정 변경이 완료되었음을 알리는 함수. captureSession.commitConfiguration() }
사진 찍기 및 앨범에 저장 기능 구현.
- 사진 찍기는 AVCapturePhotoOutput object 의 capturePhoto(with:delegate) 를 이용하면 된다.
- 찍은 사진을 저장하기 위해서는 AVCapturePhotoCaptureDelegate 프로토코을 채택해야 합니다.
- AVCapturePhotoCaptureDelegate 프로토콜은 photo capture output의 진행을 감ㅅ히하고 결과를 받아오는 메쏘드들을 제공합니다.
- capture process를 감시하는 methods
func photoOutput(_:willBeginCaptureFor)
capture output 설정을 확인했으며, capture process가 시작될 것임 delegate에 알리는 메쏘드func photoOutput(_:willCapturePhotoFor)
photo capture 가 곧 일어날 것임을 delegate 에 알리는 메쏘드func photoOutput(_:didCapturePhotoFor)
photo capture 가 일어났음을 delegate 에 알리는 메쏘드func photoOutput(_:didFinishCaptureFor)
capture process 가 완료되었음을 delegate에 알리는 메쏘드
- capture results를 받는 methods (저장 기능을 위해 구현해야 하는 부분.)
func photoOutput(_:didFinishProcessingPhoto:error)
delegate 에 capture 이미지와 관련 metadata를 제공하는 함수.
@IBAction func capturePhotoBtnTouchUp(_ sender: UIButton){ photoOutput.capturePhoto(with: photoSettings, delegate: self) } capturePhoto 이후에 capture process 가 완료된 이미지를 저장하는 메쏘드 func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { guard error == nil else {print("Error capturing photo: \(error!)"); return} // 사진 앨범에 접근 권한을 요청 PHPhotoLibrary.requestAuthorization { status in guard status == .authorized else {return} // 사진 앨범에 저장. PHPhotoLibrary.shared().performChanges({ let creationRequest = PHAssetCreationRequest.forAsset() creationRequest.addResource(with: .photo, data: photo.fileDataRepresentation()!, options: nil) }, completionHandler: nil) } }
previewView 구현
- 2편에 설명했던 AVCaptureVideoPreviewLayer를 활용해서 만들 수 있습니다.
@IBOutlet weak var previewView: UIView! override func viewDidLoad(){ ... guard let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) else {return} previewLayer.frame = self.previewView.layer.bounds self.previewView.layer.addSublayer(previewLayer) ... }
2020-06-21 오후 10:11 #9433 -
야곰키 마스터
- 글작성 : 37
- 답글작성 : 579
오오, 마크다운 완전 좋아요! 훨씬 보기 좋네요!
코드도 더 좋아지고 있는 것 같아요. 변수이름이나 메서드 이름도 더 좋아지고 있고요.
띄어쓰기도 일관성있게 해주면 더 보기 좋을것 같습니다~
guard let captureDevice = AVCaptureDevice.default(.default) else { return }
여기서는 띄어 썼는데
guard let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) else {return}
여기서는 붙여쓰고 하는것도 보이고요}else{ photoSettings = AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg]) }
이거랑
} catch { print(error) }
이런 차이도 보이네요.
사소한 차이가 코드를 훨씬 좋게 만들어줄 것 같아요 ㅎㅎㅎ
언제나 멋진글 고맙습니다!2020-06-22 오후 12:27 #9438
-
-
글쓴이글
1 답변 글타래를 보이고 있습니다
- 답변은 로그인 후 가능합니다.