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 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
|
"""
Names for the standard and extended color set.
Extended set is similar to `vim wiki <http://vim.wikia.com/wiki/Xterm256_color_names_for_console_Vim>`_, `colored <https://pypi.python.org/pypi/colored>`_, etc. Colors based on `wikipedia <https://en.wikipedia.org/wiki/ANSI_escape_code#Colors>`_.
You can access the index of the colors with names.index(name). You can access the
rgb values with ``r=int(html[n][1:3],16)``, etc.
"""
from __future__ import annotations
color_names = """\
black
red
green
yellow
blue
magenta
cyan
light_gray
dark_gray
light_red
light_green
light_yellow
light_blue
light_magenta
light_cyan
white
grey_0
navy_blue
dark_blue
blue_3
blue_3a
blue_1
dark_green
deep_sky_blue_4
deep_sky_blue_4a
deep_sky_blue_4b
dodger_blue_3
dodger_blue_2
green_4
spring_green_4
turquoise_4
deep_sky_blue_3
deep_sky_blue_3a
dodger_blue_1
green_3
spring_green_3
dark_cyan
light_sea_green
deep_sky_blue_2
deep_sky_blue_1
green_3a
spring_green_3a
spring_green_2
cyan_3
dark_turquoise
turquoise_2
green_1
spring_green_2a
spring_green_1
medium_spring_green
cyan_2
cyan_1
dark_red
deep_pink_4
purple_4
purple_4a
purple_3
blue_violet
orange_4
grey_37
medium_purple_4
slate_blue_3
slate_blue_3a
royal_blue_1
chartreuse_4
dark_sea_green_4
pale_turquoise_4
steel_blue
steel_blue_3
cornflower_blue
chartreuse_3
dark_sea_green_4a
cadet_blue
cadet_blue_a
sky_blue_3
steel_blue_1
chartreuse_3a
pale_green_3
sea_green_3
aquamarine_3
medium_turquoise
steel_blue_1a
chartreuse_2a
sea_green_2
sea_green_1
sea_green_1a
aquamarine_1
dark_slate_gray_2
dark_red_a
deep_pink_4a
dark_magenta
dark_magenta_a
dark_violet
purple
orange_4a
light_pink_4
plum_4
medium_purple_3
medium_purple_3a
slate_blue_1
yellow_4
wheat_4
grey_53
light_slate_grey
medium_purple
light_slate_blue
yellow_4_a
dark_olive_green_3
dark_sea_green
light_sky_blue_3
light_sky_blue_3a
sky_blue_2
chartreuse_2
dark_olive_green_3a
pale_green_3a
dark_sea_green_3
dark_slate_gray_3
sky_blue_1
chartreuse_1
light_green_a
light_green_b
pale_green_1
aquamarine_1a
dark_slate_gray_1
red_3
deep_pink_4b
medium_violet_red
magenta_3
dark_violet_a
purple_a
dark_orange_3
indian_red
hot_pink_3
medium_orchid_3
medium_orchid
medium_purple_2
dark_goldenrod
light_salmon_3
rosy_brown
grey_63
medium_purple_2a
medium_purple_1
gold_3
dark_khaki
navajo_white_3
grey_69
light_steel_blue_3
light_steel_blue
yellow_3
dark_olive_green_3b
dark_sea_green_3a
dark_sea_green_2
light_cyan_3
light_sky_blue_1
green_yellow
dark_olive_green_2
pale_green_1a
dark_sea_green_2a
dark_sea_green_1
pale_turquoise_1
red_3a
deep_pink_3
deep_pink_3a
magenta_3a
magenta_3b
magenta_2
dark_orange_3a
indian_red_a
hot_pink_3a
hot_pink_2
orchid
medium_orchid_1
orange_3
light_salmon_3a
light_pink_3
pink_3
plum_3
violet
gold_3a
light_goldenrod_3
tan
misty_rose_3
thistle_3
plum_2
yellow_3a
khaki_3
light_goldenrod_2
light_yellow_3
grey_84
light_steel_blue_1
yellow_2
dark_olive_green_1
dark_olive_green_1a
dark_sea_green_1a
honeydew_2
light_cyan_1
red_1
deep_pink_2
deep_pink_1
deep_pink_1a
magenta_2a
magenta_1
orange_red_1
indian_red_1
indian_red_1a
hot_pink
hot_pink_a
medium_orchid_1a
dark_orange
salmon_1
light_coral
pale_violet_red_1
orchid_2
orchid_1
orange_1
sandy_brown
light_salmon_1
light_pink_1
pink_1
plum_1
gold_1
light_goldenrod_2a
light_goldenrod_2b
navajo_white_1
misty_rose_1
thistle_1
yellow_1
light_goldenrod_1
khaki_1
wheat_1
cornsilk_1
grey_10_0
grey_3
grey_7
grey_11
grey_15
grey_19
grey_23
grey_27
grey_30
grey_35
grey_39
grey_42
grey_46
grey_50
grey_54
grey_58
grey_62
grey_66
grey_70
grey_74
grey_78
grey_82
grey_85
grey_89
grey_93""".split()
EMPTY_SLICE = slice(None, None, None)
_greys = (
3.4,
7.4,
11,
15,
19,
23,
26.7,
30.49,
34.6,
38.6,
42.4,
46.4,
50,
54,
58,
62,
66,
69.8,
73.8,
77.7,
81.6,
85.3,
89.3,
93,
)
_grey_vals = [int(x / 100.0 * 16 * 16) for x in _greys]
_grey_html = ["#" + format(x, "02x") * 3 for x in _grey_vals]
_normals = [int(x, 16) for x in "0 5f 87 af d7 ff".split()]
_normal_html = [
"#"
+ format(_normals[n // 36], "02x")
+ format(_normals[n // 6 % 6], "02x")
+ format(_normals[n % 6], "02x")
for n in range(16 - 16, 232 - 16)
]
_base_pattern = [(n // 4, n // 2 % 2, n % 2) for n in range(8)]
_base_html = (
[f"#{x[2] * 192:02x}{x[1] * 192:02x}{x[0] * 192:02x}" for x in _base_pattern]
+ ["#808080"]
+ [f"#{x[2] * 255:02x}{x[1] * 255:02x}{x[0] * 255:02x}" for x in _base_pattern][1:]
)
color_html = _base_html + _normal_html + _grey_html
color_codes_simple = list(range(8)) + list(range(60, 68))
"""Simple colors, remember that reset is #9, second half is non as common."""
# Attributes
attributes_ansi = {
"bold": 1,
"dim": 2,
"italics": 3,
"underline": 4,
"reverse": 7,
"hidden": 8,
"strikeout": 9,
}
# Stylesheet
default_styles = {
"warn": "fg red",
"title": "fg cyan underline bold",
"fatal": "fg red bold",
"highlight": "bg yellow",
"info": "fg blue",
"success": "fg green",
}
# Functions to be used for color name operations
class FindNearest:
"""This is a class for finding the nearest color given rgb values.
Different find methods are available."""
def __init__(self, r: int, g: int, b: int) -> None:
self.r = r
self.b = b
self.g = g
def only_basic(self):
"""This will only return the first 8 colors!
Breaks the colorspace into cubes, returns color"""
midlevel = 0x40 # Since bright is not included
# The colors are organised so that it is a
# 3D cube, black at 0,0,0, white at 1,1,1
# Compressed to linear_integers r,g,b
# [[[0,1],[2,3]],[[4,5],[6,7]]]
# r*1 + g*2 + b*4
return (
(self.r >= midlevel) * 1
+ (self.g >= midlevel) * 2
+ (self.b >= midlevel) * 4
)
def all_slow(self, color_slice: slice = EMPTY_SLICE) -> int:
"""This is a slow way to find the nearest color."""
distances = [
self._distance_to_color(color) for color in color_html[color_slice]
]
return min(range(len(distances)), key=distances.__getitem__)
def _distance_to_color(self, color: str) -> int:
"""This computes the distance to a color, should be minimized."""
rgb = (int(color[1:3], 16), int(color[3:5], 16), int(color[5:7], 16))
return (self.r - rgb[0]) ** 2 + (self.g - rgb[1]) ** 2 + (self.b - rgb[2]) ** 2
def _distance_to_color_number(self, n: int) -> int:
color = color_html[n]
return self._distance_to_color(color)
def only_colorblock(self) -> int:
"""This finds the nearest color based on block system, only works
for 17-232 color values."""
rint = min(
range(len(_normals)), key=[abs(x - self.r) for x in _normals].__getitem__
)
bint = min(
range(len(_normals)), key=[abs(x - self.b) for x in _normals].__getitem__
)
gint = min(
range(len(_normals)), key=[abs(x - self.g) for x in _normals].__getitem__
)
return 16 + 36 * rint + 6 * gint + bint
def only_simple(self) -> int:
"""Finds the simple color-block color."""
return self.all_slow(slice(0, 16, None))
def only_grey(self) -> int:
"""Finds the greyscale color."""
rawval = (self.r + self.b + self.g) / 3
n = min(
range(len(_grey_vals)),
key=[abs(x - rawval) for x in _grey_vals].__getitem__,
)
return n + 232
def all_fast(self) -> int:
"""Runs roughly 8 times faster than the slow version."""
colors = [self.only_simple(), self.only_colorblock(), self.only_grey()]
distances = [self._distance_to_color_number(n) for n in colors]
return colors[min(range(len(distances)), key=distances.__getitem__)]
def from_html(color: str) -> tuple[int, int, int]:
"""Convert html hex code to rgb."""
if len(color) != 7 or color[0] != "#":
raise ValueError("Invalid length of html code")
return (int(color[1:3], 16), int(color[3:5], 16), int(color[5:7], 16))
def to_html(r, g, b):
"""Convert rgb to html hex code."""
return f"#{r:02x}{g:02x}{b:02x}"
|