-
Notifications
You must be signed in to change notification settings - Fork 0
/
limits.py
121 lines (103 loc) · 3.27 KB
/
limits.py
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
from __future__ import division
from grapefruit import Color
from util import lab_chroma, chroma_hue_to_ab
def transition_point(func, lo, hi, epsilon=10e-5, depth=0):
"""
Find the place where a boolean function changes from True to False.
Arguments are a function "func", and bounds "lo" and "hi", where func(lo)
is True and func(hi) is False.
>>> import math
>>> def func(x):
... return x < math.pi
>>> result = transition_point(func, 3, 4)
>>> print('{:.4f}'.format(math.pi))
3.1416
>>> print('{:.4f}'.format(result))
3.1416
"""
if depth == 0:
assert lo < hi
assert func(lo) is True
assert func(hi) is False
if (hi - lo) < epsilon:
return lo
midpoint = (lo + hi) / 2
value = func(midpoint)
if value is True:
return transition_point(func, midpoint, hi, epsilon, depth + 1)
elif value is False:
return transition_point(func, lo, midpoint, epsilon, depth + 1)
def most_colorful_lightness():
"""
What is the lightness value that can express the highest chroma in all hues?
Equivalently, at what lightness level can you draw the biggest circle around
neutral gray without going out of gamut?
Answer: L74, with chroma 0.4
"""
best_lightness = 0
best_chroma = 0
for lightness in range(0, 100):
chroma = min_global_chroma(lightness)
if chroma > best_chroma:
best_chroma = chroma
best_lightness = lightness
return best_lightness, best_chroma
def peak_chroma_color():
"""
What is the color with the highest chroma value?
"""
best_chroma = 0
best_color = None
for lightness in range(0, 100):
for hue in range(0, 360):
chroma = max_chroma(hue, lightness)
if chroma > best_chroma:
best_chroma = chroma
a, b = chroma_hue_to_ab(chroma, hue)
best_color = Color.NewFromLab(lightness, a, b)
return best_color, best_chroma
#1.3187713623046875
##0a0cff
#(32.9999966526222, 0.7751544267050672, -1.0669084698150417)
def peak_chroma_color_scipy():
"""
Most intensely chromatic color:
#0000ff
L 32.310726263632034
a 0.79175287142984774
b -1.0784594584851654
chroma: 1.3378890973099862
"""
import scipy.optimize
import math
guess = (33, 0.7, -0.9)
def f(x):
l, a, b = x
return -lab_chroma(l, a, b)
l, a, b = scipy.optimize.fmin(f, guess, xtol=1e-5)
return Color.NewFromLab(l, a, b), lab_chroma(l, a, b)
def max_chroma(hue, lightness):
def valid_for_chroma(chroma):
a, b = chroma_hue_to_ab(chroma, hue)
color = Color.NewFromLab(lightness, a, b)
return color.isLegal
try:
return transition_point(valid_for_chroma, 0.0, 1.5)
except AssertionError:
return None
def min_global_chroma(lightness):
"""
For the given lightness, what is the lowest chroma that crosses the edge of
the gamut?
"""
return min(
max_chroma(hue, lightness)
for hue in range(0, 360)
)
if __name__ == '__main__':
#print(most_colorful_lightness())
#color, chroma = peak_chroma_color()
color, chroma = peak_chroma_color_scipy()
print(chroma)
print(color.html)
print(color.lab)