summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2022-05-05 20:56:14 +0200
committerCarl Hetherington <cth@carlh.net>2022-05-05 21:09:40 +0200
commitcbbb9e63b7ec7a5c34f186ceafe5da6be8faa739 (patch)
tree79ccaa11973954138df02c2022b2ea25c0717b9d /src
parentad7244de981a7dd0b9b4f8f3d62d4704f1968012 (diff)
Allow LUTs to be created with a particular range.
Diffstat (limited to 'src')
-rw-r--r--src/gamma_transfer_function.cc5
-rw-r--r--src/gamma_transfer_function.h2
-rw-r--r--src/identity_transfer_function.cc5
-rw-r--r--src/identity_transfer_function.h2
-rw-r--r--src/modified_gamma_transfer_function.cc16
-rw-r--r--src/modified_gamma_transfer_function.h2
-rw-r--r--src/rgb_xyz.cc12
-rw-r--r--src/s_gamut3_transfer_function.cc14
-rw-r--r--src/s_gamut3_transfer_function.h2
-rw-r--r--src/transfer_function.cc30
-rw-r--r--src/transfer_function.h23
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;
};