summaryrefslogtreecommitdiff
path: root/test_coverage.py
diff options
context:
space:
mode:
Diffstat (limited to 'test_coverage.py')
-rw-r--r--test_coverage.py102
1 files changed, 102 insertions, 0 deletions
diff --git a/test_coverage.py b/test_coverage.py
new file mode 100644
index 0000000..07ceb08
--- /dev/null
+++ b/test_coverage.py
@@ -0,0 +1,102 @@
+import numpy as np, os, multiprocessing
+from colour import *
+from colour.models import eotf_inverse_sRGB
+from jakob_hanika import jakob_hanika, model_sd
+
+
+
+illuminant = "D65"
+ill_xy = ILLUMINANTS["CIE 1931 2 Degree Standard Observer"][illuminant]
+ill_sd = SpectralDistribution(ILLUMINANTS_SDS[illuminant]) # Note: changed in dev (to ILLUMINANTS_SD)
+
+# Resolution of the discretization cubes
+# Both should be 64, but this code is a bit too slow at the moment
+CHROMA_STEPS = 8
+LIGHTNESS_STEPS = 8
+
+
+
+# Solve for a specific RGB color
+def optimize_RGB(linear_RGB, ccp0):
+ RGB = eotf_inverse_sRGB(linear_RGB)
+ target = sRGB_to_XYZ(RGB, ill_xy)
+ ccp, error = jakob_hanika(target, ill_sd, ill_xy, ccp0, verbose=False)
+ if error > 0.1:
+ print("WARNING: convergence failed with L=%s, starting from %s" \
+ % (linear_RGB, ccp0))
+
+ return ccp, error
+
+# Solve for all lightness values of a fully saturated RGB color
+def optimize_chromaticity(argv):
+ linear_RGB, dirname = argv
+
+ # alpha's aren't spaced equally (see the article)
+ def smoothstep(x):
+ return x**2 * (3 - 2 * x)
+
+ ii = np.arange(0, LIGHTNESS_STEPS)
+ aa = smoothstep(smoothstep(ii / LIGHTNESS_STEPS))
+ ccps = np.empty((LIGHTNESS_STEPS, 3)) # FIXME: dtype?
+
+ def f(alpha, ccp0):
+ path = "%s/%.3f" % (dirname, alpha)
+ print("%s..." % path)
+
+ ccp, error = optimize_RGB(linear_RGB * alpha, ccp0)
+
+ try:
+ os.makedirs(os.path.dirname(path))
+ except:
+ pass
+ with open(path, "w") as fd:
+ fd.write("%s, %s" % (ccp, error))
+ if error > 0.1:
+ fd.write(" FAILED")
+ fd.write("\n")
+
+ return ccp, error
+
+
+ i_mid = LIGHTNESS_STEPS // 2
+ ccps[i_mid, :], _ = f(aa[i_mid], (0, 0, 0))
+
+ ccp0 = ccps[i_mid, :]
+ for i in range(i_mid + 1, LIGHTNESS_STEPS):
+ ccps[i, :], _ = f(aa[i], ccp0)
+
+ ccp0 = ccps[i_mid, :]
+ for i in reversed(range(0, i_mid)):
+ ccps[i, :], _ = f(aa[i], ccp0)
+
+
+
+# This demo discretizes the sRGB space to three 8x8x8 cubes and tries to find
+# the model parameters for all the colors. Coefficients are saved to a file
+# somewhere in the 'out' directory (each color gets its own file).
+# FIXME: This dumpster fire of an output format is to be replaced ASAP.
+# FIXME: This takes a good while (on the order of an hour).
+if __name__ == "__main__":
+ args = []
+
+ done = 0
+ total = 0
+ for A in np.linspace(0, 1, CHROMA_STEPS):
+ for B in np.linspace(0, 1, CHROMA_STEPS):
+ for RGB in [np.array([1, A, B]),
+ np.array([A, 1, B]),
+ np.array([A, B, 1])]:
+
+ dirname = "out/R%.3fG%.3fB%.3f" % (*RGB,)
+ total += 1
+
+ if os.path.exists(dirname) and len(os.listdir(dirname)) == LIGHTNESS_STEPS:
+ done += 1
+ continue
+
+ args.append((RGB, dirname))
+
+ print("%d/%d already done" % (done, total))
+
+ pool = multiprocessing.Pool()
+ pool.map(optimize_chromaticity, args)