diff options
| author | Carl Hetherington <cth@carlh.net> | 2022-05-05 17:38:48 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2022-05-05 18:53:39 +0200 |
| commit | 969c9c28c87e83f4e3fcb7b52a921773d363511f (patch) | |
| tree | 361713cfbb0246b75af7442f257375c27655083b | |
| parent | 504955b1e8036a25b1dc196625e530808ac42e99 (diff) | |
Use two LUTs.inaccurate-gamma
| -rw-r--r-- | src/gamma_transfer_function.cc | 5 | ||||
| -rw-r--r-- | src/gamma_transfer_function.h | 2 | ||||
| -rw-r--r-- | src/identity_transfer_function.cc | 3 | ||||
| -rw-r--r-- | src/identity_transfer_function.h | 2 | ||||
| -rw-r--r-- | src/modified_gamma_transfer_function.cc | 3 | ||||
| -rw-r--r-- | src/modified_gamma_transfer_function.h | 2 | ||||
| -rw-r--r-- | src/rgb_xyz.cc | 46 | ||||
| -rw-r--r-- | src/s_gamut3_transfer_function.cc | 3 | ||||
| -rw-r--r-- | src/s_gamut3_transfer_function.h | 2 | ||||
| -rw-r--r-- | src/transfer_function.cc | 8 | ||||
| -rw-r--r-- | src/transfer_function.h | 6 | ||||
| -rw-r--r-- | test/colour_conversion_test.cc | 4 |
12 files changed, 46 insertions, 40 deletions
diff --git a/src/gamma_transfer_function.cc b/src/gamma_transfer_function.cc index 1875221e..33513b78 100644 --- a/src/gamma_transfer_function.cc +++ b/src/gamma_transfer_function.cc @@ -55,13 +55,14 @@ GammaTransferFunction::GammaTransferFunction (double gamma) double * -GammaTransferFunction::make_lut (int bit_depth, bool inverse) const +GammaTransferFunction::make_lut (double from, double to, int bit_depth, bool inverse) const { int const bit_length = int(std::pow(2.0f, bit_depth)); auto lut = new double[bit_length]; double const gamma = inverse ? (1 / _gamma) : _gamma; for (int i = 0; i < bit_length; ++i) { - lut[i] = pow(double(i) / (bit_length - 1), gamma); + double const x = double(i) / (bit_length - 1); + lut[i] = pow((x * (to - from)) + from, gamma); } return lut; diff --git a/src/gamma_transfer_function.h b/src/gamma_transfer_function.h index 8402d6af..947fec66 100644 --- a/src/gamma_transfer_function.h +++ b/src/gamma_transfer_function.h @@ -58,7 +58,7 @@ public: bool about_equal (std::shared_ptr<const TransferFunction> other, double epsilon) const override; protected: - double * make_lut (int bit_depth, bool inverse) const override; + double * make_lut (double from, double to, int bit_depth, bool inverse) const override; private: double _gamma; diff --git a/src/identity_transfer_function.cc b/src/identity_transfer_function.cc index c01e6698..bd754c77 100644 --- a/src/identity_transfer_function.cc +++ b/src/identity_transfer_function.cc @@ -47,8 +47,9 @@ using std::dynamic_pointer_cast; using namespace dcp; +/* XXX */ double * -IdentityTransferFunction::make_lut (int bit_depth, bool) const +IdentityTransferFunction::make_lut (double, double, int bit_depth, bool) const { int const bit_length = int(std::pow(2.0f, bit_depth)); auto lut = new double[bit_length]; diff --git a/src/identity_transfer_function.h b/src/identity_transfer_function.h index de7a897a..918f6185 100644 --- a/src/identity_transfer_function.h +++ b/src/identity_transfer_function.h @@ -49,7 +49,7 @@ public: bool about_equal (std::shared_ptr<const TransferFunction> other, double epsilon) const override; protected: - double * make_lut (int bit_depth, bool inverse) const override; + double * make_lut (double from, double to, int bit_depth, bool inverse) const override; }; diff --git a/src/modified_gamma_transfer_function.cc b/src/modified_gamma_transfer_function.cc index 039e9284..e9b09a6d 100644 --- a/src/modified_gamma_transfer_function.cc +++ b/src/modified_gamma_transfer_function.cc @@ -57,8 +57,9 @@ ModifiedGammaTransferFunction::ModifiedGammaTransferFunction (double power, doub } +/* XXX */ double * -ModifiedGammaTransferFunction::make_lut (int bit_depth, bool inverse) const +ModifiedGammaTransferFunction::make_lut (double, double, int bit_depth, bool inverse) const { int const bit_length = int(std::pow(2.0f, bit_depth)); double* lut = new double[bit_length]; diff --git a/src/modified_gamma_transfer_function.h b/src/modified_gamma_transfer_function.h index 34904855..abc51e35 100644 --- a/src/modified_gamma_transfer_function.h +++ b/src/modified_gamma_transfer_function.h @@ -77,7 +77,7 @@ public: bool about_equal (std::shared_ptr<const TransferFunction>, double epsilon) const override; protected: - double * make_lut (int bit_depth, bool inverse) const override; + double * make_lut (double from, double to, int bit_depth, bool inverse) const override; private: double _power; diff --git a/src/rgb_xyz.cc b/src/rgb_xyz.cc index f2aaec8e..47b7a9ee 100644 --- a/src/rgb_xyz.cc +++ b/src/rgb_xyz.cc @@ -80,8 +80,8 @@ dcp::xyz_to_rgba ( int* xyz_y = xyz_image->data (1); int* xyz_z = xyz_image->data (2); - double const * lut_in = conversion.out()->lut (12, false); - double const * lut_out = conversion.in()->lut (16, true); + double const * lut_in = conversion.out()->lut("all", 0, 1, 12, false); + double const * lut_out = conversion.in()->lut("all", 0, 1, 16, true); boost::numeric::ublas::matrix<double> const matrix = conversion.xyz_to_rgb (); double fast_matrix[9] = { @@ -157,8 +157,8 @@ dcp::xyz_to_rgb ( int* xyz_y = xyz_image->data (1); int* xyz_z = xyz_image->data (2); - double const * lut_in = conversion.out()->lut (12, false); - double const * lut_out = conversion.in()->lut (16, true); + double const * lut_in = conversion.out()->lut("all", 0, 1, 12, false); + double const * lut_out = conversion.in()->lut("all", 0, 1, 16, true); auto const matrix = conversion.xyz_to_rgb (); double fast_matrix[9] = { @@ -237,23 +237,23 @@ dcp::combined_rgb_to_xyz (ColourConversion const & conversion, double* matrix) auto const bradford = conversion.bradford (); matrix[0] = (bradford (0, 0) * rgb_to_xyz (0, 0) + bradford (0, 1) * rgb_to_xyz (1, 0) + bradford (0, 2) * rgb_to_xyz (2, 0)) - * DCI_COEFFICIENT * 1048576; + * DCI_COEFFICIENT; matrix[1] = (bradford (0, 0) * rgb_to_xyz (0, 1) + bradford (0, 1) * rgb_to_xyz (1, 1) + bradford (0, 2) * rgb_to_xyz (2, 1)) - * DCI_COEFFICIENT * 1048576; + * DCI_COEFFICIENT; matrix[2] = (bradford (0, 0) * rgb_to_xyz (0, 2) + bradford (0, 1) * rgb_to_xyz (1, 2) + bradford (0, 2) * rgb_to_xyz (2, 2)) - * DCI_COEFFICIENT * 1048576; + * DCI_COEFFICIENT; matrix[3] = (bradford (1, 0) * rgb_to_xyz (0, 0) + bradford (1, 1) * rgb_to_xyz (1, 0) + bradford (1, 2) * rgb_to_xyz (2, 0)) - * DCI_COEFFICIENT * 1048576; + * DCI_COEFFICIENT; matrix[4] = (bradford (1, 0) * rgb_to_xyz (0, 1) + bradford (1, 1) * rgb_to_xyz (1, 1) + bradford (1, 2) * rgb_to_xyz (2, 1)) - * DCI_COEFFICIENT * 1048576; + * DCI_COEFFICIENT; matrix[5] = (bradford (1, 0) * rgb_to_xyz (0, 2) + bradford (1, 1) * rgb_to_xyz (1, 2) + bradford (1, 2) * rgb_to_xyz (2, 2)) - * DCI_COEFFICIENT * 1048576; + * DCI_COEFFICIENT; matrix[6] = (bradford (2, 0) * rgb_to_xyz (0, 0) + bradford (2, 1) * rgb_to_xyz (1, 0) + bradford (2, 2) * rgb_to_xyz (2, 0)) - * DCI_COEFFICIENT * 1048576; + * DCI_COEFFICIENT; matrix[7] = (bradford (2, 0) * rgb_to_xyz (0, 1) + bradford (2, 1) * rgb_to_xyz (1, 1) + bradford (2, 2) * rgb_to_xyz (2, 1)) - * DCI_COEFFICIENT * 1048576; + * DCI_COEFFICIENT; matrix[8] = (bradford (2, 0) * rgb_to_xyz (0, 2) + bradford (2, 1) * rgb_to_xyz (1, 2) + bradford (2, 2) * rgb_to_xyz (2, 2)) - * DCI_COEFFICIENT * 1048576; + * DCI_COEFFICIENT; } @@ -276,8 +276,10 @@ dcp::rgb_to_xyz ( double x, y, z; } d; - auto const * lut_in = conversion.in()->lut (12, false); - auto const * lut_out = conversion.out()->lut (20, true); + auto const * lut_in = conversion.in()->lut ("all", 0, 1, 12, false); + auto constexpr piece = 0.02; + auto const * lut_out_low = conversion.out()->lut("low_inv", 0, piece, 16, true); + auto const * lut_out_high = conversion.out()->lut("high_inv", piece, 1, 12, true); /* This is is the product of the RGB to XYZ matrix, the Bradford transform and the DCI companding */ double fast_matrix[9]; @@ -303,21 +305,21 @@ dcp::rgb_to_xyz ( /* Clamp */ - if (d.x < 0 || d.y < 0 || d.z < 0 || d.x > 1048576 || d.y > 1048576 || d.z > 1048576) { + if (d.x < 0 || d.y < 0 || d.z < 0 || d.x > 1 || d.y > 1 || d.z > 1) { ++clamped; } d.x = max (0.0, d.x); d.y = max (0.0, d.y); d.z = max (0.0, d.z); - d.x = min (1048576.0, d.x); - d.y = min (1048576.0, d.y); - d.z = min (1048576.0, d.z); + d.x = min (1.0, d.x); + d.y = min (1.0, d.y); + d.z = min (1.0, d.z); /* Out gamma LUT */ - *xyz_x++ = lrint (lut_out[lrint(d.x)] * 4095); - *xyz_y++ = lrint (lut_out[lrint(d.y)] * 4095); - *xyz_z++ = lrint (lut_out[lrint(d.z)] * 4095); + *xyz_x++ = lrint((d.x < piece ? lut_out_low[lrint((d.x / piece) * 65536)] : lut_out_high[lrint(((d.x - piece) / (1 - piece)) * 4096)]) * 4095); + *xyz_y++ = lrint((d.y < piece ? lut_out_low[lrint((d.y / piece) * 65536)] : lut_out_high[lrint(((d.y - piece) / (1 - piece)) * 4096)]) * 4095); + *xyz_z++ = lrint((d.z < piece ? lut_out_low[lrint((d.z / piece) * 65536)] : lut_out_high[lrint(((d.z - piece) / (1 - piece)) * 4096)]) * 4095); } } diff --git a/src/s_gamut3_transfer_function.cc b/src/s_gamut3_transfer_function.cc index edfbe2ad..c234b002 100644 --- a/src/s_gamut3_transfer_function.cc +++ b/src/s_gamut3_transfer_function.cc @@ -47,8 +47,9 @@ using std::dynamic_pointer_cast; using namespace dcp; +/* XXX */ double * -SGamut3TransferFunction::make_lut (int bit_depth, bool inverse) const +SGamut3TransferFunction::make_lut (double, double, int bit_depth, bool inverse) const { int const bit_length = int(std::pow(2.0f, bit_depth)); double* lut = new double[bit_length]; diff --git a/src/s_gamut3_transfer_function.h b/src/s_gamut3_transfer_function.h index 0d297e8b..4c3714b9 100644 --- a/src/s_gamut3_transfer_function.h +++ b/src/s_gamut3_transfer_function.h @@ -49,7 +49,7 @@ public: bool about_equal (std::shared_ptr<const TransferFunction> other, double epsilon) const override; protected: - double * make_lut (int bit_depth, bool inverse) const override; + double * make_lut (double from, double to, int bit_depth, bool inverse) const override; }; diff --git a/src/transfer_function.cc b/src/transfer_function.cc index 00968e2f..237f6844 100644 --- a/src/transfer_function.cc +++ b/src/transfer_function.cc @@ -62,15 +62,15 @@ TransferFunction::~TransferFunction () double const * -TransferFunction::lut (int bit_depth, bool inverse) const +TransferFunction::lut (std::string name, double from, double to, int bit_depth, bool inverse) const { boost::mutex::scoped_lock lm (_mutex); - auto i = _luts.find (make_pair (bit_depth, inverse)); + auto i = _luts.find (name); if (i != _luts.end ()) { return i->second; } - _luts[make_pair(bit_depth, inverse)] = make_lut (bit_depth, inverse); - return _luts[make_pair(bit_depth, inverse)]; + _luts[name] = make_lut (from, to, bit_depth, inverse); + return _luts[name]; } diff --git a/src/transfer_function.h b/src/transfer_function.h index a52011ec..5b591901 100644 --- a/src/transfer_function.h +++ b/src/transfer_function.h @@ -63,16 +63,16 @@ public: virtual ~TransferFunction (); /** @return A look-up table (of size 2^bit_depth) whose values range from 0 to 1 */ - double const * lut (int bit_depth, bool inverse) const; + double const * lut (std::string name, double from, double to, int bit_depth, bool inverse) const; virtual bool about_equal (std::shared_ptr<const TransferFunction> other, double epsilon) const = 0; protected: /** Make a LUT and return an array allocated by new */ - virtual double * make_lut (int bit_depth, bool inverse) const = 0; + virtual double * make_lut (double from, double to, int bit_depth, bool inverse) const = 0; private: - mutable std::map<std::pair<int, bool>, double*> _luts; + mutable std::map<std::string, double*> _luts; /** mutex to protect _luts */ mutable boost::mutex _mutex; }; diff --git a/test/colour_conversion_test.cc b/test/colour_conversion_test.cc index 5a6bdd85..04c182a3 100644 --- a/test/colour_conversion_test.cc +++ b/test/colour_conversion_test.cc @@ -44,7 +44,7 @@ using namespace dcp; static void check_gamma (shared_ptr<const TransferFunction> tf, int bit_depth, bool inverse, float gamma) { - double const * lut = tf->lut (bit_depth, inverse); + double const * lut = tf->lut ("all", 0, 1, bit_depth, inverse); int const count = rint (pow (2.0, bit_depth)); for (int i = 0; i < count; ++i) { @@ -55,7 +55,7 @@ check_gamma (shared_ptr<const TransferFunction> tf, int bit_depth, bool inverse, static void check_modified_gamma (shared_ptr<const TransferFunction> tf, int bit_depth, bool inverse, double power, double threshold, double A, double B) { - double const * lut = tf->lut (bit_depth, inverse); + double const * lut = tf->lut ("all", 0, 1, bit_depth, inverse); int const count = rint (pow (2.0, bit_depth)); for (int i = 0; i < count; ++i) { |
