summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2022-05-05 17:38:48 +0200
committerCarl Hetherington <cth@carlh.net>2022-05-05 18:53:39 +0200
commit969c9c28c87e83f4e3fcb7b52a921773d363511f (patch)
tree361713cfbb0246b75af7442f257375c27655083b
parent504955b1e8036a25b1dc196625e530808ac42e99 (diff)
Use two LUTs.inaccurate-gamma
-rw-r--r--src/gamma_transfer_function.cc5
-rw-r--r--src/gamma_transfer_function.h2
-rw-r--r--src/identity_transfer_function.cc3
-rw-r--r--src/identity_transfer_function.h2
-rw-r--r--src/modified_gamma_transfer_function.cc3
-rw-r--r--src/modified_gamma_transfer_function.h2
-rw-r--r--src/rgb_xyz.cc46
-rw-r--r--src/s_gamut3_transfer_function.cc3
-rw-r--r--src/s_gamut3_transfer_function.h2
-rw-r--r--src/transfer_function.cc8
-rw-r--r--src/transfer_function.h6
-rw-r--r--test/colour_conversion_test.cc4
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) {