Easy Colors
py_simple.easy_colors
Beginner-friendly helpers for hex and RGB color handling.
contrast_ratio(hex1, hex2)
Calculates WCAG contrast ratio between two hex colors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hex1
|
str
|
First hex color string (e.g., "#000000"). |
required |
hex2
|
str
|
Second hex color string (e.g., "#FFFFFF"). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
float |
float
|
Contrast ratio between the two colors. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If either hex color is not valid. |
Example
from py_simple import contrast_ratio
contrast_ratio("#000000", "#FFFFFF") # -> 21.0
contrast_ratio("#777777", "#FFFFFF") # -> 4.48
def contrast(l1, l2):
lighter = max(l1, l2)
darker = min(l1, l2)
return (lighter + 0.05) / (darker + 0.05)
l_black = 0.0
l_white = 1.0
ratio = contrast(l_black, l_white) # -> 21.0
hex_to_rgb(hex_code)
Converts a hex color code string to an (R, G, B) integer tuple.
Supports 3-digit and 6-digit hex color codes with or without '#'.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hex_code
|
str
|
Hex color string to convert (e.g., "#FFFFFF" or "fff"). |
required |
Returns:
| Type | Description |
|---|---|
tuple[int, int, int]
|
tuple[int, int, int]: RGB values as (r, g, b) integers in range 0-255. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If hex_code is not a valid hex color. |
Example
from py_simple import hex_to_rgb
hex_to_rgb("#FFFFFF") # -> (255, 255, 255)
hex_to_rgb("00ff00") # -> (0, 255, 0)
hex_code = "#FFFFFF".lstrip("#")
if len(hex_code) == 3:
hex_code = "".join(c * 2 for c in hex_code)
r, g, b = tuple(int(hex_code[i : i + 2], 16) for i in (0, 2, 4))
hex_to_rgba(hex_code, alpha)
Converts a hex color and alpha value into an (R, G, B, A) tuple.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hex_code
|
str
|
Hex color string to convert (e.g., "#FFFFFF" or "fff"). |
required |
alpha
|
float
|
Alpha channel value in range 0.0 to 1.0. |
required |
Returns:
| Type | Description |
|---|---|
tuple[int, int, int, float]
|
tuple[int, int, int, float]: RGBA values as (r, g, b, alpha). |
Raises:
| Type | Description |
|---|---|
ValueError
|
If hex_code is not a valid hex color. |
ValueError
|
If alpha is outside the 0.0-1.0 range. |
Example
from py_simple import hex_to_rgba
hex_to_rgba("#FF0000", 0.5) # -> (255, 0, 0, 0.5)
hex_to_rgba("00ff00", 1.0) # -> (0, 255, 0, 1.0)
hex_code = "#FF0000".lstrip("#")
if len(hex_code) == 3:
hex_code = "".join(c * 2 for c in hex_code)
r = int(hex_code[0:2], 16)
g = int(hex_code[2:4], 16)
b = int(hex_code[4:6], 16)
alpha = 0.5
rgba = (r, g, b, alpha)
hsl_to_rgb(h, s, lightness)
Converts an (H, S, L) color to an (R, G, B) integer tuple.
Hue is measured in degrees (0-360), while Saturation and Lightness are measured as percentages (0-100).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
h
|
float
|
Hue in degrees (0 to 360). |
required |
s
|
float
|
Saturation as a percentage (0 to 100). |
required |
lightness
|
float
|
Lightness as a percentage (0 to 100). |
required |
Returns:
| Type | Description |
|---|---|
tuple[int, int, int]
|
tuple[int, int, int]: RGB values as (r, g, b) integers in range 0-255. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If hue is outside the 0-360 range or saturation/lightness are outside the 0-100 range. |
TypeError
|
If any value is not an int or float. |
Example
from py_simple import hsl_to_rgb
hsl_to_rgb(120, 100, 50) # -> (0, 255, 0)
hsl_to_rgb(0, 0, 100) # -> (255, 255, 255)
h, s, lightness = 120, 100, 50
s, lightness = s / 100, lightness / 100
chroma = (1 - abs(2 * lightness - 1)) * s
secondary = chroma * (1 - abs((h / 60) % 2 - 1))
match = lightness - chroma / 2
if h < 60:
red, green, blue = chroma, secondary, 0
elif h < 120:
red, green, blue = secondary, chroma, 0
elif h < 180:
red, green, blue = 0, chroma, secondary
elif h < 240:
red, green, blue = 0, secondary, chroma
elif h < 300:
red, green, blue = secondary, 0, chroma
else:
red, green, blue = chroma, 0, secondary
r = round((red + match) * 255)
g = round((green + match) * 255)
b = round((blue + match) * 255)
is_light_color(hex_code, threshold=LUMINANCE_LIGHT_THRESHOLD)
Takes a hex color and returns whether it's "light" based on perceived luminance. Uses the sRGB relative luminance formula (ITU-R BT.709 weights). Threshold ~0.179 is commonly used for WCAG contrast calculations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hex_code
|
str
|
Hex color string to convert (e.g., "#FFFFFF" or "fff"). |
required |
threshold
|
float
|
Luminance threshold for "light" classification (default 0.179). |
LUMINANCE_LIGHT_THRESHOLD
|
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True if it's "light" based on perceived luminance. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If hex_code is not a valid hex color. |
Example
from py_simple import is_light_color
is_light_color("#FFFFFF") # -> True
is_light_color("#000000") # -> False
hex_code = "#FFFFFF".lstrip("#")
if len(hex_code) == 3:
hex_code = "".join(c * 2 for c in hex_code)
r, g, b = (int(hex_code[i:i + 2], 16) / 255 for i in (0, 2, 4))
def linearize(c):
return c / 12.92 if c <= 0.03928 else ((c + 0.055) / 1.055) ** 2.4
luminance = sum(w * linearize(v)
for w, v in zip((0.2126, 0.7152, 0.0722), (r, g, b)))
is_light = luminance > 0.179 # -> True
is_valid_hex(hex_code)
Checks whether a string is a valid hex color code.
Supports 3-digit and 6-digit hex color formats, with or without a leading '#' prefix.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hex_code
|
str
|
Color string to check. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True if hex_code is a valid hex color, False otherwise. |
Example
from py_simple import is_valid_hex
is_valid_hex("#FFFFFF") # -> True
is_valid_hex("fff") # -> True
is_valid_hex("invalid") # -> False
import re
hex_code = "#FFFFFF"
cleaned = hex_code.lstrip("#")
is_valid = len(cleaned) in (3, 6) and all(
c in "0123456789abcdefABCDEF" for c in cleaned
)
random_hex_color()
Returns a random valid hex color string in uppercase #RRGGBB format.
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
Uppercase hex color string (e.g., "#FFFFFF"). |
Example
from py_simple import random_hex_color
color = random_hex_color() # -> e.g. "#A1B2C3"
import random
color = f"#{random.randint(0, 0xFFFFFF):06X}"
rgb_to_hex(r, g, b)
Converts (R, G, B) color values to a hex color string.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
r
|
int
|
Red channel value (0 to 255). |
required |
g
|
int
|
Green channel value (0 to 255). |
required |
b
|
int
|
Blue channel value (0 to 255). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
Uppercase hex color string (e.g., "#FFFFFF"). |
Raises:
| Type | Description |
|---|---|
ValueError
|
If any channel is outside the 0-255 range. |
TypeError
|
If any channel is not an integer. |
Example
from py_simple import rgb_to_hex
rgb_to_hex(255, 255, 255) # -> "#FFFFFF"
rgb_to_hex(0, 128, 64) # -> "#008040"
r, g, b = 255, 255, 255
hex_code = f"#{r:02X}{g:02X}{b:02X}"
rgb_to_hsl(r, g, b)
Converts (R, G, B) color values to an (H, S, L) tuple.
Hue is measured in degrees (0-360), while Saturation and Lightness are measured as percentages (0-100).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
r
|
int
|
Red channel value (0 to 255). |
required |
g
|
int
|
Green channel value (0 to 255). |
required |
b
|
int
|
Blue channel value (0 to 255). |
required |
Returns:
| Type | Description |
|---|---|
float
|
tuple[float, float, float]: HSL values as (h, s, l), where h is in |
float
|
the 0-360 range and s/l are percentages in the 0-100 range. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If any channel is outside the 0-255 range. |
TypeError
|
If any channel is not an integer. |
Example
from py_simple import rgb_to_hsl
rgb_to_hsl(255, 0, 0) # -> (0.0, 100.0, 50.0)
rgb_to_hsl(18, 52, 86) # -> (210.0, 65.38, 20.39)
r, g, b = 18, 52, 86
r, g, b = r / 255, g / 255, b / 255
color_max, color_min = max(r, g, b), min(r, g, b)
delta = color_max - color_min
lightness = (color_max + color_min) / 2
if delta == 0:
hue = saturation = 0
else:
saturation = delta / (1 - abs(2 * lightness - 1))
if color_max == r:
hue = (60 * ((g - b) / delta)) % 360
elif color_max == g:
hue = 60 * ((b - r) / delta) + 120
else:
hue = 60 * ((r - g) / delta) + 240