ハイライト
Apple ディスプレイおよびカラー テクノロジー チームは、iOS および iPadOS で EDR (拡張ダイナミック レンジ) のネイティブ サポートを導入し、開発者が SDR ホワイト 1.0 を超えるピクセル値を使用して、iPhone および iPad の HDR ディスプレイ上でより明るく、より飽和したコンテンツをレンダリングできるようにしました。
主要内容
多くのアプリはすでに HDR 写真やビデオを処理できますが、レンダリング側が最後のステップで停止することがよくあります。ファイル内にはハイライトディテールがありますが、表示時にはSDR白以内に抑えられています。炎、太陽の反射、金属のハイライトはすべてデータ内に残っていますが、画面上で平らに切り取られたように見えます。
EDR (拡張ダイナミック レンジ) はこのステップを解決します。 SDR コンテンツを 0 から 1 のスケールで配置し続け、SDR ホワイトより上の明るさを 1 より上に配置します。このようにして、浮動小数点ピクセル表現の同じセットで、SDR ボディと HDR ハイライトの両方をホストできます (00:24)。
このセッションの新機能は、EDR API が iOS と iPadOS に導入されたことです (02:20)。レンダリング パイプラインがすでに macOS で使用されている場合CAMetalLayerEDR をエクスポートする場合、コア スイッチ、ピクセル フォーマット、およびカラー スペースの考え方は、iPhone および iPad に移行する場合と同じままです。
Apple はまた、12.9 インチ iPad Pro にプロフェッショナルなカラー ワークフローをこのリンクに導入します。リファレンス モードでは、SDR ピークを 100 nit に固定し、HDR ピークを 1000 nit に固定し、EDR ヘッドルームを 10 倍にし、True Tone、自動輝度、Night Shift などの動的ディスプレイ調整をオフにします (02:40)。 Sidecar は、リファレンス モードで iPad Pro を Apple Silicon Mac のリファレンス ディスプレイとして使用することもできます (04:37)。
詳細
1. EDR ピクセル値はどのように明るさを表しますか?
(06:09) 従来の SDR 浮動小数点表現では、0 が黒、1 が SDR 白として扱われます。 EDR は次の範囲に従います。0 ~ 1 は依然として SDR コンテンツであり、1 を超える値は SDR ホワイトよりも明るいコンテンツを表します。
let sdrWhite: Float = 1.0
let campfireHighlight: Float = 2.4
let displayableHighlight = min(campfireHighlight, screen.currentEDRHeadroom)
キーポイント:
sdrWhiteトランスクリプトの EDR 1.0 に対応し、SDR ホワイトです。 -campfireHighlightは、ハイライトを 1 より大きい浮動小数点値として表す概念的な例です。 -screen.currentEDRHeadroomiOS 上の現在のヘッドルームをクエリするための API です。セッションはこれを使用して、現在のディスプレイ環境がどの程度明るくできるかを決定します。 -minデフォルトの EDR 動作を表すコア制約: 現在のヘッドルームを超える値はクリップされます。
EDR値は線形空間で表現されます。2.0EDR は視覚的に 2 倍明るいわけではありません。セッションは、EDR が HDR 値を 0 から 1 に戻すトーン マップを行わないことを特に強調しています。 0 から 1 までの SDR コンテンツは常に表示でき、1 を超えるコンテンツは現在のヘッドルーム内に表示され、余分な部分はトリミングされます (06:24)。
2. HDR 画像を浮動小数点ビットマップにデコードします
(08:18) ワークフロー例は、HDR 静止画像から始まります。通常、元のイメージは二平面 YUV です。この形式を直接操作するのは難しいため、セッションは最初に Image I/O を使用して読み出します。CGImage、次に使用しますCGBitmapContextMetal により適した 16 ビット浮動小数点ビットマップに変換します。
// Create CGImage from HDR Image
let isr = CGImageSourceCreateWithURL(HDRImageURL, nil)
let img = CGImageSourceCreateImageAtIndex(isr, 0, nil)
// Draw into floating point bitmap context
let width = img.width
let height = img.height
let info = CGBitmapInfo(rawValue: kCGBitmapByteOrder16Host |CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.floatComponents.rawValue)
let ctx = CGContext(data: nil, width: width, height: height, bitsPerComponent: 16,
bytesPerRow: 0, space: layer.colorspace, bitmapInfo: info.rawValue)
ctx?.draw(in: img,
image: CGRect(x: 0, y: 0, width: CGFloat(width), height: CGFloat(height)))
キーポイント:
CGImageSourceCreateWithURLHDR 画像 URL から画像 I/O ソースを作成します。 -CGImageSourceCreateImageAtIndexソースから最初のものを取得しますCGImage。widthそしてheightから直接CGImage、同じサイズのビットマップを作成するために使用されます。 -CGBitmapInfo.floatComponentsビットマップが浮動小数点コンポーネントを使用することを指定します。 -bitsPerComponent: 16浮動小数点コンポーネントと組み合わせると、16 ビット浮動小数点コンテキストが得られます。 -space: layer.colorspaceビットマップ コンテキストのカラー スペースを、後でレンダリングするカラー スペースと一致させます。CAMetalLayer。ctx?.drawバンドルCGImageデコードして浮動小数点ビットマップ コンテキストに描画します。
一部の HDR 形式で浮動小数点バッファを生成する必要がある場合、セッションでは新しい浮動小数点バッファを設定できると述べられています。kCGImageSourceShouldAllowFloatオプション (09:35)。
3. ビットマップ データをメタル テクスチャにロードします
(10:28) ビットマップはすでに 16 ビット浮動小数点形式であり、メタル テクスチャも一致する形式を選択する必要があります。セッションの使用例.rgba16Float。
// Create floating point texture
let desc = MTLTextureDescriptor()
desc.pixelFormat = .rgba16Float
desc.textureType = .type2D
let texture = layer.device.makeTexture(descriptor: desc)
// Load EDR bitmap into texture
let data = ctx.data
texture.replace(region: MTLRegionMake2D(0, 0, width, height),
mipmapLevel: 0,
withBytes: &data,
bytesPerRow: ctx.bytesPerRow)
キーポイント:
MTLTextureDescriptor()作成するメタルテクスチャを記述します。 -desc.pixelFormat = .rgba16Floatテクスチャに半精度浮動小数点 RGBA を使用させ、前のビットマップ コンテキストと一致させます。 -desc.textureType = .type2Dこれが 2D テクスチャであることを示します。 -layer.device.makeTexture使用CAMetalLayerMetal デバイスはテクスチャを作成します。 -ctx.dataビットマップ コンテキストの背後にあるピクセル データを取得します。 -texture.replaceビットマップ全体をメタル テクスチャにコピーします。 -bytesPerRow: ctx.bytesPerRowソースビットマップの行範囲を維持します。
この時点で、アプリには EDR 値を含む Metal テクスチャがすでにあり、独自の Metal パイプラインでレンダリングできます (11:08)。
4. CAMetalLayer で EDR を有効にする
(11:27) iOS と iPadOS は macOS と同じ方法でオンになります。CAMetalLayer、開けるwantsExtendedDynamicRangeContent、EDR をサポートするピクセル形式と色空間を選択します。
// Opt into using EDR
var layer = CAMetalLayer()
layer?.wantsExtendedDynamicRangeContent = true
// Use supported pixel format and color spaces
layer.pixelFormat = MTLPixelFormatRGBA16Float
layer.colorspace = CGColorSpace(name: kCGColorSpaceExtendedLinearDisplayP3)
キーポイント:
CAMetalLayerこのレンダリング パスの出力レイヤーです。 -wantsExtendedDynamicRangeContent = trueレイヤーが EDR レンダリングに明示的に入るようにします。 -pixelFormatコンテンツのフォーマットに合わせるため。この例では 16 ビット浮動小数点を使用しています。 -kCGColorSpaceExtendedLinearDisplayP3拡張リニア表示P3です。- セッションでは、線形色空間を使用する場合は拡張バリアントを使用し、それ以外の場合はコンテンツが SDR にクリップされることを強調しました (12:22)。
iOS は、2 種類の EDR レンダリングの組み合わせをサポートしています。線形色空間を使用した 16 ビット浮動小数点ピクセル バッファーと、PQ または HLG 色空間を使用した 10 ビット パック BGRA ピクセル バッファーです (12:22)。
5. ヘッドルームに基づいてレンダリング戦略を決定する
(13:11) EDR で使用できる輝度は固定値ではありません。現在のヘッドルームは、デバイスのディスプレイ技術や画面の明るさなどの要因に影響されます。 iOS は関連クエリをUIScreen優れた。
// Query potential headroom
let screen = windowScene.screen
let maxPotentialEDR = screen.potentialEDRHeadroom
if (maxPotentialEDR < 1.5) {
// SDR path
}
// Query current headroom
func draw(_ rect: CGRect) {
let maxEDR = screen.currentEDRHeadroom
// Tone-map to maxEDR
}
// Register for Reference Mode notifications
let notification = NotificationCenter.default
notification.addObserver(self,
selector: #selector(screenChangedEvent(_:)),
name: UIScreen.referenceDisplayModeStatusDidChangeNotification,
object: nil)
// Query for latest status and headroom
func screenChangedEvent(_ notification: Notification?) {
let status = screen.referenceDisplayModeStatus
let maxPotentialEDR = screen.potentialEDRHeadroom
}
キーポイント:
windowScene.screen現在のシーンの位置を取得するUIScreen。potentialEDRHeadroomこのディスプレイが提供できる最大ヘッドルームを示します。 -maxPotentialEDR < 1.5これは戦略的な判断です。潜在的なヘッドルームが低すぎる場合は、SDR パスを選択して処理コストを節約できます。 -currentEDRHeadroom描画呼び出しでの読み取りに適した、現時点で利用可能なヘッドルームを示します。 -UIScreen.referenceDisplayModeStatusDidChangeNotification通知は、リファレンス モードの状態が変化したときに送信されます。 -referenceDisplayModeStatusリファレンス モードが有効か、制限されているか、有効ではないか、サポートされていないかをアプリに伝えます。
UIScreenEDR ヘッドルーム変更通知はありません。セッションの提案は、レンダリング コールバックでクエリすることです。currentEDRHeadroom、リファレンス モードの状態が変化したときに状態と潜在的なヘッドルームを再度読み取ります (14:17)。
6. CAEDRMetadata を使用してシステム トーン マッピングを引き渡す
(16:24) ビデオ コンテンツを処理している場合、アプリは Apple の組み込みトーン マッピングを使用できます。入り口は、CAEDRMetadata、HLG および HDR10 のメタデータ構築方法を提供します。
// Check if EDR metadata is available
let isAvailable = CAEDRMetadata.isAvailable
// Instantiate EDR metadata
// ...
// Apply EDR metadata to layer
let layer: CAMetalLayer? = nil
layer?.edrMetadata = metadata
キーポイント:
CAEDRMetadata.isAvailable現在のプラットフォームがこの一連のトーン マッピング機能をサポートしているかどうかを確認するために使用されます。 -metadataHLG または HDR10 コンストラクターによって作成された EDR メタデータを表します。 -layer?.edrMetadata = metadataメタデータを次のように設定しますCAMetalLayer。- 設定後、このレイヤーにレンダリングされたコンテンツは、メタデータに従ってシステム トーン マッパーによって処理されます。
HLG では、メタデータの構築時にパラメーターは必要ありません。 HDR10 には 2 つのコンストラクターがあります。1 つは最小輝度、最大輝度、およびマスタリング表示を渡します。opticalOutputScale; MasterDisplayColourVolume SEI、ContentLightLevelInformation SEI、およびopticalOutputScale(17:22)。
// HLG
let edrMetadata = CAEDRMetadata.hlg
// HDR10 (Mastering Display luminance)
let edrMetaData = CAEDRMetadata.hdr10(minLuminance: minLuminance,
maxLuminance: maxContentMasteringDisplayBrightness,
opticalOutputScale: outputScale)
// HDR10 (Supplemental Enhancement Information)
let edrMetaData = CAEDRMetadata.hdr10(displayInfo: displayData,
contentInfo: contentInfo,
opticalOutputScale: outputScale)
キーポイント:
CAEDRMetadata.hlgHLG 色空間のコンテンツ。 -hdr10(minLuminance:maxLuminance:opticalOutputScale:)マスタリング ディスプレイの輝度情報を使用して、HDR10 コンテンツを説明します。 -minLuminanceそしてmaxLuminance単位はニットです。 -opticalOutputScaleEDR 1.0 が何 nit に対応するかを説明します。セッションでは、通常は 100 に設定されていると述べています。 -hdr10(displayInfo:contentInfo:opticalOutputScale:)コンテンツに付属する SEI メッセージを使用する方が、作成者の意図を保持するのに適しています。
重要ポイント
-
**HDR 写真比較ビューアを作成します。 ** ユーザーは同じ写真上で SDR 表示と EDR 表示を切り替えることができます。 EDRが有効な場合に使用されます
CAMetalLayer.wantsExtendedDynamicRangeContentそして.rgba16Floatテクスチャー。オフにすると、ハイライトが SDR パスにプッシュされます。これにより、ハイライトの詳細が画像データに残っているかどうかを直感的に確認できます。 -
**リファレンス モードのステータス プロンプトをビデオ編集アプリに追加します。 ** 12.9 インチ iPad Pro で監視
UIScreen.referenceDisplayModeStatusDidChangeNotification。ステータスが有効な場合、参照プレビューが表示されます。ステータスが制限されている場合、現在の環境では参照応答を保証できないことをユーザーに通知します。 -
**ヘッドルームを押すと、レンダリング コストが自動的に選択されます。 ** レンダリング前にお読みください
potentialEDRHeadroom。潜在的なヘッドルームが低すぎる場合は、SDR プレビューに進みます。十分であれば、浮動小数点テクスチャをロードして読み取ります。currentEDRHeadroomトーンマッピングを行います。 -
**システム トーン マッピングを HDR10 再生レイヤーに追加します。 ** コンテンツにマスタリング表示または SEI メタデータが含まれている場合は、最初に確認してください
CAEDRMetadata.isAvailable、次に HDR10 メタデータを作成し、それを次のように設定します。CAMetalLayer.edrMetadata、トーン マッピングを自分で実装するコストを削減します。
関連セッション
- Core Image、Metal、および SwiftUI を使用した EDR コンテンツの表示 — Core Image、SwiftUI、および Metal ビュー アーキテクチャで EDR コンテンツを表示する方法について引き続き説明します。
- EDR を使用した HDR レンダリングを探索する - macOS 上の EDR レンダリング モデルと API を紹介します。これは、この分野の iOS API を理解するための前提条件となります。
- AVFoundation を使用した HDR ビデオの編集と再生 — HDR ビデオの再生と編集における色空間、伝達関数、メタデータについて説明します。
コメント
GitHub Issues · utterances