Skip to content

Instantly share code, notes, and snippets.

@jsundram
Last active January 31, 2025 05:10
Show Gist options
  • Save jsundram/b68d5ec56e75d332f36888dbf430ef94 to your computer and use it in GitHub Desktop.
Save jsundram/b68d5ec56e75d332f36888dbf430ef94 to your computer and use it in GitHub Desktop.
Trying to find names for colors. Takes the html code for a color (e.g. "#30c5ff" and finds the closest XKCD color name (https://xkcd.com/color/rgb/ and https://blog.xkcd.com/2010/05/03/color-survey-results/)
from matplotlib.colors import hex2color, rgb_to_hsv, XKCD_COLORS, CSS4_COLORS
import matplotlib.pyplot as plt
import numpy as np
class ColorNames:
def __init__(self, color_dict, converter=hex2color):
"""
color dict: A map of names to hex values.
converter: A function that takes a hex color and returns an array.
"""
self.colors = np.array([converter(c) for c in color_dict.values()])
self.names = list(color_dict.keys())
self.converter = converter
def closest(self, color):
v = self.converter(color)
distances = np.sum((self.colors - v) ** 2, axis=1)
closest_index = np.argmin(distances)
return self.names[closest_index]
def plot(data):
# Create figure and axis
fig, ax = plt.subplots(figsize=(12, 4))
# Hide axes
ax.axis('off')
# Prepare cell colors - None for text cells, hex colors for color cells
cell_colors = []
header_row = ['white'] * 6
cell_colors.append(header_row)
for row in data[1:]:
# For data rows: 3 None values for text cells, then 3 color values
row_colors = ['white'] * 3 + [row[3], row[4], row[5]]
cell_colors.append(row_colors)
# Create the table
table = ax.table(
cellText=data, # All cell text
cellColours=cell_colors,
loc='center',
cellLoc='center'
)
# Style the table
table.auto_set_font_size(False)
table.set_fontsize(9)
table.scale(1.2, 1.5)
# Style header row
for i in range(6):
table[(0, i)].set_text_props(weight='bold')
table[(0, i)].set_facecolor('#f0f0f0')
# Remove text from color cells
for row in range(1, len(data)):
for col in range(6):
cell = table[(row, col)]
if col < 3:
cell.set_text_props(ha='left') # Left-justify text
else:
cell.set_text_props(text='')
plt.tight_layout()
plt.show()
def main():
colors = ["#30c5ff", "#2a2d34", "#5c946e", "#80c2af", "#a0dde6"]
xkcd = {n.replace('xkcd:', ''): c for n, c in XKCD_COLORS.items()}
xkcd_names = ColorNames(xkcd)
css4_names = ColorNames(CSS4_COLORS)
table = [["HEX", "XKCD", "CSS4", "Color", "XKCD", "CSS4"], ]
for c in colors:
x = xkcd_names.closest(c)
c4 = css4_names.closest(c)
row = [c, x, c4, c, xkcd[x], CSS4_COLORS[c4]]
table.append(row)
plot(table)
if __name__ == "__main__":
main()
@jsundram
Copy link
Author

See also my answer on stackoverflow. This could probably be made better by doing this in a color space other than rgb, but hsv looks worse to me.

Output:
color-names-2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment