WWDC Quick Look 💓 By SwiftGGTeam
Support HDR images in your app

Support HDR images in your app

元の動画を見る

ハイライト

iOS 17 では ISO HDR 静止画像標準への完全なサポートが導入され、開発者は SwiftUI、UIKit、Core Graphics で HDR 写真を直接読み込み、表示し、作成できるようになりました。複雑なトーンマッピングを手作業で扱う必要はありません。

主な内容

SDR(標準ダイナミックレンジ)ディスプレイの輝度範囲は限られているため、撮影シーン内のハイライト部分は圧縮またはクリップされます。HDR ディスプレイはより広い輝度範囲を表現でき、画像を実際のシーンに近づけます。

Apple は今年、ISO HDR 標準への対応を導入しました。この標準(TS22028-5)は、HDR コンテンツを既存の静止画像形式へエンコードする方法を定義しています。主なパラメータには、伝達関数として HLG または PQ を使うこと、BT.2020 の広色域、10 ビット以上のビット深度が含まれます。HEIF は HDR をエンコードできますが、従来の JPEG は 8 ビットのみのため対応できません。

開発者にとって最大の変化は、システムフレームワークが HDR の識別と表示を処理してくれることです。SwiftUI の Image、UIKit の UIImageViewCALayer はいずれも HDR コンテンツを自動認識して正しくレンダリングできます。画像メタデータが正しいことだけを確認すれば、システムは EDR(Extended Dynamic Range)を使い、対応ディスプレイ上で SDR の白色点を超える輝度の内容を表示します。

詳細

HDR の基本概念

00:40)HDR 表示の中心は headroom(ヘッドルーム)です。SDR ディスプレイの最も明るい白は reference white(基準白)と呼ばれ、HDR は reference white より明るい内容を表示できます。

EDR の考え方では:

  • reference white = 1.0
  • peak = 显示器能表示的最大值

ISO HDR 標準の定義:

  • 黒: 0.0005 cd/m²
  • デフォルトの reference white: 203 cd/m²
  • 203 を超える部分はすべて headroom

SDR との比較:

  • sRGB/Display P3 の黒: 0.2 cd/m²
  • 白: 80 cd/m²

HDR 画像の識別

02:35)システムは、画像が HDR かどうかを判断する複数の方法を提供します。

SwiftUI の自動処理:

import SwiftUI

struct ContentView: View {
    var body: some View {
        Image("sunrise_hdr")
            .resizable()
            .scaledToFit()
    }
}

SwiftUI の Image は HDR コンテンツを自動認識し、EDR 対応ディスプレイ上で正しくレンダリングします。

UIKit の処理:

import UIKit

let imageView = UIImageView()
imageView.image = UIImage(named: "sunrise_hdr")
imageView.preferredImageDynamicRange = .high

キーポイント:

  • preferredImageDynamicRange = .high は、この画像を HDR としてレンダリングすべきことをシステムに伝える
  • システムは EDR マッピングを自動処理する

ProRAW/RAW から HDR 画像を作成する

04:30)iPhone で撮影した ProRAW には高ダイナミックレンジのデータが含まれており、HDR 静止画像として書き出せます。

import CoreImage
import ImageIO

// ProRAW から HDR CGImage を作成
guard let rawImage = CIImage(contentsOf: prorawURL,
                             options: [.rawFilterOptions: true]) else { return }

// HDR データを保持するためにトーンマッピングを適用
let toneMapped = rawImage.applyingFilter("CIToneCurve",
    parameters: [
        "inputPoint0": CIVector(x: 0, y: 0),
        "inputPoint1": CIVector(x: 0.25, y: 0.25),
        "inputPoint2": CIVector(x: 0.5, y: 0.5),
        "inputPoint3": CIVector(x: 0.75, y: 0.75),
        "inputPoint4": CIVector(x: 1, y: 1.2)  // スーパーホワイト領域を保持
    ])

// HDR 付き HEIF として書き出す
let context = CIContext()
guard let cgImage = context.createCGImage(toneMapped, from: toneMapped.extent) else { return }

let destination = CGImageDestinationCreateWithURL(outputURL,
                                                   UTType.heic.identifier as CFString,
                                                   1,
                                                   nil)
let hdrProperties: [String: Any] = [
    kCGImagePropertyHEICSDRHint as String: true,
    kCGImagePropertyHEICGainMap as String: gainMapData
]
CGImageDestinationAddImage(destination!, cgImage, hdrProperties as CFDictionary)
CGImageDestinationFinalize(destination!)

キーポイント:

  • ProRAW はセンサーレベルのダイナミックレンジデータを保持する
  • 書き出し時に HEIF 形式を選び、HDR メタデータに対応する
  • kCGImagePropertyHEICSDRHint は画像に HDR コンテンツが含まれることを示す

CALayer で HDR を表示する

06:15)カスタムレンダリングの場面では、CALayer の EDR サポートを使えます。

import QuartzCore

let layer = CALayer()
layer.contents = hdrCGImage
layer.wantsExtendedDynamicRangeContent = true

// EDR ヘッドルームを設定
layer.edrMetadata = .hdrContent(
    luminance: 1000.0  // コンテンツのピーク輝度、単位は nits
)

キーポイント:

  • wantsExtendedDynamicRangeContent = true で EDR レンダリングを有効にする
  • edrMetadata はコンテンツの輝度範囲をシステムに伝え、正しいマッピングを助ける

Core Graphics の ISO HDR サポート

08:00)Core Graphics には、ISO HDR 画像の読み書きサポートが追加されました。

import CoreGraphics

// HDR 画像のメタデータを読み取る
let source = CGImageSourceCreateWithURL(imageURL as CFURL, nil)
let properties = CGImageSourceCopyPropertiesAtIndex(source!, 0, nil) as? [String: Any]

// HDR 関連属性を確認
let isHDR = properties?[kCGImagePropertyHDRDictionary as String] != nil
let transferFunction = properties?[kCGImagePropertyHDRTransferFunction as String]
// "HLG" または "PQ"

// HDR 画像を書き込む
let destination = CGImageDestinationCreateWithURL(outputURL as CFURL,
                                                   UTType.heic.identifier as CFString,
                                                   1, nil)
let hdrProps: [String: Any] = [
    kCGImagePropertyHDRDictionary as String: [
        kCGImagePropertyHDRTransferFunction as String: "HLG",
        kCGImagePropertyHDRReferenceWhite as String: 203.0
    ]
]
CGImageDestinationAddImage(destination!, cgImage, hdrProps as CFDictionary)

キーポイント:

  • kCGImagePropertyHDRDictionary には HDR 固有のメタデータが含まれる
  • HLG と PQ の 2 種類の伝達関数に対応する
  • 10 ビットのビット深度が ISO HDR の最低要件

重要ポイント

1. 写真編集 App の HDR 書き出し

  • 何をするか: ユーザーが編集した写真を HDR として書き出せるようにし、ハイライトの細部を保持する
  • 取り組む価値: iPhone 15 Pro シリーズのユーザーが撮影する写真は HDR が増えており、編集後に SDR でしか書き出せないと元データを活かせない
  • 始め方: CGImageDestination を使って HEIF を書き出し、kCGImagePropertyHDRDictionary メタデータを設定する

2. ギャラリー/ソーシャル App の HDR 表示

  • 何をするか: フィードと詳細ページで HDR 写真を自動認識し、正しく表示する
  • 取り組む価値: SwiftUI Image と UIKit UIImageView はすでに自動対応しているため、メタデータを壊さないことを確認すればよい
  • 始め方: 画像読み込みフローを確認し、HDR メタデータが失われないようにする。UIImageView では preferredImageDynamicRange = .high を設定する

3. カメラ App の HDR 撮影プレビュー

  • 何をするか: ビューファインダーで HDR 効果をリアルタイム表示し、ユーザーが最終的な見え方を確認できるようにする
  • 取り組む価値: HDR プレビューは構図を決めるときの露出判断を助け、特に逆光シーンで有効
  • 始め方: AVCaptureVideoPreviewLayer を使い、wantsExtendedDynamicRangeContent = true を設定する

4. ProRAW から HDR アルバムを一括生成

  • 何をするか: ユーザーの ProRAW 写真を、共有しやすい HDR HEIF へ一括変換する
  • 取り組む価値: ProRAW ファイルは大きい(25MB+)一方、HDR HEIF は数 MB で、共有と保存に向いている
  • 始め方: CIImage(contentsOf:options:) で ProRAW を読み込み、CGImageDestination で HDR メタデータ付き HEIF として書き出す

関連セッション

コメント

GitHub Issues · utterances