Color Palette in FuncSketch

Color Palette in FuncSketch#

Hide code cell source

import colour
import colour.notation
import numpy
import plotly.graph_objects
import IPython.display
import plotly.io

# cspell: ignore RRGGBB


def hex_rgb_to_oklch(hex_color: str) -> numpy.ndarray:
    """Convert RGB in hexadecimal format to Oklch.

    Args:
        hex_color (str): Hexadecimal color string (e.g., "#RRGGBB").

    Returns:
        numpy.ndarray: Oklch color representation (lightness, chroma, hue).
    """
    return colour.convert(colour.notation.HEX_to_RGB(hex_color), "sRGB", "Oklch")


def plot_color_palette(center_oklch: numpy.ndarray) -> IPython.display.HTML:
    """Plot color palette.

    Args:
        center_oklch (numpy.ndarray): Center color in Oklch.

    Returns:
        IPython.display.HTML: HTML representation of the color palette plot.
    """
    l_point = numpy.array([0.0, center_oklch[0], 1.0])
    c_point = numpy.array([0.0, center_oklch[1], 0.0])
    h_point = numpy.array([center_oklch[2]] * 3)

    l_interp = numpy.linspace(0.0, 1.0, 101)
    c_interp = numpy.interp(l_interp, l_point, c_point)
    h_interp = numpy.interp(l_interp, l_point, h_point)

    lch_interp = numpy.stack((l_interp, c_interp, h_interp), axis=1)

    rgb_interp = colour.convert(lch_interp, "Oklch", "sRGB")

    rgb_bytes = numpy.round(rgb_interp * 255).astype(int)
    if numpy.any(rgb_bytes < 0) or numpy.any(rgb_bytes > 255):
        raise ValueError("RGB values are out of bounds.")

    rgb_in_hex = [f"#{r:02x}{g:02x}{b:02x}" for r, g, b in rgb_bytes]

    figure = plotly.graph_objects.Figure()
    figure.add_heatmap(
        z=l_interp,
        x=list(range(len(rgb_in_hex))),
        y=[0] * len(rgb_in_hex),
        coloraxis="coloraxis",
        text=rgb_in_hex,
        showscale=False,
    )
    figure.update_layout(
        {
            "coloraxis": {
                "colorscale": [
                    [pos, color] for pos, color in zip(l_interp, rgb_in_hex)
                ],
                "cmin": 0.0,
                "cmax": 1.0,
            }
        }
    )

    return IPython.display.HTML(
        plotly.io.to_html(
            figure,
            full_html=False,
            include_plotlyjs="cdn",
            include_mathjax=False,
        )
    )

Primary Color#

Hide code cell source

PRIMARY = numpy.array([0.7, 0.14, 0.15])
plot_color_palette(PRIMARY)

Gray Color#

Hide code cell source

GRAY = numpy.array([0.7, 0.02, 0.15])
plot_color_palette(GRAY)

Error Color#

Hide code cell source

ERROR = hex_rgb_to_oklch("#CB0541")
plot_color_palette(ERROR)