WWDC Quick Look 💓 By SwiftGGTeam
Implement high resolution photo capture

Implement high resolution photo capture

观看原视频

Highlight

Apple 在 iOS 27 上向第三方 App 开放了原生相机的延迟照片处理(Deferred Photo Processing)和快速拍摄优先(Fast Capture Prioritization)能力,让 24MP/48MP 高分辨率拍摄不再阻塞快门,开发者可以在不牺牲连拍响应速度的前提下输出最高画质照片。

核心内容

高分辨率照片到底高在哪里

预览流(Preview Stream)的分辨率只够在屏幕上显示,拍出来的照片细节少、噪点多。如果你需要裁切、放大查看细节,或者做图像分析,预览流完全不够用。

Apple 从 iPhone 14 Pro 开始引入 48MP 四合一像素传感器(Quad-pixel sensor),支持两种模式:四像素合一输出 12MP(进光量更大,适合暗光),或者全像素输出 48MP(细节最丰富)。到了 iPhone 15,又新增了 24MP 模式——它先用四合一像素拍出一张 12MP 的多帧融合 HDR 照片,再通过 Photonic Engine 计算摄影管线与 48MP 全分辨率图像融合,最终输出一张分辨率翻倍、文件大小只增加约 50% 的照片。

24MP 和 48MP 的支持范围也在扩大。iPhone 16 Pro 的长焦镜头、iPhone 17 的超广角镜头都支持这两种高分辨率模式。

四种高分辨率拍摄类型

你的 App 可以向系统请求四种不同的高分辨率照片:

  • Fully processed photo:多帧融合,经过 Photonic Engine 处理,动态范围和细节都有提升。这是最常用的模式。
  • Exposure brackets:同一场景的多张不同曝光帧,适合 HDR 合成或手动选帧。
  • Bayer RAW:传感器直出的最小处理数据,适合后期编辑。
  • Apple ProRAW:RAW 的灵活性加上 iPhone 的图像处理,编辑曝光、色彩、细节时空间更大。

画质与速度的权衡

拍高分辨率照片最大的痛点是处理时间。48MP 单帧处理已经要几秒,24MP 的多帧融合更慢。如果每拍完一张都要等处理完才能拍下一张,用户会错过关键瞬间。

Apple 的解决方案分三层:

第一层:资源预分配。通过 setPreparedPhotoSettingsArray 提前告诉系统你打算用什么分辨率和质量设置,让系统在用户按下快门前就把底层资源准备好。如果不做这一步,第一次拍摄时现场分配资源,延迟会非常明显。

第二层:响应式快门(Responsive Capture)。开启 isResponsiveCaptureEnabled 后,下一张照片可以在上一张的 capture 阶段结束后立即开始,不需要等 processing 阶段完成。配合 captureReadiness 属性,你可以精确知道什么时候可以拍下一帧。

第三层:延迟照片处理(Deferred Photo Processing)。系统在拍摄完成后先返回一张轻量级的代理照片(Proxy Photo),把耗时的多帧融合和深度处理放到后台或设备空闲时执行。最终照片可以通过 PhotoKit 按需获取,或者由系统在后台自动完成。

第四层:快速拍摄优先(Fast Capture Prioritization)。iOS 27 的新能力。当检测到用户连续快速拍摄时,系统会自动把 photoQualityPrioritization.quality 降级到 .balanced,减少 capture 和 processing 时间。这些降级后的照片后续也会通过延迟处理在后台慢慢优化。从演示来看,同样的篮球投篮场景,不开启这些 API 只能拍到 1 张,开启后能拍到 5 张。

详细内容

配置 AVCaptureSession

05:26

只有 .photo preset 支持 24MP 和 48MP,其他 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 三个级别都准备资源。
  • 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 开始可用,列出了当前格式支持的所有照片尺寸。
  • 示例代码选最大的尺寸做演示,实际开发中应该按业务需求选择合适的尺寸。
  • 必须在 commitConfiguration() 之前完成 photo output 的配置,修改已提交的设置会触发耗时的管线重新配置。

配置拍摄参数

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,同一会话支持多种质量和尺寸,不需要重新配置管线。

预分配资源

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("Failed to prepare: \(error)")
        return
    }
    print("Pipeline prepared: \(prepared)")
}

// 实际拍摄时创建新的 settings 对象
let captureSettings = AVCapturePhotoSettings()
captureSettings.maxPhotoDimensions = photoOutput.maxPhotoDimensions
captureSettings.photoQualityPrioritization = .quality
photoOutput.capturePhoto(with: captureSettings, delegate: self)

关键点:

  • setPreparedPhotoSettingsArray 应该在用户进入对应拍摄模式时尽早调用,比如切换到 48MP 模式的瞬间。
  • prepareSettingscaptureSettings 必须是两个独立的对象,不能复用。但配置必须完全匹配,这样实际拍摄才能命中预分配的资源。
  • 如果不预分配资源,拍摄时现场分配会拖慢第一次拍摄的速度。

延迟处理与快速拍摄优先

12:43

// 开启响应式快门
photoOutput.isResponsiveCaptureEnabled = true

// 开启延迟照片处理
photoOutput.isDeferredPhotoDeliveryEnabled = true

// iOS 27:开启快速拍摄优先
if #available(iOS 27.0, *) {
    photoOutput.fastCapturePrioritizationEnabled = true
}

关键点:

  • isResponsiveCaptureEnabled 允许 capture 阶段重叠,下一张照片可以在上一张 capture 结束后立即开始。
  • isDeferredPhotoDeliveryEnabled 让系统先返回代理照片,最终处理放到后台。代理照片通过 didFinishCapturingDeferredPhotoProxy 回调接收。
  • fastCapturePrioritizationEnabled 在检测到快速连拍时自动把质量从 .quality 降到 .balanced。iOS 27 起,降级后的照片也会走延迟处理在后台优化。
  • 延迟处理不占用 capture session 的内存,这让 18MP/24MP 的多帧融合成为可能。

核心启发

1. 做一个专业级手动相机 App

  • 做什么:让用户手动选择 12MP/24MP/48MP,实时显示当前设置下的预计处理时间。
  • 为什么值得做photoProcessingTimeRange 属性可以告诉用户还要等多久,结合 captureReadiness 做快门按钮的可用状态,体验比原生相机更专业。
  • 怎么开始:监听 AVCapturePhotoOutput.captureReadiness,在 UI 上显示 “Ready” / “Processing” 状态。用 AVCaptureResolvedSettings.photoProcessingTimeRange 估算剩余时间。

2. 文档扫描 App 的 48MP 模式

  • 做什么:扫描文档时切换到 48MP,拍完后自动裁切、透视校正,输出超高精度的 PDF。
  • 为什么值得做:48MP 单帧照片细节极其丰富,文字边缘锐利,放大后依然清晰。延迟处理让拍完一张立刻可以拍下一张,扫描多页文档不卡顿。
  • 怎么开始:配置 maxPhotoDimensions 为 48MP 尺寸,photoQualityPrioritization 设为 .balanced(48MP 单帧支持 balanced),开启 isDeferredPhotoDeliveryEnabled

3. 连拍选优相机

  • 做什么:用户按住快门连续拍摄,App 事后从一组照片中自动选出最清晰、构图最好的一张。
  • 为什么值得做:开启 fastCapturePrioritizationEnabled 后,连拍速度大幅提升。配合延迟处理,可以在后台对每张照片做质量评分。
  • 怎么开始:开启 isResponsiveCaptureEnabledfastCapturePrioritizationEnabled,用 didCapturePhotoFor 回调记录每张照片的元数据,后台通过延迟处理获取最终照片后做清晰度分析。

4. RAW + 高分辨率双轨拍摄

  • 做什么:同时请求 ProRAW 48MP 和 fully processed 24MP,让用户既有 RAW 的后期空间,又有计算摄影的即出效果。
  • 为什么值得做:Session 提到 RAW、ProRAW、fully processed 是独立的拍摄类型。可以同时配置多个输出,一次快门得到两种格式。
  • 怎么开始:配置两个 AVCapturePhotoOutput,一个设 isHighResolutionCaptureEnabled 和 RAW 格式,另一个设 24MP fully processed。或者用同一个 output 的 bracketed capture 功能。

关联 Session

评论

GitHub Issues · utterances