【iOS】AVFoundationを使用してRAWデータ撮影機能を実装する
AVFoundationのCapture APIを使用して、RAWデータ撮影機能を実装する方法について書きます。以下の記事を先にお読みいただくと、本記事の内容をスムーズに理解することができます。
本記事をお読みいただくことで、以下の内容を学ぶことができます。
- RAWデータを出力するキャプチャセッションの設定方法
- RAWデータに対応するピクセルフォーマットを取得する方法
- RAWデータの撮影を開始する方法
- デリゲートメソッドを介したRAWデータの取得方法
- RAWデータを一つのアセットで写真アルバムに追加する方法
本記事の内容は、「詳解 AVFoundation Capture」から一部の説明を抜粋した内容になっています。
アプリがカメラやマイク、写真アルバムへアクセスするために必要なアクセス権を取得する方法については、本記事では割愛しています。「詳解 AVFoundation Capture」の「第2章 アクセス権」または、以下のドキュメントをご参照ください。キャプチャセッションの設定
RAWデータ撮影を行うためのキャプチャセッション設定は、静止画データ撮影を行う時と同じです。AVCapturePhotoOutput
オブジェクトをAVCaptureSession
オブジェクトに追加することで、AVCapturePhotoCaptureDelegate
プロトコルで定義されているデリゲートメソッドを介して、撮影したRAWデータを取得することができます。RAWデータを撮影する時は、AVCaptureSession
オブジェクトのsessionPreset
プロパティに、AVCaptureSession.Preset.photo
オブジェクトを代入します。以下のソースコードでは、RAWデータ撮影を行うためのキャプチャセッションの設定を行なっています。
撮影オプション設定
AVCapturePhotoSettings
は、静止画データを撮影する時の撮影オプション設定を行うことができるクラスです。
AVCapturePhotoSettings
オブジェクトの各プロパティに、撮影オプション設定に対応するオブジェクトを代入することで、静止画データ撮影に関する設定を制御することができます。RAWデータ撮影を行うために、AVCapturePhotoSettings
のinit(rawPixelFormatType:processedFormat:)
イニシャライザで、RAW データ撮影を行うためのAVCapturePhotoSettings
オブジェクトを取得します。
rawPixelFormatType
引数には、RAW データのピクセルフォーマットタイプを表すOSType
オブジェクトを指定します。RAW データのピクセルフォーマットタイプ表すOSType
オブジェクトは、AVCapturePhotoOutput
オブジェクトのavailableRawPhotoPixelFormatTypes
プロパティで取得することができます。
availableRawPhotoPixelFormatTypes
は、RAW / Apple ProRAW といったRAWデータのピクセルフォーマットタイプを表すOSType
オブジェクトの配列が代入されているプロパティです。以下のソースコードでは、RAW データのピクセルフォーマットタイプを表すOSType オブジェクトを取得しています。
isBayerRAWPixelFormat(_:)
は、第一引数に指定したOSType
オブジェクトが、RAW データのピクセルフォーマットタイプを表すOSType
オブジェクトかどうかを表すBool
値を返すメソッドです。
query
変数には、引数に指定したOSType
オブジェクトが、RAWデータのピクセルフォーマットタイプを表すOSType
オブジェクトかどうかを判定するクロージャを代入しています。availableRawPhotoPixelFormatTypes.first(where: query)
で、RAWデータのピクセルフォーマットタイプを表すOSType
オブジェクトを取得しています。
以下のソースコードでは、RAWデータ撮影を行うためのAVCapturePhotoSettings
オブジェクトを取得しています。
静止画データ・RAW データ撮影の開始
AVCapturePhotoOutput
オブジェクトのcapturePhoto(with:delegate:)
メソッドで、RAWデータ撮影を開始することができます。
with
引数には、先ほど取得したRAWデータ撮影を行うためのAVCapturePhotoSettings
オブジェクトを指定します。delegate
引数には、AVCapturePhotoCaptureDelegate
プロトコルに準拠するオブジェクトを指定します。AVCapturePhotoCaptureDelegate
プロトコルで定義されているデリゲートメソッドについては後述しますが、上記のソースコードでは、self
を指定しています。AVCapturePhotoCaptureDelegate
プロトコルに準拠したオブジェクトに、RAW データ撮影の開始から完了するまでに呼び出されるデリゲートメソッドを定義します。
プロトコルへの準拠
capturePhoto(with:delegate:)
メソッドのdelegate
引数に、RAWデータ撮影の開始から完了するまでに呼び出されるデリゲートメソッドの委譲先を指定しました。今回は、移譲先にself
を指定したので、capturePhoto(with:delegate:)
メソッドを実行するクラス自身にデリゲートメソッドを定義します。デリゲートメソッドを定義するために、self
をAVCapturePhotoCaptureDelegate
プロトコルに準拠させます。
RAW データ・静止画データの取得
photoOutput(_:didFinishProcessingPhoto:error:)
は、AVCapturePhotoCaptureDelegate
プロトコルで定義されているデリゲートメソッドです。
静止画データが出力される時に呼び出されます。RAWデータ撮影を行う時は、RAW データと圧縮済みデータの二つが出力されます。つまり、photoOutput(_:didFinishProcessingPhoto:error:)
メソッドは、合計二回呼び出されます。出力された両データは、photo
引数に代入されているAVCapturePhoto
オブジェクトで取得することができます。AVCapturePhoto
は、静止画データやメタデータ情報を格納することができるクラスです。
RAWデータの取得処理を行う前に、AVCapturePhoto
オブジェクトのisRawPhoto
プロパティを確認します。
isRawPhoto
は、自身に格納されているデータがRAWデータかどうかを表すBool
値が代入されているプロパティです。自身に代入されているデータがRAWデータの時、isRawPhoto
プロパティにはtrue
が代入されています。以下のソースコードでは、静止画データをcompressedData
変数に代入し、rawImageFileURL
変数に代入されているURL
オブジェクトが表すドキュメントフォルダパスに、RAWデータを書き込んでいます。
取得した静止画データを表すData
オブジェクトと、ドキュメントフォルダパスを表すURL
オブジェクトは、別のデリゲートメソッド内で、静止画データとRAW データを写真アルバムへ追加する処理を行う時に使用するため、変数に保持しておきます。
「RAW + L」データを写真アルバムへ追加
photoOutput(_:didFinishProcessingPhoto:error:)
は、AVCapturePhotoCaptureDelegate
プロトコルで定義されているデリゲートメソッドです。
撮影に関連する全ての処理が完了した時に呼び出されます。「RAW + L」データ(RAW データとLarge サイズの圧縮済みデータ) を写真アルバムへ追加する処理は、photoOutput(_:didFinishCaptureFor:error:)
メソッド内で行います。「RAW + L」データ(以降、アセットデータ) を写真アルバムに追加する処理は、PhotoKitフレームワークのAPIを使用します。PhotoKitは、写真アルバムを操作するためのAPI が定義されているフレームワークです。写真アルバムに変更を加える時は、PHPhotoLibrary
のperformChanges(_:)
メソッドを実行します。
performChanges(_:)
は、第一引数に指定した写真アルバムに変更を加える処理を、PhotoKitにリクエストするメソッドです。
第一引数には、写真アルバムを操作する処理をクロージャで記述します。写真アルバムに対する変更は、PHAssetCreationRequest
オブジェクトのメソッドで行います。PHAssetCreationRequest
は、写真アルバムに対する変更をPhotoKitにリクエストすることができるメソッドを持つクラスです。
PHAssetCreationRequest
オブジェクトは、forAsset()
メソッドで取得することができます。
Data
オブジェクトのアセットデータを写真アルバムに追加する時は、PHAssetCreationRequest
オブジェクトのaddResource(with:data:options:)
メソッドを実行します。
addResource(with:data:options:)
は、data
引数に指定したData
オブジェクトのアセットデータを、写真アルバムに追加することをPhotoKitにリクエストするメソッドです。with
引数には、写真アルバムに追加するアセットのタイプを、PHAssetResourceType
オブジェクトで指定します。今回は、静止画データを写真アルバムに追加するので、上記のソースコードでは、with
引数に.photo
を指定しています。data
引数には、写真アルバムに追加するアセットデータを、Data
オブジェクトで指定します。上記のソースコードでは、撮影した圧縮済み静止画データが代入されているcompressedData
変数を指定しています。
次に、RAWデータを写真アルバムに追加することをリクエストするメソッドを実行します。特定のドキュメントフォルダパスに書き込まれているアセットデータを写真アルバムに追加する時は、PHAssetCreationRequest
オブジェクトのaddResource(with:fileURL:options:)
メソッドを実行します。
静止画データにRAW データを関連づけて、「RAW + L」データとして写真アルバムに追加する時は、with
引数に.alternatePhoto
を指定します。.alternatePhoto
を指定することで、事前に実行したaddResource(with:data:options:)
メソッドで、写真アルバムに追加することをリクエストした静止画データに対してRAW データを関連づけることが、PhotoKitにリクエストされます。
options
引数には、PHAssetResourceCreationOptions
オブジェクトを指定します。PHAssetResourceCreationOptions
は、アセットデータを写真アルバムに追加する時の追加処理オプションを設定することができるクラスです。
ドキュメントフォルダパスに配置されているRAWデータを写真アルバムに追加した後に、元のRAWデータが不要な時は、PHAssetResourceCreationOptions
オブジェクトのshouldMoveFile
プロパティにtrue
を代入します。shouldMoveFile
プロパティにtrue
を代入したPHAssetResourceCreationOptions
オブジェクトをoptions
引数に指定することで、元のRAWデータが写真アルバムに移動してから、RAWデータを写真アルバムに追加する処理が行われます。つまり、元のRAWデータが配置されていたドキュメントフォルダパスにはRAWデータが存在しなくなり、端末のストレージを節約することができます。
以下のソースコードでは、photoOutput(_:didFinishCaptureFor:error:)
メソッド内で静止画データにRAWデータを関連づけて、「RAW + L」データを一つのアセットデータとして、写真アルバムに追加する処理を行っています。
参考資料
・詳解 AVFoundation Capture
・Capturing Photos in RAW and Apple ProRAW Formats
Discussion