diff options
| author | Carl Hetherington <cth@carlh.net> | 2022-05-05 20:56:14 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2022-05-05 21:09:40 +0200 |
| commit | cbbb9e63b7ec7a5c34f186ceafe5da6be8faa739 (patch) | |
| tree | 79ccaa11973954138df02c2022b2ea25c0717b9d /src | |
| parent | ad7244de981a7dd0b9b4f8f3d62d4704f1968012 (diff) | |
Allow LUTs to be created with a particular range.
Diffstat (limited to 'src')
| -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 | 5 | ||||
| -rw-r--r-- | src/identity_transfer_function.h | 2 | ||||
| -rw-r--r-- | src/modified_gamma_transfer_function.cc | 16 | ||||
| -rw-r--r-- | src/modified_gamma_transfer_function.h | 2 | ||||
| -rw-r--r-- | src/rgb_xyz.cc | 12 | ||||
| -rw-r--r-- | src/s_gamut3_transfer_function.cc | 14 | ||||
| -rw-r--r-- | src/s_gamut3_transfer_function.h | 2 | ||||
| -rw-r--r-- | src/transfer_function.cc | 30 | ||||
| -rw-r--r-- | src/transfer_function.h | 23 |
11 files changed, 76 insertions, 37 deletions
diff --git a/src/gamma_transfer_function.cc b/src/gamma_transfer_function.cc index 4ec09afb..ff9073a1 100644 --- a/src/gamma_transfer_function.cc +++ b/src/gamma_transfer_function.cc @@ -56,13 +56,14 @@ GammaTransferFunction::GammaTransferFunction (double gamma) vector<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 = vector<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 bfd336df..e7294000 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: - std::vector<double> make_lut (int bit_depth, bool inverse) const override; + std::vector<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 c888bd3e..b6f03d07 100644 --- a/src/identity_transfer_function.cc +++ b/src/identity_transfer_function.cc @@ -49,12 +49,13 @@ using namespace dcp; vector<double> -IdentityTransferFunction::make_lut (int bit_depth, bool) const +IdentityTransferFunction::make_lut (double from, double to, int bit_depth, bool) const { int const bit_length = int(std::pow(2.0f, bit_depth)); auto lut = vector<double>(bit_length); for (int i = 0; i < bit_length; ++i) { - lut[i] = double(i) / (bit_length - 1); + double x = double(i) / (bit_length - 1); + lut[i] = (x * (to - from)) + from; } return lut; diff --git a/src/identity_transfer_function.h b/src/identity_transfer_function.h index 3db71b30..f6e80abb 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: - std::vector<double> make_lut (int bit_depth, bool inverse) const override; + std::vector<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 e2cc1e86..991e642e 100644 --- a/src/modified_gamma_transfer_function.cc +++ b/src/modified_gamma_transfer_function.cc @@ -59,7 +59,7 @@ ModifiedGammaTransferFunction::ModifiedGammaTransferFunction (double power, doub vector<double> -ModifiedGammaTransferFunction::make_lut (int bit_depth, bool inverse) const +ModifiedGammaTransferFunction::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 = vector<double>(bit_length); @@ -67,19 +67,21 @@ ModifiedGammaTransferFunction::make_lut (int bit_depth, bool inverse) const double const threshold = _threshold / _B; for (int i = 0; i < bit_length; ++i) { double const p = static_cast<double>(i) / (bit_length - 1); - if (p > threshold) { - lut[i] = (1 + _A) * pow (p, 1 / _power) - _A; + double const q = (p * (to - from)) + from; + if (q > threshold) { + lut[i] = (1 + _A) * pow (q, 1 / _power) - _A; } else { - lut[i] = p * _B; + lut[i] = q * _B; } } } else { for (int i = 0; i < bit_length; ++i) { double const p = static_cast<double>(i) / (bit_length - 1); - if (p > _threshold) { - lut[i] = pow ((p + _A) / (1 + _A), _power); + double const q = (p * (to - from)) + from; + if (q > _threshold) { + lut[i] = pow ((q + _A) / (1 + _A), _power); } else { - lut[i] = p / _B; + lut[i] = q / _B; } } } diff --git a/src/modified_gamma_transfer_function.h b/src/modified_gamma_transfer_function.h index d4e9cf97..0427dd61 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: - std::vector<double> make_lut (int bit_depth, bool inverse) const override; + std::vector<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 b8acc9b0..de6a40db 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); - auto lut_in = conversion.out()->lut (12, false); - auto lut_out = conversion.in()->lut (16, true); + auto lut_in = conversion.out()->lut(0, 1, 12, false); + auto lut_out = conversion.in()->lut(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); - auto lut_in = conversion.out()->lut (12, false); - auto lut_out = conversion.in()->lut (16, true); + auto lut_in = conversion.out()->lut(0, 1, 12, false); + auto lut_out = conversion.in()->lut(0, 1, 16, true); auto const matrix = conversion.xyz_to_rgb (); double fast_matrix[9] = { @@ -276,8 +276,8 @@ dcp::rgb_to_xyz ( double x, y, z; } d; - auto lut_in = conversion.in()->lut (12, false); - auto lut_out = conversion.out()->lut (16, true); + auto lut_in = conversion.in()->lut(0, 1, 12, false); + auto lut_out = conversion.out()->lut(0, 1, 16, true); /* This is is the product of the RGB to XYZ matrix, the Bradford transform and the DCI companding */ double fast_matrix[9]; diff --git a/src/s_gamut3_transfer_function.cc b/src/s_gamut3_transfer_function.cc index b2e82b51..512a2951 100644 --- a/src/s_gamut3_transfer_function.cc +++ b/src/s_gamut3_transfer_function.cc @@ -49,26 +49,28 @@ using namespace dcp; vector<double> -SGamut3TransferFunction::make_lut (int bit_depth, bool inverse) const +SGamut3TransferFunction::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 = vector<double>(bit_length); if (inverse) { for (int i = 0; i < bit_length; ++i) { auto const p = static_cast<double>(i) / (bit_length - 1); - if (p >= (0.01125 / 1023)) { - lut[i] = (420 + log10((p + 0.01) / (0.18 + 0.01)) * 261.5) / 1023; + auto const q = (p * (to - from)) + from; + if (q >= (0.01125 / 1023)) { + lut[i] = (420 + log10((q + 0.01) / (0.18 + 0.01)) * 261.5) / 1023; } else { - lut[i] = (p * (171.2102946929 - 95) / 0.01125000 + 95) / 1023; + lut[i] = (q * (171.2102946929 - 95) / 0.01125000 + 95) / 1023; } } } else { for (int i = 0; i < bit_length; ++i) { auto const p = static_cast<double>(i) / (bit_length - 1); - if (p >= (171.2102946929 / 1023)) { + auto const q = (p * (to - from)) + from; + if (q >= (171.2102946929 / 1023)) { lut[i] = pow(10, ((p * 1023 - 420) / 261.5)) * (0.18 + 0.01) - 0.01; } else { - lut[i] = (p * 1023 - 95) * 0.01125000 / (171.2102946929 - 95); + lut[i] = (q * 1023 - 95) * 0.01125000 / (171.2102946929 - 95); } } } diff --git a/src/s_gamut3_transfer_function.h b/src/s_gamut3_transfer_function.h index 790cd6b1..50b4875a 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: - std::vector<double> make_lut (int bit_depth, bool inverse) const override; + std::vector<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 dd3512ec..c1343ff2 100644 --- a/src/transfer_function.cc +++ b/src/transfer_function.cc @@ -51,15 +51,35 @@ using namespace dcp; vector<double> const& -TransferFunction::lut (int bit_depth, bool inverse) const +TransferFunction::lut (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)); - if (i != _luts.end ()) { + auto const descriptor = LUTDescriptor{from, to, bit_depth, inverse}; + + auto i = _luts.find(descriptor); + 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[descriptor] = make_lut(from, to, bit_depth, inverse); + return _luts[descriptor]; +} + + +bool +TransferFunction::LUTDescriptor::operator==(TransferFunction::LUTDescriptor const& other) const +{ + return from == other.from && to == other.to && bit_depth == other.bit_depth && inverse == other.inverse; +} + + +std::size_t +TransferFunction::LUTDescriptorHasher::operator()(TransferFunction::LUTDescriptor const& desc) const +{ + return std::hash<double>()(desc.from) ^ + std::hash<double>()(desc.to) ^ + std::hash<int>()(desc.bit_depth) ^ + std::hash<bool>()(desc.inverse); } + diff --git a/src/transfer_function.h b/src/transfer_function.h index 04678733..a53a476e 100644 --- a/src/transfer_function.h +++ b/src/transfer_function.h @@ -42,7 +42,7 @@ #include <boost/thread/mutex.hpp> -#include <map> +#include <unordered_map> #include <memory> #include <vector> @@ -60,17 +60,30 @@ public: virtual ~TransferFunction () {} - /** @return A look-up table (of size 2^bit_depth) whose values range from 0 to 1 */ - std::vector<double> const& lut (int bit_depth, bool inverse) const; + /** @return A look-up table (of size 2^bit_depth) */ + std::vector<double> const& lut (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 std::vector<double> make_lut (int bit_depth, bool inverse) const = 0; + virtual std::vector<double> make_lut (double from, double to, int bit_depth, bool inverse) const = 0; private: - mutable std::map<std::pair<int, bool>, std::vector<double>> _luts; + struct LUTDescriptor { + double from; + double to; + int bit_depth; + bool inverse; + + bool operator==(LUTDescriptor const& other) const; + }; + + struct LUTDescriptorHasher { + std::size_t operator()(LUTDescriptor const& desc) const; + }; + + mutable std::unordered_map<LUTDescriptor, std::vector<double>, LUTDescriptorHasher> _luts; /** mutex to protect _luts */ mutable boost::mutex _mutex; }; |
