Windows の HDR ディスプレイへ OpenEXR を 8-bit SDR に潰さず表示するための、 .NET 10 / Direct3D 11 ベースのライブラリと最小 WPF ビューアーです。
現在は
0.1.0の初期実装です。Core の CPU 処理と Windows 上の D3D11 初期化は自動テストできますが、個々の HDR パネルでの見え方、EDID の輝度値、 色管理は実機で確認してください。
| Project | Role |
|---|---|
HdrImage.Core |
UI 非依存の EXR 読み込み、RGBA half データ、メタデータ、統計、露出、Reinhard/ACES SDR トーンマッピング |
HdrImage.Direct3D |
D3D11、FP16 テクスチャ、FP16 flip-model scRGB スワップチェーン、DXGI HDR 判定、描画 |
HdrImage.Viewer |
動作確認用 WPF GUI。Direct3D の詳細は子 HWND ホスト内へ隠蔽 |
HdrImage.Tests |
Core、EXR、フォールバック、リソース所有権の単体テスト |
Core は WPF/WinUI に依存しません。Direct3D 層の公開境界は HWND、
HdrImageData、DisplaySettings です。
- Windows 10 version 2004 (build 19041) 以降
- .NET 10 SDK
- Direct3D 11 対応 GPU/ドライバー
- HDR 表示には Windows の「HDR を使用する」が有効な HDR ディスプレイ
dotnet restore HdrImage.slnx
dotnet build HdrImage.slnx
dotnet test HdrImage.Tests/HdrImage.Tests.csproj
dotnet run --project HdrImage.ViewerNuGet パッケージ候補は次で作成できます。
dotnet pack HdrImage.Core/HdrImage.Core.csproj -c Release -o artifactsPackageId, Description, RepositoryUrl, PackageTags, MIT ライセンス、
README、シンボルパッケージを設定済みです。公開前に
RepositoryUrl=https://github.com/yopur/HdrImage が実際の公開先と一致するか
確認してください。
using HdrImage.Core;
HdrImageData image = await HdrImageLoader.LoadAsync("image.exr");
Console.WriteLine(image.Width);
Console.WriteLine(image.Height);
Console.WriteLine(image.PixelFormat);
Console.WriteLine(image.Statistics.MaxChannelValue);
Console.WriteLine(image.IsLikelyHdr);
HdrImageData adjusted = image.ApplyExposure(1.5f);
SdrImageData preview = adjusted.ToneMap(
ToneMappingOperator.Aces,
new ToneMappingOptions
{
Exposure = 0.0f,
Gamma = 2.2f
});HdrImageData.Pixels は interleaved RGBA Half (System.Half) です。EXR
デコーダーの float 出力から half へ変換しますが、途中で 8-bit UNORM や PNG
を経由しません。EXR の FLOAT チャンネルも表示用内部形式に合わせて half
精度へ量子化され、half の有限範囲を超える値は ±65504 に制限されます。
Windows の Advanced Color 合成空間は linear BT.709/sRGB primaries の scRGB
と FP16 を使います。スワップチェーンは
DXGI_FORMAT_R16G16B16A16_FLOAT、色空間は
DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709、flip discard です。
既定値:
| Setting | Default | Meaning |
|---|---|---|
Exposure |
0 EV | EXR の scene-linear 値へ 2^EV を乗算 |
PaperWhiteNits |
203 nit | EXR の 1.0 を拡散白として表示するときのユーザー指定ターゲット |
PeakBrightnessNits |
1000 nit | HDR 出力の上限 |
ReferenceWhiteNits |
80 nit | Windows scRGB の基準白 |
HDR shader の概略は次です。
scRGB = EXR_linear × 2^Exposure × PaperWhiteNits / ReferenceWhiteNits
203 nit は Windows デスクトップ HDR で一般的な約 200 nit の SDR/拡散白を 初期値にしたものです。80 nit は Windows の scRGB nominal reference white です。EXR の 1.0 が本質的に 80 nit、100 nit、203 nit のいずれかを意味する とは仮定していません。 EXR は scene-referred、display-referred、または 単なる演算用バッファである可能性があるため、4 設定を表示時の解釈として 明示的に保持します。
Windows HDR が対象モニターで無効なら、PreferHdr=true でも ACES または
Reinhard の SDR トーンマッピングへ自動フォールバックします。対象モニターは
ウィンドウとの重なり面積が最大の DXGI output です。
- 明示的な輝度関連メタデータがあれば HDR の根拠にします。
- それがなければ floating-point RGB の有限値を解析し、1.0 超または負値を含む 場合に「likely HDR」と推定します。
- EXR という拡張子だけでは HDR と断定しません。
- 16-bit PNG のような高ビット深度整数は、それだけでは HDR と判定しません。
- 非有限値は統計から除外し、件数を別に表示します。
この判定はコンテンツの意味を保証するものではありません。正規化範囲内の scene-linear EXR は HDR であっても推定できない場合があります。
Open EXR…またはドラッグ&ドロップで EXR を開く- Exposure を -10 EV から +10 EV まで変更
- HDR output の有効/無効を切り替え
- Reinhard / ACES Filmic を切り替え
- Paper white / Peak / Reference white を変更
- リサイズ時は黒帯を使いアスペクト比を維持
FullscreenボタンまたはF11で、ツールバー・情報パネル・ステータスを すべて隠した画像専用の全画面表示。Escで解除- 全画面時は WPF の最大化余白を使わず、現在のモニターの物理ピクセル境界へ 枠なしウィンドウを正確に合わせる
- 読み込み・描画エラーはステータスとダイアログへ表示
SDR/HDR Compare を有効にすると、同じFP16テクスチャと同じ画像座標を使って
GPU shader内で表示だけを分岐します。Coreの画像データやpublic APIは変更しません。
- 左: ACES FilmicまたはReinhardによるSDRシミュレーション
- 右: 既存のPaper White / Peak / Reference Whiteを使うHDR scRGB
- 黄色の境界付近を左右へドラッグして分割位置を変更
- ExposureとZoomは左右で共有
SDR whiteはSDR側の最大白レベル。scRGB上で指定nitへ制限- Spaceを押している間は全面SDR、離すと全面HDR
Splitで左右分割へ戻る
比較中は画面上部へ現在のモード、分割位置、tone mapper、SDR White、Zoom、 Windows HDR状態を常時表示します。このSDR側はWindows HDR合成空間内での シミュレーションであり、Windowsやディスプレイを物理的にHDR OFFへ変更した 状態とは完全には一致しません。Windows HDRが無効な場合、HDR比較は利用不可と 明示し、安全なSDRフォールバックを表示します。
スクリーンショットを README に載せる場合は、利用権のある EXR を開いた状態で
docs/screenshots/viewer.png を作成し、次の行をこの README に追加してください。
サンプル EXR はリポジトリへ含めません。
- 現在の高レベル loader は最初の flat RGBA 表示を対象にします。deep EXR は 明示的なエラーです。multipart/layer UI は未実装です。
- source channel type、sampling、linear flag、選択された custom attributes は
保持します。
chromaticitiesがあることは示しますが、初期版の shader は source primaries から scRGB primaries への完全な色変換をまだ行いません。 - alpha は保持しますが、ビューアーの swap chain は不透明です。
- SDR の
SdrImageDataはガンマ符号化 8-bit RGBA です。PNG 書き出しを追加する 場合はこの SDR 結果だけを入力とし、HDR 原画像の保存形式とは扱いません。 - GUI 初期化に失敗しても WPF ウィンドウは維持し、原因を status bar に表示します。
- TinyEXR.NET 1.1.0 (MIT): 純 C# の OpenEXR 読み書き
- Vortice.Windows 3.8.3 (MIT): Direct3D 11、DXGI、D3DCompiler の managed bindings
設計根拠は Microsoft の
DirectX advanced color and HDR guidance
および
IDXGISwapChain3::SetColorSpace1
に従っています。
MIT。外部ライブラリとトーンマッピング式の帰属情報は THIRD-PARTY-NOTICES.md を参照してください。