Open6
AVKitでカメラとプレビューを扱う
Infoに許可を取るステートメントを設定しておく
これがないとカメラを利用できない
プレビューViewの作成
兎にも角にもこれがないと始まらない
公式を見るといい感じのサンプルが載っているが…
今回はサブレイヤーとしてもたせ、またLayerを埋める(いわゆるaspectFill)設定を加えた:
セッションの構成と開始
以降、ViewController
クラスをメインに話を進める
AVCaptureSession
をフィールドとしてもち、viewDidLoad
でセッションを構成する
以下、ポイント
- デバイスは特に拘らずデフォルトのものを取得して使用
- プリセットは
high
(A preset suitable for capturing high-quality output) を選択 - 出力はAVCapturePhotoOutput ではなく、AVCaptureVideoDataOutput を使用
- これによりカメラの出力を直接得ることができる
- 出力はフィールドで持っておく
- セッションの構成は
begin
で始めてcommit
で抜ける- 多分セッションが動いてるなら一回止めた方がいい
構成したセッションは viewWillAppear
で開始しておく セッションの開始処理はちょっと重いらしく、メインスレッドで動かすとランタイム警告が出るので注意
カメラ映像の表示と取得
ここまで実装すると、PreviewView
にカメラの映像がプレビューされる
プレビューしているフレームは AVCaptureVideoDataOutputSampleBufferDelegate
の didOutput
メソッドで取得できる:
取得したフレーム(CMSampleBuffer
)はフィールドに保存しておく
今後の処理的に面倒が起きないよう、フラグ shouldUpdateBuffer
が立っていなければ更新しないようにしている
…書いてて気づいたけど CMSampleBuffer
値型じゃないのか 何かしらでコピーとかした方がいいんだろうか?
フレームから画像を生成
ここが本題
変換の流れは以下の通り
- バッファ(
CMSampleBuffer
) ->CIImage
- カメラがキャプチャした映像のうち、
PreviewView
に表示されている領域を取得 - 1で取得した画像を、2で取得した領域に合わせて切り抜く
-
CIContext
により、CGImage
に変換 - 4で得た
CGImage
を、向きを考慮してUIImage
に変換
ポイントは2と4
プレビューに表示されている領域?
PreviewView
がもつ AVCaptureVideoPreviewLayer
の videoGravity
は .resizeAspectFill
なので、プレビューに表示される領域はカメラがキャプチャしたそれとは異なる:
// TODO: 図入れる