summaryrefslogtreecommitdiff
path: root/test_coverage.py
blob: 90e3c7923e1e02d67b7d57137edc93b73db4719b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import numpy as np, os, multiprocessing
from colour import *
from colour.models import eotf_inverse_sRGB
from gsoc_common import D65, D65_xy, jakob_hanika, model_sd, plot_comparison



# 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, D65_xy)
	ccp, error = jakob_hanika(target, D65, D65_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)