WWDC Quick Look 💓 By SwiftGGTeam
高解像度写真キャプチャを実装する

高解像度写真キャプチャを実装する

元の動画を見る

ハイライト

Apple は iOS 27 で、標準カメラ App の Deferred Photo Processing と Fast Capture Prioritization をサードパーティ App に開放しました。24MP/48MP の高解像度撮影でもシャッターをブロックせずに済み、開発者は連写の応答性を犠牲にせず最高画質の写真を出力できます。

主要内容

高解像度写真は何が高解像度なのか

プレビューストリームの解像度は画面表示には十分ですが、そこから得られる写真は細部が少なく、ノイズも多くなります。切り抜き、拡大しての確認、画像解析が必要なら、プレビューストリームでは足りません。

Apple は iPhone 14 Pro から 48MP の Quad-pixel sensor を導入しました。これは 2 つのモードをサポートします。4 つのピクセルを 1 つにまとめて 12MP を出力するモードは暗所でより多くの光を取り込めます。全ピクセルを使って 48MP を出力するモードは、最も豊かな細部を得られます。iPhone 15 では 24MP モードも追加されました。まず Quad-pixel 出力で 12MP のマルチフレーム融合 HDR 写真を撮り、Photonic Engine の計算写真パイプラインで 48MP の全解像度画像と融合します。最終的に、ファイルサイズを約 50% 増やすだけで解像度が 2 倍の写真を出力します。

24MP と 48MP の対応範囲も広がっています。iPhone 16 Pro の望遠カメラ、iPhone 17 の超広角カメラも、この 2 種類の高解像度モードをサポートします。

4 種類の高解像度撮影タイプ

App はシステムに 4 種類の高解像度写真を要求できます。

  • Fully processed photo: 複数フレームを融合し、Photonic Engine で処理された写真です。ダイナミックレンジと細部が改善されます。最もよく使うモードです。
  • Exposure brackets: 同じシーンを異なる露出で複数撮るフレーム群です。HDR 合成や手動のフレーム選択に向いています。
  • Bayer RAW: センサーから出た最小限の処理済みデータです。後編集に向いています。
  • Apple ProRAW: RAW の柔軟性と iPhone の画像処理を組み合わせたものです。露出、色、細部の編集により大きな余地があります。

画質と速度のトレードオフ

高解像度写真で最もつらいのは処理時間です。48MP の単一フレーム処理だけでも数秒かかり、24MP のマルチフレーム融合はさらに遅くなります。1 枚撮るたびに処理完了を待ってから次を撮る必要があると、ユーザーは大事な瞬間を逃します。

Apple の解決策は 4 層です。

第 1 層: リソースの事前割り当てsetPreparedPhotoSettingsArray で、使う予定の解像度と品質設定を事前にシステムへ伝えます。これにより、ユーザーがシャッターを押す前に低レベルリソースを準備できます。これをしないと、初回撮影時に現場でリソースを割り当てるため、目に見える遅延が出ます。

第 2 層: Responsive Capture によるレスポンシブシャッターisResponsiveCaptureEnabled を有効にすると、前の写真の capture 段階が終わり次第、次の写真をすぐ開始できます。processing 段階の完了を待つ必要はありません。captureReadiness プロパティと組み合わせれば、次のフレームをいつ撮れるかを正確に把握できます。

第 3 層: Deferred Photo Processing。撮影完了後、システムはまず軽量な代理写真、つまり Proxy Photo を返します。時間のかかるマルチフレーム融合や深度処理は、バックグラウンドまたはデバイスが空いたタイミングに回します。最終写真は PhotoKit 経由で必要に応じて取得でき、またはシステムがバックグラウンドで自動完成させます。

第 4 層: Fast Capture Prioritization。iOS 27 の新機能です。ユーザーが連続して素早く撮っていることを検知すると、システムは photoQualityPrioritization.quality から .balanced に自動で下げ、capture と processing の時間を短くします。下げられた写真も、その後の遅延処理でバックグラウンド改善されます。デモでは、同じバスケットボールのシュート場面で、これらの API を使わない場合は 1 枚しか撮れず、有効にすると 5 枚撮れていました。

詳細

AVCaptureSession を設定する

(05:26)

24MP と 48MP をサポートするのは .photo preset だけです。他の preset は高解像度撮影をサポートしません。

import AVFoundation

private let session = AVCaptureSession()

private func configureSession() {
    session.beginConfiguration()
    session.sessionPreset = .photo
}

重要ポイント:

  • sessionPreset.photo にする必要があります。そうしないと高解像度オプションは使えません。

AVCapturePhotoOutput を設定する

(06:11)

import AVFoundation

private let photoOutput = AVCapturePhotoOutput()

private let configurePhotoOutput: () -> Void = {
    photoOutput.maxPhotoQualityPrioritization = .quality
}

重要ポイント:

  • maxPhotoQualityPrioritization.quality にすると、システムは speed、balanced、quality の 3 レベルすべてのリソースを準備します。
  • 24MP と 18MP、つまり Center Stage フロントカメラは .quality を必須とします。.balanced.speed にすると 12MP へフォールバックします。
  • 48MP の単一フレーム写真は .balanced.quality をサポートしますが、.speed はサポートしません。

最大写真サイズを設定する

(06:38)

import AVFoundation

let supportedMaxPhotoDimensions = device?.activeFormat.supportedMaxPhotoDimensions ?? []

if let largestDimension = supportedMaxPhotoDimensions.max(by: { lhs, rhs in
    Int(lhs.width) * Int(lhs.height) < Int(rhs.width) * Int(rhs.height)
}) {
    photoOutput?.maxPhotoDimensions = largestDimension
}

session?.commitConfiguration()
session?.startRunning()

重要ポイント:

  • supportedMaxPhotoDimensions は iOS 16 から利用でき、現在の format がサポートするすべての写真サイズを列挙します。
  • サンプルコードはデモとして最大サイズを選んでいます。実際の開発では、事業要件に合ったサイズを選ぶべきです。
  • photo output の設定は commitConfiguration() の前に完了させる必要があります。commit 後に設定を変えると、時間のかかるパイプライン再設定が発生します。

撮影パラメータを設定する

(07:21)

import AVFoundation

let settings = AVCapturePhotoSettings()
settings.maxPhotoDimensions = dimension.cmVideoDimensionsValue
settings.photoQualityPrioritization = .quality

var delegate: AVCapturePhotoCaptureDelegate?

if let delegate {
    photoOutput?.capturePhoto(with: settings, delegate: delegate)
}

重要ポイント:

  • maxPhotoDimensions は要求であり、保証ではありません。システムは光量、シーン、利用可能な処理能力に応じて最適な経路を選びます。
  • 実際の出力サイズは AVCaptureResolvedSettings で返され、撮影完了時には delegate に通知されます。
  • 撮影ごとに maxPhotoDimensionsphotoQualityPrioritization を個別に設定できます。同じ session で複数の品質とサイズを扱え、パイプライン再設定は不要です。

リソースを事前割り当てする

(08:59)

import AVFoundation

let prepareSettings = AVCapturePhotoSettings()
prepareSettings.maxPhotoDimensions = photoOutput.maxPhotoDimensions
prepareSettings.photoQualityPrioritization = .quality

photoOutput.setPreparedPhotoSettingsArray([prepareSettings]) { prepared, error in
    if let error = error {
        print("準備に失敗しました: \(error)")
        return
    }
    print("パイプラインを準備しました: \(prepared)")
}

// 実際の撮影では新しい settings オブジェクトを作る
let captureSettings = AVCapturePhotoSettings()
captureSettings.maxPhotoDimensions = photoOutput.maxPhotoDimensions
captureSettings.photoQualityPrioritization = .quality
photoOutput.capturePhoto(with: captureSettings, delegate: self)

重要ポイント:

  • setPreparedPhotoSettingsArray は、ユーザーが対応する撮影モードに入ったらできるだけ早く呼ぶべきです。たとえば 48MP モードに切り替えた瞬間です。
  • prepareSettingscaptureSettings は 2 つの独立したオブジェクトである必要があり、再利用できません。ただし設定は完全に一致している必要があります。そうして初めて実際の撮影が事前割り当て済みリソースに当たります。
  • リソースを事前割り当てしない場合、撮影時に現場で割り当てが行われ、初回撮影が遅くなります。

遅延処理と Fast Capture Prioritization

(12:43)

// レスポンシブシャッターを有効にする
photoOutput.isResponsiveCaptureEnabled = true

// 遅延写真処理を有効にする
photoOutput.isDeferredPhotoDeliveryEnabled = true

// iOS 27: 高速撮影優先を有効にする
if #available(iOS 27.0, *) {
    photoOutput.fastCapturePrioritizationEnabled = true
}

重要ポイント:

  • isResponsiveCaptureEnabled は capture 段階の重なりを許可し、前の写真の capture が終わるとすぐ次の写真を開始できるようにします。
  • isDeferredPhotoDeliveryEnabled により、システムはまず代理写真を返し、最終処理をバックグラウンドへ移します。代理写真は didFinishCapturingDeferredPhotoProxy callback で受け取ります。
  • fastCapturePrioritizationEnabled は、高速連写を検知すると品質を .quality から .balanced へ自動的に下げます。iOS 27 以降では、下げられた写真も遅延処理でバックグラウンド改善されます。
  • 遅延処理は capture session のメモリを消費しません。これにより 18MP/24MP のマルチフレーム融合が実用的になります。

重要な示唆

1. プロ向けの手動カメラ App を作る

  • 何をするか: ユーザーが 12MP/24MP/48MP を手動で選び、現在の設定での予想処理時間をリアルタイムに表示できるようにします。
  • なぜ価値があるか: photoProcessingTimeRange プロパティは、ユーザーにあとどれくらい待つ必要があるかを伝えられます。captureReadiness と組み合わせれば、標準カメラよりプロらしいシャッターボタンの状態を作れます。
  • どう始めるか: AVCapturePhotoOutput.captureReadiness を監視し、UI に "準備完了" / "処理中" の状態を表示します。AVCaptureResolvedSettings.photoProcessingTimeRange で残り時間を推定します。

2. 文書スキャナー App の 48MP モード

  • 何をするか: 文書をスキャンするときに 48MP へ切り替え、撮影後に自動で切り抜き、透視補正を行い、超高精度の PDF を出力します。
  • なぜ価値があるか: 48MP の単一フレーム写真は非常に細部が豊かで、文字のエッジが鋭く、拡大しても鮮明です。遅延処理により、1 枚撮ったらすぐ次のページを撮れるため、複数ページのスキャンでも詰まりません。
  • どう始めるか: maxPhotoDimensions を 48MP サイズに設定し、photoQualityPrioritization.balanced にします。48MP 単一フレームは balanced をサポートします。さらに isDeferredPhotoDeliveryEnabled を有効にします。

3. 連写から最良ショットを選ぶカメラ

  • 何をするか: ユーザーがシャッターを押し続けて連続撮影し、あとから最も鮮明で構図のよい 1 枚を App が自動で選びます。
  • なぜ価値があるか: fastCapturePrioritizationEnabled を有効にすると、連写速度が大きく上がります。遅延処理と組み合わせることで、バックグラウンドで各写真を品質採点できます。
  • どう始めるか: isResponsiveCaptureEnabledfastCapturePrioritizationEnabled を有効にし、didCapturePhotoFor callback で各写真のメタデータを記録します。遅延処理で最終写真を取得した後、バックグラウンドで鮮明度分析を行います。

4. RAW + 高解像度の二系統撮影

  • 何をするか: 48MP ProRAW と 24MP fully processed photo を同時に要求し、ユーザーに RAW の後編集余地と、すぐ使える計算写真結果の両方を提供します。
  • なぜ価値があるか: session では、RAW、ProRAW、fully processed は独立した撮影タイプだと説明されています。複数の出力を同時に構成すれば、1 回のシャッターで 2 種類の形式を得られます。
  • どう始めるか: 2 つの AVCapturePhotoOutput を設定し、一方は isHighResolutionCaptureEnabled と RAW format、もう一方は 24MP fully processed にします。または同じ output の bracketed capture 機能を使います。

関連セッション

コメント

GitHub Issues · utterances