前に UIImagePickerController でカメラを扱いましたが、AVCapturePhotoOutputを使うとより細かく設定可能です。
iOS9まではAVCaptureStillImageOutputでしたが非推奨となり、代わりがこのAVCapturePhotoOutput です。
iOS11から jpegPhotoDataRepresentation が非推奨となり、fileDataRepresentation を使うようになりました。またPermissionも少し変わりました。
画面タップでシャッターを切る例です。
Xcode 11.3.1
AVCapturePhotoOutput
この記事でのカバー範囲と注意点です。
- 実機で試す
- simulatorではデバッグできません、実機で試してください。
- Info.plistの編集
- 以下を設定しないとエラーになります。
- NSCameraUsageDescription
- NSPhotoLibraryAddUsageDescription
- NSPhotoLibraryUsageDescription(アプリによっては必要かもしれません)
- UIImagePickerController
- Dual cameraの設定はここではやりません。
- Live Photosの設定はここではやりません
- ファイルが増大するので
以下は Appleのサンプルコード を適当にはしょって作りました。ので、本当はもっと細かく設定しないと売り物にはなりませんので。ここでは基本的なところだけです。
Tap を受け取るために UIGestureRecognizerDelegateをdelegateで設定しています。
AVCapturePhotoCaptureDelegateというdelegateも追加されました。
ViewController.swift
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
import UIKit import AVFoundation class ViewController: UIViewController, UIGestureRecognizerDelegate, AVCapturePhotoCaptureDelegate { var input:AVCaptureDeviceInput! var output:AVCapturePhotoOutput! var session:AVCaptureSession! var preView:UIView! var camera:AVCaptureDevice! private var photoData: Data? override func viewDidLoad() { super.viewDidLoad() // 画面タップでシャッターを切るための設定 let tapGesture:UITapGestureRecognizer = UITapGestureRecognizer( target: self, action: #selector(ViewController.tapped(_:))) // デリゲートをセット tapGesture.delegate = self; // Viewに追加. self.view.addGestureRecognizer(tapGesture) } override func viewWillAppear(_ animated: Bool) { // スクリーン設定 setupDisplay() // カメラの設定 setupCamera() } override func viewDidDisappear(_ animated: Bool) { // camera stop メモリ解放 session.stopRunning() for output in session.outputs { session.removeOutput(output) } for input in session.inputs { session.removeInput(input) } session = nil camera = nil } func setupDisplay(){ //スクリーンの幅 let screenWidth = UIScreen.main.bounds.size.width; //スクリーンの高さ let screenHeight = UIScreen.main.bounds.size.height; // プレビュー用のビューを生成 preView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: screenWidth, height: screenHeight)) } // camera initialize func setupCamera(){ // セッション session = AVCaptureSession() // 背面・前面カメラの選択 camera = AVCaptureDevice.default( AVCaptureDevice.DeviceType.builtInWideAngleCamera, for: AVMediaType.video, position: .back) // position: .front // カメラからの入力データ do { input = try AVCaptureDeviceInput(device: camera) } catch let error as NSError { print(error) } // 入力をセッションに追加 if(session.canAddInput(input)) { session.addInput(input) } // 静止画出力のインスタンス生成 output = AVCapturePhotoOutput() // 出力をセッションに追加 if(session.canAddOutput(output)) { session.addOutput(output) } // セッションからプレビューを表示を let previewLayer = AVCaptureVideoPreviewLayer(session: session) previewLayer.frame = preView.frame previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill // レイヤーをViewに設定 // これを外すとプレビューが無くなる、けれど撮影はできる self.view.layer.addSublayer(previewLayer) session.startRunning() } // タップイベント. @objc func tapped(_ sender: UITapGestureRecognizer){ print("タップ") takeStillPicture() } func takeStillPicture(){ let photoSettings = AVCapturePhotoSettings() photoSettings.flashMode = .auto photoSettings.isHighResolutionPhotoEnabled = false output?.capturePhoto(with: photoSettings, delegate: self) } // @available(iOS 11.0, *) func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { // AVCapturePhotoOutput.jpegPhotoDataRepresentation deprecated in iOS11 let imageData = photo.fileDataRepresentation() let photo = UIImage(data: imageData!) // アルバムに追加. UIImageWriteToSavedPhotosAlbum(photo!, self, nil, nil) } } |
レイヤーをViewに追加するところを外すとプレビュー無しの撮影になります
position: .back
position: .front
で背面、前面カメラを切り替えられます
関連
- UIImagePickerController
- AVCapturePhotoOutput
- AVCaptureVideoDataOutput
Ref:
AVCapturePhotoOutput
Sample Code
シミュレータによるテストとデバッグ – Apple Developer