Skip to content

Instantly share code, notes, and snippets.

@Mason-McGough
Created December 11, 2024 18:38
Show Gist options
  • Save Mason-McGough/d5ef8e5a343ef8fe715b219fe407f727 to your computer and use it in GitHub Desktop.
Save Mason-McGough/d5ef8e5a343ef8fe715b219fe407f727 to your computer and use it in GitHub Desktop.
Color scheme generation app based on "A Math-Based Approach to Color Theory" by Ethan Gardner
"""
Based on "A Math-Based Approach to Color Theory" by Ethan Gardner
- ethangardner.com/posts/color-theory-math/
"""
import colorsys
import gradio as gr
from PIL import Image, ImageDraw
def complementary_color_scheme(base_color_hsv):
scheme_colors = [
base_color_hsv,
((base_color_hsv[0] + 0.5) % 1, base_color_hsv[1], base_color_hsv[2])
]
return scheme_colors
def split_complementary_color_scheme(base_color_hsv):
scheme_colors = [
base_color_hsv,
((base_color_hsv[0] + 0.4) % 1, base_color_hsv[1], base_color_hsv[2]),
((base_color_hsv[0] + 0.6) % 1, base_color_hsv[1], base_color_hsv[2])
]
return scheme_colors
def triadic_color_scheme(base_color_hsv):
scheme_colors = [
base_color_hsv,
((base_color_hsv[0] + 1/3) % 1, base_color_hsv[1], base_color_hsv[2]),
((base_color_hsv[0] + 2/3) % 1, base_color_hsv[1], base_color_hsv[2])
]
return scheme_colors
def tetradic_color_scheme(base_color_hsv):
scheme_colors = [
base_color_hsv,
((base_color_hsv[0] + 0.25) % 1, base_color_hsv[1], base_color_hsv[2]),
((base_color_hsv[0] + 0.5) % 1, base_color_hsv[1], base_color_hsv[2]),
((base_color_hsv[0] + 0.75) % 1, base_color_hsv[1], base_color_hsv[2])
]
return scheme_colors
def monochrome_color_scheme(base_color_hsv):
return (base_color_hsv,)
def analogous_color_scheme(base_color_hsv):
scheme_colors = [
base_color_hsv,
((base_color_hsv[0] + 0.05) % 1, base_color_hsv[1], base_color_hsv[2]),
((base_color_hsv[0] - 0.05) % 1, base_color_hsv[1], base_color_hsv[2])
]
return scheme_colors
color_scheme_map = {
"complementary": complementary_color_scheme,
"split-complementary": split_complementary_color_scheme,
"triadic": triadic_color_scheme,
"tetradic": tetradic_color_scheme,
"monochrome": monochrome_color_scheme,
"analogous": analogous_color_scheme
}
def generate_color_scheme(base_color_hsv, scheme_type):
try:
scheme_fn = color_scheme_map[scheme_type]
except KeyError as e:
raise ValueError("Invalid color scheme") from e
return scheme_fn(base_color_hsv)
def color_scheme_generator(base_color_dropdown, scheme_type_dropdown):
# Convert hex value to tuple of integers
base_color = tuple(int(base_color_dropdown.lstrip("#")[i:i + 2], 16) for i in (0, 2, 4))
# Convert base color from RGB to HSV
base_color_hsv = colorsys.rgb_to_hsv(*[c / 255.0 for c in base_color])
# Generate color scheme
scheme_colors = generate_color_scheme(base_color_hsv, scheme_type_dropdown)
# Create a color palette image
palette_width = 400
palette_height = 300
n_rows = 6
palette = Image.new("RGB", (palette_width, palette_height))
draw = ImageDraw.Draw(palette)
color_width = palette_width // len(scheme_colors)
row_height = palette_height // n_rows
r = 0
for r in range(n_rows):
for i, color in enumerate(scheme_colors):
# Adjust value of color based on row
color_adj = list(color)
# Places the base value at the top of the palette
# color_adj[2] = (1.0 - r / n_rows) if r > 0 else color[2]
# Ignores base value and generates a range across rows
color_adj[2] = 1.0 - r / n_rows
color_adj = tuple(color_adj)
# Convert scheme colors from HSV to RGB
color_rgb = tuple(round(c * 255) for c in colorsys.hsv_to_rgb(*color_adj))
# Draw color rectangle in image
draw.rectangle(
[i * color_width, r * row_height,
(i + 1) * color_width, (r + 1) * row_height],
fill=color_rgb
)
return palette
# Define the base color dropdown
base_color_dropdown = gr.ColorPicker(
label="Select Base Color (RGB)"
)
# Define the color scheme type dropdown
scheme_type_dropdown = gr.Dropdown(
choices=color_scheme_map.keys(),
label="Select Color Scheme Type",
value="complementary"
)
iface = gr.Interface(
fn=color_scheme_generator,
inputs=[base_color_dropdown, scheme_type_dropdown],
outputs="image"
)
iface.launch()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment