-
Notifications
You must be signed in to change notification settings - Fork 48
fix primaries used for display p3 gamut #331
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -89,15 +89,15 @@ void ShepardsIDW::fillShepardsIDW(float* weights, int incR, int incB) { | |
| // sRGB transformations | ||
|
|
||
| // See IEC 61966-2-1/Amd 1:2003, Equation F.7. | ||
| static const float kSrgbR = 0.2126f, kSrgbG = 0.7152f, kSrgbB = 0.0722f; | ||
| static const float kSrgbR = 0.212639f, kSrgbG = 0.715169f, kSrgbB = 0.072192f; | ||
|
|
||
| float srgbLuminance(Color e) { return kSrgbR * e.r + kSrgbG * e.g + kSrgbB * e.b; } | ||
|
|
||
| // See ITU-R BT.709-6, Section 3. | ||
| // Uses the same coefficients for deriving luma signal as | ||
| // IEC 61966-2-1/Amd 1:2003 states for luminance, so we reuse the luminance | ||
| // function above. | ||
| static const float kSrgbCb = 1.8556f, kSrgbCr = 1.5748f; | ||
| static const float kSrgbCb = (2 * (1 - kSrgbB)), kSrgbCr = (2 * (1 - kSrgbR)); | ||
|
|
||
| Color srgbRgbToYuv(Color e_gamma) { | ||
| float y_gamma = srgbLuminance(e_gamma); | ||
|
|
@@ -121,15 +121,14 @@ float srgbInvOetf(float e_gamma) { | |
| if (e_gamma <= 0.04045f) { | ||
| return e_gamma / 12.92f; | ||
| } else { | ||
| return pow((e_gamma + 0.055f) / 1.055f, 2.4); | ||
| return pow((e_gamma + 0.055f) / 1.055f, 2.4f); | ||
| } | ||
| } | ||
|
|
||
| Color srgbInvOetf(Color e_gamma) { | ||
| return {{{srgbInvOetf(e_gamma.r), srgbInvOetf(e_gamma.g), srgbInvOetf(e_gamma.b)}}}; | ||
| } | ||
|
|
||
| // See IEC 61966-2-1, Equations F.5 and F.6. | ||
| float srgbInvOetfLUT(float e_gamma) { | ||
| int32_t value = static_cast<int32_t>(e_gamma * (kSrgbInvOETFNumEntries - 1) + 0.5); | ||
| // TODO() : Remove once conversion modules have appropriate clamping in place | ||
|
|
@@ -142,24 +141,25 @@ Color srgbInvOetfLUT(Color e_gamma) { | |
| return {{{srgbInvOetfLUT(e_gamma.r), srgbInvOetfLUT(e_gamma.g), srgbInvOetfLUT(e_gamma.b)}}}; | ||
| } | ||
|
|
||
| // See IEC 61966-2-1/Amd 1:2003, Equations F.10 and F.11. | ||
| float srgbOetf(float e) { | ||
| constexpr float kThreshold = 0.0031308; | ||
| constexpr float kLowSlope = 12.92; | ||
| constexpr float kHighOffset = 0.055; | ||
| constexpr float kPowerExponent = 1.0 / 2.4; | ||
| constexpr float kThreshold = 0.0031308f; | ||
| constexpr float kLowSlope = 12.92f; | ||
| constexpr float kHighOffset = 0.055f; | ||
| constexpr float kPowerExponent = 1.0f / 2.4f; | ||
| if (e <= kThreshold) { | ||
| return kLowSlope * e; | ||
| } | ||
| return (1.0 + kHighOffset) * std::pow(e, kPowerExponent) - kHighOffset; | ||
| return (1.0f + kHighOffset) * std::pow(e, kPowerExponent) - kHighOffset; | ||
| } | ||
|
|
||
| Color srgbOetf(Color e) { return {{{srgbOetf(e.r), srgbOetf(e.g), srgbOetf(e.b)}}}; } | ||
|
|
||
| //////////////////////////////////////////////////////////////////////////////// | ||
| // Display-P3 transformations | ||
|
|
||
| // See SMPTE EG 432-1, Equation 7-8. | ||
| static const float kP3R = 0.20949f, kP3G = 0.72160f, kP3B = 0.06891f; | ||
| // See SMPTE EG 432-1, Equation G-7. | ||
| static const float kP3R = 0.2289746f, kP3G = 0.6917385f, kP3B = 0.0792869f; | ||
|
|
||
| float p3Luminance(Color e) { return kP3R * e.r + kP3G * e.g + kP3B * e.b; } | ||
|
|
||
|
|
@@ -190,14 +190,14 @@ Color p3YuvToRgb(Color e_gamma) { | |
| // BT.2100 transformations - according to ITU-R BT.2100-2 | ||
|
|
||
| // See ITU-R BT.2100-2, Table 5, HLG Reference OOTF | ||
| static const float kBt2100R = 0.2627f, kBt2100G = 0.6780f, kBt2100B = 0.0593f; | ||
| static const float kBt2100R = 0.2627f, kBt2100G = 0.677998f, kBt2100B = 0.059302f; | ||
|
|
||
| float bt2100Luminance(Color e) { return kBt2100R * e.r + kBt2100G * e.g + kBt2100B * e.b; } | ||
|
|
||
| // See ITU-R BT.2100-2, Table 6, Derivation of colour difference signals. | ||
| // BT.2100 uses the same coefficients for calculating luma signal and luminance, | ||
| // so we reuse the luminance function here. | ||
| static const float kBt2100Cb = 1.8814f, kBt2100Cr = 1.4746f; | ||
| static const float kBt2100Cb = (2 * (1 - kBt2100B)), kBt2100Cr = (2 * (1 - kBt2100R)); | ||
|
|
||
| Color bt2100RgbToYuv(Color e_gamma) { | ||
| float y_gamma = bt2100Luminance(e_gamma); | ||
|
|
@@ -239,7 +239,7 @@ Color bt2100YuvToRgb(Color e_gamma) { | |
| } | ||
|
|
||
| // See ITU-R BT.2100-2, Table 5, HLG Reference OETF. | ||
| static const float kHlgA = 0.17883277f, kHlgB = 0.28466892f, kHlgC = 0.55991073; | ||
| static const float kHlgA = 0.17883277f, kHlgB = 0.28466892f, kHlgC = 0.55991073f; | ||
|
|
||
| float hlgOetf(float e) { | ||
| if (e <= 1.0f / 12.0f) { | ||
|
|
@@ -286,9 +286,11 @@ Color hlgInvOetfLUT(Color e_gamma) { | |
| return {{{hlgInvOetfLUT(e_gamma.r), hlgInvOetfLUT(e_gamma.g), hlgInvOetfLUT(e_gamma.b)}}}; | ||
| } | ||
|
|
||
| // 1.2f + 0.42 * log(kHlgMaxNits / 1000) | ||
| // See ITU-R BT.2100-2, Table 5, Note 5f | ||
| // Gamma = 1.2 + 0.42 * log(kHlgMaxNits / 1000) | ||
| static const float kOotfGamma = 1.2f; | ||
|
|
||
| // See ITU-R BT.2100-2, Table 5, HLG Reference OOTF | ||
| Color hlgOotf(Color e, LuminanceFn luminance) { | ||
| float y = luminance(e); | ||
| return e * std::pow(y, kOotfGamma - 1.0f); | ||
|
|
@@ -298,6 +300,7 @@ Color hlgOotfApprox(Color e, [[maybe_unused]] LuminanceFn luminance) { | |
| return {{{std::pow(e.r, kOotfGamma), std::pow(e.g, kOotfGamma), std::pow(e.b, kOotfGamma)}}}; | ||
| } | ||
|
|
||
| // See ITU-R BT.2100-2, Table 5, Note 5i | ||
| Color hlgInverseOotf(Color e, LuminanceFn luminance) { | ||
| float y = luminance(e); | ||
| return e * std::pow(y, (1.0f / kOotfGamma) - 1.0f); | ||
|
|
@@ -600,41 +603,43 @@ void putYuv444Pixel(uhdr_raw_image_t* image, size_t x, size_t y, Color& pixel) { | |
|
|
||
| //////////////////////////////////////////////////////////////////////////////// | ||
| // Color space conversions | ||
| // Sample, See, | ||
| // https://registry.khronos.org/DataFormat/specs/1.3/dataformat.1.3.html#_bt_709_bt_2020_primary_conversion_example | ||
|
|
||
| Color bt709ToP3(Color e) { | ||
| return {{{0.82254f * e.r + 0.17755f * e.g + 0.00006f * e.b, | ||
| 0.03312f * e.r + 0.96684f * e.g + -0.00001f * e.b, | ||
| 0.01706f * e.r + 0.07240f * e.g + 0.91049f * e.b}}}; | ||
| return {{{0.822462f * e.r + 0.177537f * e.g + 0.000001f * e.b, | ||
| 0.033194f * e.r + 0.966807f * e.g + -0.000001f * e.b, | ||
| 0.017083f * e.r + 0.072398f * e.g + 0.91052f * e.b}}}; | ||
| } | ||
|
|
||
| Color bt709ToBt2100(Color e) { | ||
| return {{{0.62740f * e.r + 0.32930f * e.g + 0.04332f * e.b, | ||
| 0.06904f * e.r + 0.91958f * e.g + 0.01138f * e.b, | ||
| 0.01636f * e.r + 0.08799f * e.g + 0.89555f * e.b}}}; | ||
| return {{{0.627404f * e.r + 0.329282f * e.g + 0.043314f * e.b, | ||
| 0.069097f * e.r + 0.919541f * e.g + 0.011362f * e.b, | ||
| 0.016392f * e.r + 0.088013f * e.g + 0.895595f * e.b}}}; | ||
| } | ||
|
|
||
| Color p3ToBt709(Color e) { | ||
| return {{{1.22482f * e.r + -0.22490f * e.g + -0.00007f * e.b, | ||
| -0.04196f * e.r + 1.04199f * e.g + 0.00001f * e.b, | ||
| -0.01961f * e.r + -0.07865f * e.g + 1.09831f * e.b}}}; | ||
| return {{{1.22494f * e.r + -0.22494f * e.g + 0.0f * e.b, | ||
| -0.042057f * e.r + 1.042057f * e.g + 0.0f * e.b, | ||
| -0.019638f * e.r + -0.078636f * e.g + 1.098274f * e.b}}}; | ||
| } | ||
|
|
||
| Color p3ToBt2100(Color e) { | ||
| return {{{0.75378f * e.r + 0.19862f * e.g + 0.04754f * e.b, | ||
| 0.04576f * e.r + 0.94177f * e.g + 0.01250f * e.b, | ||
| -0.00121f * e.r + 0.01757f * e.g + 0.98359f * e.b}}}; | ||
| return {{{0.753833f * e.r + 0.198597f * e.g + 0.04757f * e.b, | ||
| 0.045744f * e.r + 0.941777f * e.g + 0.012479f * e.b, | ||
| -0.00121f * e.r + 0.017601f * e.g + 0.983608f * e.b}}}; | ||
| } | ||
|
|
||
| Color bt2100ToBt709(Color e) { | ||
| return {{{1.66045f * e.r + -0.58764f * e.g + -0.07286f * e.b, | ||
| -0.12445f * e.r + 1.13282f * e.g + -0.00837f * e.b, | ||
| -0.01811f * e.r + -0.10057f * e.g + 1.11878f * e.b}}}; | ||
| return {{{1.660491f * e.r + -0.587641f * e.g + -0.07285f * e.b, | ||
| -0.124551f * e.r + 1.1329f * e.g + -0.008349f * e.b, | ||
| -0.018151f * e.r + -0.100579f * e.g + 1.11873f * e.b}}}; | ||
| } | ||
|
|
||
| Color bt2100ToP3(Color e) { | ||
| return {{{1.34369f * e.r + -0.28223f * e.g + -0.06135f * e.b, | ||
| -0.06533f * e.r + 1.07580f * e.g + -0.01051f * e.b, | ||
| 0.00283f * e.r + -0.01957f * e.g + 1.01679f * e.b}}}; | ||
| return {{{1.343578f * e.r + -0.282179f * e.g + -0.061399f * e.b, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you double check if this matrix is correct? I use and got this: (maybe I am wrong)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the matrix multiplication seems to be wrong. The individual matrices are same as the ones i am using.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK I re-did the math with gemini and this time the result matches with yours. My previous result with chatGPT was wrong. Sorry for the confusion. |
||
| -0.065298f * e.r + 1.075788f * e.g + -0.01049f * e.b, | ||
| 0.002822f * e.r + -0.019598f * e.g + 1.016777f * e.b}}}; | ||
| } | ||
|
|
||
| // All of these conversions are derived from the respective input YUV->RGB conversion followed by | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.