diff options
Diffstat (limited to 'gfx/gl/Colorspaces.h')
-rw-r--r-- | gfx/gl/Colorspaces.h | 128 |
1 files changed, 88 insertions, 40 deletions
diff --git a/gfx/gl/Colorspaces.h b/gfx/gl/Colorspaces.h index 8f36854d2d..062897d2dd 100644 --- a/gfx/gl/Colorspaces.h +++ b/gfx/gl/Colorspaces.h @@ -42,19 +42,27 @@ typedef struct _qcms_profile qcms_profile; namespace mozilla::color { +// - + struct YuvLumaCoeffs final { float r = 0.2126; float g = 0.7152; float b = 0.0722; auto Members() const { return std::tie(r, g, b); } - INLINE_AUTO_MAPPABLE(YuvLumaCoeffs) + MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(YuvLumaCoeffs) static constexpr auto Rec709() { return YuvLumaCoeffs(); } static constexpr auto Rec2020() { - return YuvLumaCoeffs{0.2627, 0.6780, 0.0593}; + return YuvLumaCoeffs{ + .r = 0.2627, + .g = 0.6780, + .b = 0.0593, + }; } + + static constexpr auto Gbr() { return YuvLumaCoeffs{.r = 0, .g = 1, .b = 0}; } }; struct PiecewiseGammaDesc final { @@ -68,26 +76,26 @@ struct PiecewiseGammaDesc final { float k = 12.92; auto Members() const { return std::tie(a, b, g, k); } - INLINE_AUTO_MAPPABLE(PiecewiseGammaDesc) + MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(PiecewiseGammaDesc) static constexpr auto Srgb() { return PiecewiseGammaDesc(); } static constexpr auto DisplayP3() { return Srgb(); } static constexpr auto Rec709() { return PiecewiseGammaDesc{ - 1.099, - 0.018, - 1.0 / 0.45, // ~2.222 - 4.5, + .a = 1.099, + .b = 0.018, + .g = 1.0 / 0.45, // ~2.222 + .k = 4.5, }; } // FYI: static constexpr auto Rec2020_10bit() { return Rec709(); } static constexpr auto Rec2020_12bit() { return PiecewiseGammaDesc{ - 1.0993, - 0.0181, - 1.0 / 0.45, // ~2.222 - 4.5, + .a = 1.0993, + .b = 0.0181, + .g = 1.0 / 0.45, // ~2.222 + .k = 4.5, }; } }; @@ -99,21 +107,21 @@ struct YcbcrDesc final { float uPlusHalf = 240 / 255.0; auto Members() const { return std::tie(y0, y1, u0, uPlusHalf); } - INLINE_AUTO_MAPPABLE(YcbcrDesc) + MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(YcbcrDesc) static constexpr auto Narrow8() { // AKA limited/studio/tv return YcbcrDesc(); } static constexpr auto Full8() { // AKA pc return YcbcrDesc{ - 0 / 255.0, - 255 / 255.0, - 128 / 255.0, - 254 / 255.0, + .y0 = 0 / 255.0, + .y1 = 255 / 255.0, + .u0 = 128 / 255.0, + .uPlusHalf = 254 / 255.0, }; } static constexpr auto Float() { // Best for a LUT - return YcbcrDesc{0.0, 1.0, 0.5, 1.0}; + return YcbcrDesc{.y0 = 0.0, .y1 = 1.0, .u0 = 0.5, .uPlusHalf = 1.0}; } }; @@ -129,7 +137,7 @@ struct Chromaticities final { static constexpr float wy = 0.3290; auto Members() const { return std::tie(rx, ry, gx, gy, bx, by); } - INLINE_AUTO_MAPPABLE(Chromaticities) + MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(Chromaticities) // - @@ -145,23 +153,32 @@ struct Chromaticities final { } static constexpr auto Rec601_525_Ntsc() { return Chromaticities{ - 0.630, 0.340, // r - 0.310, 0.595, // g - 0.155, 0.070, // b + .rx = 0.630, + .ry = 0.340, // r + .gx = 0.310, + .gy = 0.595, // g + .bx = 0.155, + .by = 0.070, // b }; } static constexpr auto Rec2020() { return Chromaticities{ - 0.708, 0.292, // r - 0.170, 0.797, // g - 0.131, 0.046, // b + .rx = 0.708, + .ry = 0.292, // r + .gx = 0.170, + .gy = 0.797, // g + .bx = 0.131, + .by = 0.046, // b }; } static constexpr auto DisplayP3() { return Chromaticities{ - 0.680, 0.320, // r - 0.265, 0.690, // g - 0.150, 0.060, // b + .rx = 0.680, + .ry = 0.320, // r + .gx = 0.265, + .gy = 0.690, // g + .bx = 0.150, + .by = 0.060, // b }; } }; @@ -173,7 +190,7 @@ struct YuvDesc final { YcbcrDesc ycbcr; auto Members() const { return std::tie(yCoeffs, ycbcr); } - INLINE_AUTO_MAPPABLE(YuvDesc); + MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(YuvDesc) }; struct ColorspaceDesc final { @@ -182,11 +199,30 @@ struct ColorspaceDesc final { std::optional<YuvDesc> yuv; auto Members() const { return std::tie(chrom, tf, yuv); } - INLINE_AUTO_MAPPABLE(ColorspaceDesc); + MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(ColorspaceDesc) }; // - +} // namespace mozilla::color + +#define _(X) \ + template <> \ + struct std::hash<X> : mozilla::StdHashMembers<X> {}; + +_(mozilla::color::YuvLumaCoeffs) +_(mozilla::color::PiecewiseGammaDesc) +_(mozilla::color::YcbcrDesc) +_(mozilla::color::Chromaticities) +_(mozilla::color::YuvDesc) +_(mozilla::color::ColorspaceDesc) + +#undef _ + +namespace mozilla::color { + +// - + template <class TT, int NN> struct avec final { using T = TT; @@ -336,6 +372,11 @@ auto max(const avec<T, N>& a, const avec<T, N>& b) { } template <class T, int N> +auto clamp(const avec<T, N>& v, const avec<T, N>& lo, const avec<T, N>& hi) { + return max(lo, min(v, hi)); +} + +template <class T, int N> auto floor(const avec<T, N>& a) { auto ret = avec<T, N>{}; for (int i = 0; i < ret.N; i++) { @@ -404,6 +445,11 @@ struct mat final { } } + constexpr bool operator==(const mat& rhs) const { + return this->rows == rhs.rows; + } + constexpr bool operator!=(const mat& rhs) const { return !(*this == rhs); } + const auto& at(const int x, const int y) const { return rows.at(y)[x]; } auto& at(const int x, const int y) { return rows.at(y)[x]; } @@ -722,17 +768,19 @@ inline float SampleOutByIn(const C& outByIn, const float in) { return outByIn.at(0); } MOZ_ASSERT(outByIn.size() >= 2); - const auto begin = outByIn.begin(); - - const auto in0i = size_t(floorf(in * (outByIn.size() - 1))); - const auto out0_itr = begin + std::min(in0i, outByIn.size() - 2); - - const auto in0 = float(out0_itr - begin) / (outByIn.size() - 1); - const auto out0 = *out0_itr; - const auto d_in = float(1) / (outByIn.size() - 1); - const auto d_out = *(out0_itr + 1) - *out0_itr; - const auto out = out0 + (d_out / d_in) * (in - in0); + // Estimate based on nearest (first) derivative: + // Find the nearest point to `in` in `outByIn`. + const auto inId = in * (outByIn.size() - 1); + const auto inId0F = std::clamp(floorf(inId), 0.f, float(outByIn.size() - 2)); + const auto inId0 = size_t(inId0F); + const auto out0 = outByIn.at(inId0 + 0); + const auto out1 = outByIn.at(inId0 + 1); + const auto d_inId0 = float(1); + const auto d_out0 = out1 - out0; + const auto d_inId = inId - inId0; + + const auto out = out0 + (d_out0 / d_inId0) * d_inId; // printf("SampleOutByIn(%f)->%f\n", in, out); return out; } @@ -963,7 +1011,7 @@ struct ColorProfileConversionDesc { }; static ColorProfileConversionDesc From(const FromDesc&); - vec3 Apply(const vec3 src) const { + vec3 DstFromSrc(const vec3 src) const { const auto srcRgb = vec3(srcRgbFromSrcYuv * vec4(src, 1)); const auto srcLinear = vec3{{ SampleOutByIn(srcLinearFromSrcTf.r, srcRgb.x()), |