aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--third_party/skcms/skcms.h6
-rw-r--r--third_party/skcms/src/Transform.c44
-rwxr-xr-xthird_party/skcms/version.sha12
3 files changed, 51 insertions, 1 deletions
diff --git a/third_party/skcms/skcms.h b/third_party/skcms/skcms.h
index 54c9e8ebae..108eb58863 100644
--- a/third_party/skcms/skcms.h
+++ b/third_party/skcms/skcms.h
@@ -203,6 +203,12 @@ bool skcms_Transform(const void* src,
// (e.g. skcms_sRGB_profile) where not.
void skcms_EnsureUsableAsDestination(skcms_ICCProfile* profile, const skcms_ICCProfile* fallback);
+// If profile cannot be used as a destination profile with a single parametric transfer function,
+// (ie for rasterization), rewrite it with approximations where reasonable or by pulling from
+// fallback (e.g. skcms_sRGB_profile) where not.
+void skcms_EnsureUsableAsDestinationWithSingleCurve(skcms_ICCProfile* profile,
+ const skcms_ICCProfile* fallback);
+
#ifdef __cplusplus
}
#endif
diff --git a/third_party/skcms/src/Transform.c b/third_party/skcms/src/Transform.c
index b3a6b55705..16cfaec0a2 100644
--- a/third_party/skcms/src/Transform.c
+++ b/third_party/skcms/src/Transform.c
@@ -6,6 +6,7 @@
*/
#include "../skcms.h"
+#include "GaussNewton.h"
#include "LinearAlgebra.h"
#include "Macros.h"
#include "PortableMath.h"
@@ -643,3 +644,46 @@ void skcms_EnsureUsableAsDestination(skcms_ICCProfile* profile, const skcms_ICCP
*profile = ok;
assert_usable_as_destination(profile);
}
+
+static float max_roundtrip_error(const skcms_TransferFunction* inv_tf, const skcms_Curve* curve) {
+ int N = curve->table_entries ? (int)curve->table_entries : 256;
+ const float x_scale = 1.0f / (N - 1);
+ float err = 0;
+ for (int i = 0; i < N; i++) {
+ float x = i * x_scale,
+ y = skcms_eval_curve(x, curve);
+ err = fmaxf_(err, fabsf_(x - skcms_TransferFunction_eval(inv_tf, y)));
+ }
+ return err;
+}
+
+void skcms_EnsureUsableAsDestinationWithSingleCurve(skcms_ICCProfile* profile,
+ const skcms_ICCProfile* fallback) {
+ // Operate on a copy of profile, so we can choose the best TF for the original curves
+ skcms_ICCProfile result = *profile;
+ skcms_EnsureUsableAsDestination(&result, fallback);
+
+ int best_tf = 0;
+ float min_max_error = INFINITY_;
+ const skcms_ICCProfile* ref = profile->has_trc ? profile : fallback;
+ for (int i = 0; i < 3; i++) {
+ skcms_TransferFunction inv;
+ skcms_TransferFunction_invert(&result.trc[i].parametric, &inv);
+
+ float err = 0;
+ for (int j = 0; j < 3; ++j) {
+ err = fmaxf_(err, max_roundtrip_error(&inv, &ref->trc[j]));
+ }
+ if (min_max_error > err) {
+ min_max_error = err;
+ best_tf = i;
+ }
+ }
+
+ for (int i = 0; i < 3; i++) {
+ result.trc[i].parametric = result.trc[best_tf].parametric;
+ }
+
+ *profile = result;
+ assert_usable_as_destination(profile);
+}
diff --git a/third_party/skcms/version.sha1 b/third_party/skcms/version.sha1
index 72a033c208..5e4190ba95 100755
--- a/third_party/skcms/version.sha1
+++ b/third_party/skcms/version.sha1
@@ -1 +1 @@
-4028d1477684db34b7cf4da8c6b2438071062b32 \ No newline at end of file
+8e64fbf367c7d3186ab4b002b142eca84431ddcc \ No newline at end of file