Fix typo.
[pyutils.git] / docs / colors.py
1 #!/usr/bin/env python3
2
3 """
4 The start of something cool.
5 """
6
7 import logging
8 import math
9 from typing import Optional, Tuple
10
11 from pyutils import ansi, bootstrap, config
12
13 logger = logging.getLogger(__name__)
14 args = config.add_commandline_args(f'({__file__})', f'Args related to {__file__}')
15
16
17 def rgb_to_hsv(rgb: Tuple[int, int, int]) -> Tuple[int, int, int]:
18     r = rgb[0] / 255.0
19     g = rgb[1] / 255.0
20     b = rgb[2] / 255.0
21
22     cmax = max(r, g, b)
23     cmin = min(r, g, b)
24     diff = cmax - cmin
25     h = -1
26     s = -1
27
28     if cmax == cmin:
29         h = 0
30     elif cmax == r:
31         h = math.fmod(60 * ((g - b) / diff) + 360, 360)
32     elif cmax == g:
33         h = math.fmod(60 * ((b - r) / diff) + 120, 360)
34     elif cmax == b:
35         h = math.fmod(60 * ((r - g) / diff) + 240, 360)
36
37     if cmax == 0:
38         s = 0
39     else:
40         s = (diff / cmax) * 100.0
41
42     v = cmax * 100.0
43     return (h, s, v)
44
45
46 def step(code, repetitions=1):
47     r = code[0]
48     g = code[1]
49     b = code[2]
50     lum = math.sqrt(0.241 * r + 0.691 * g + 0.068 * b)
51     h, s, v = rgb_to_hsv(code)
52     h2 = int(h * repetitions)
53     lum2 = int(lum * repetitions)
54     v2 = int(v * repetitions)
55     if h2 % 2 == 1:
56         v2 = repetitions - v2
57         lum = repetitions - lum
58     return (-h2, lum, v2)
59
60
61 def sort_value(code: Tuple[int, int, int]) -> int:
62     lum = math.sqrt(0.241 * code[0] + 0.691 * code[1] + 0.068 * code[2])
63     hsv = rgb_to_hsv(code)
64     return lum * hsv[0] * hsv[1]
65
66
67 @bootstrap.initialize
68 def main() -> Optional[int]:
69     colors = {}
70     colors_to_code = {}
71     for name, code in ansi.COLOR_NAMES_TO_RGB.items():
72         colors_to_code[name] = code
73         colors[name] = step(code, 8)
74
75     print('    <TABLE><TR><TD></TD><TD></TD><TD></TD><TD></TD>')
76     for n, name in enumerate(
77         {k: v for k, v in sorted(colors.items(), key=lambda i: i[1])}
78     ):
79         if n % 4 == 0:
80             print('    </TR><TR>')
81         code = colors_to_code[name]
82         contrast = ansi.pick_contrasting_color(None, code[0], code[1], code[2])
83         code = code[0] << 16 | code[1] << 8 | code[2]
84         code = f'{code:06X}'
85         contrast = contrast[0] << 16 | contrast[1] << 8 | contrast[2]
86         contrast = f'{contrast:06X}'
87
88         print(
89             f"    <TD BGCOLOR='{code}'><FONT COLOR='{contrast}'><CENTER>{name} (0x{code})</CENTER></FONT></TD>"
90         )
91     return None
92
93
94 if __name__ == '__main__':
95     main()