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
|
#!/usr/bin/env python3
"""
(brewer_colors, svgcolor_names, color_names) → colortbl.h generator
"""
import argparse
import locale
import re
import sys
def rgb_to_hsv(r: int, g: int, b: int) -> tuple[int, int, int]:
"""transform an RGB color into HSV format"""
r /= 255.0
g /= 255.0
b /= 255.0
max_ = max((r, g, b))
min_ = min((r, g, b))
v = max_
if max_ != 0:
s = (max_ - min_) / max_
else:
s = 0
if s == 0:
h = 0
else:
delta = max_ - min_
rc = (max_ - r) / delta
gc = (max_ - g) / delta
bc = (max_ - b) / delta
if r == max_:
h = bc - gc
elif g == max_:
h = 2.0 + (rc - bc)
else:
h = 4.0 + (gc - rc)
h *= 60.0
if h < 0.0:
h += 360.0
return int(h / 360.0 * 255.0), int(s * 255.0), int(v * 255.0)
def main(args: list[str]) -> int:
"""entry point"""
# avoid sorting issues due to locale differences
locale.setlocale(locale.LC_ALL, "C")
# parse command line arguments
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"brewer_colors",
type=argparse.FileType("rt"),
help="input Brewer color table entries",
)
parser.add_argument(
"svgcolor_names",
type=argparse.FileType("rt"),
help="input SVG color table entries",
)
parser.add_argument(
"color_names",
type=argparse.FileType("rt"),
help="input other color table entries",
)
parser.add_argument(
"output", type=argparse.FileType("wt"), help="output color table C header"
)
options = parser.parse_args(args[1:])
options.output.write("static const hsvrgbacolor_t color_lib[] = {\n")
# collect all color entries
entries = (
options.brewer_colors.readlines()
+ options.svgcolor_names.readlines()
+ options.color_names.readlines()
)
# sort these so `bsearch` for a color will work correctly
entries = sorted(entries, key=locale.strxfrm)
for entry in entries:
# ignore blank lines
if entry.strip() == "":
continue
# ignore commented lines
if re.match(r"\s*#", entry) is not None:
continue
# extract fields of the entry
m = re.match(
r"(?P<name>\S+) (?P<r>\d+) (?P<g>\d+) (?P<b>\d+) (?P<a>\d+)", entry
)
assert m is not None, f'unexpected entry format "{entry}"'
# transform an RGB color into HSV
r = int(m.group("r"))
g = int(m.group("g"))
b = int(m.group("b"))
h, s, v = rgb_to_hsv(r, g, b)
# write this out as a C array entry
name = m.group("name")
a = int(m.group("a"))
options.output.write(f'{{"{name}",{h},{s},{v},{r},{g},{b},{a}}},\n')
options.output.write("};\n")
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv))
|