• Hey Guest,

    We wanted to share a quick update with the community.

    Our public expense ledger is now live, allowing anyone to see how donations are used to support the ongoing operation of the site.

    👉 View the ledger here

    Over the past year, increased regulatory pressure in multiple regions like UK OFCOM and Australia's eSafety has led to higher operational costs, including infrastructure, security, and the need to work with more specialized service providers to keep the site online and stable.

    If you value the community and would like to help support its continued operation, donations are greatly appreciated. If you wish to donate via Bank Transfer or other options, please open a ticket.

    Donate via cryptocurrency:

    Bitcoin (BTC):
    Ethereum (ETH):
    Monero (XMR):
Unbearable Mr. Bear

Unbearable Mr. Bear

Sometimes, all you need is a hug...
May 9, 2025
988
So, there's something that has been something I play with to take my head off the gutter: Coloraide. Coloraide is a python library that is basically color theory central. It can use a shit ton of colorspaces, blend colors with a multitude of methods, create gradients and spectra based on many different rules, it's amazing and activates my monke neuron very much.

But it is a library, so you need to learn python, and that's what I did. Now, I'm no coder, but I really wanted to use the tool so it pushed me forward. Good news is, the website has a lot of clear documentation, with interactive examples, AND a playground, so you can try Coloraide online, without installing anything! https://facelessuser.github.io/coloraide/playground/

I'm posting this here because it could be useful to artists. I'm more of a music person, but I just adore messing around with it, so if you feel like you want something related to color theory, like palettes, gradients, or just visualizing colors, I can code for you. I'll do it happily, I love messing around with the tool, and that would make me feel useful!

Here's an example of what I did in 10 minutes: A palette generator (Mostly for pixel art)
Python:
pal_final = [Color("#000"), Color("#FFF")]
pal_lim = 16
iter = 10000
init_tresh = 1000
tresh = init_tresh

while len(pal_final) < pal_lim and iter >= 0:
    col_ng = False
    new_col = Color.random("srgb")
    for pal_col in pal_final:
        iter -= 1
        if new_col.delta_e(pal_col) < tresh:
            col_ng = True
            tresh *= 0.99
        if col_ng:
            break
    if not col_ng:
        tresh = init_tresh
        pal_final.append(new_col)

iter
len(pal_final)
pal_final

If you paste the code on the "Playground" page, it generates an 8 color palette including black and white, using color delta to make sure the colors are different enough. pal_lim is the size of the final palette, if you wanna change that.

Well there you have it, thanks for reading and I look forward for requests!
 
Last edited:
  • Love
  • Like
Reactions: GlassMoon, Forveleth and kotonearisato
kotonearisato

kotonearisato

memento mori
Feb 13, 2024
118
Whoa, this is awesome. Thanks for sharing! I actually spent some time earlier in the year learning python, so I'm excited to try this out.
 
  • Love
Reactions: Unbearable Mr. Bear
Unbearable Mr. Bear

Unbearable Mr. Bear

Sometimes, all you need is a hug...
May 9, 2025
988
Whoa, this is awesome. Thanks for sharing! I actually spent some time earlier in the year learning python, so I'm excited to try this out.
Glad I could pique your interest. It is an amazing tool but more of a fun toy for me since I'm not into drawing or painting. If you need any tips I already use this tool for like 2/3 years so I have lots of experience.

Really, though, I'm happy I could make you happy. 🧸
 
  • Love
Reactions: kotonearisato
Unbearable Mr. Bear

Unbearable Mr. Bear

Sometimes, all you need is a hug...
May 9, 2025
988
Here's an updated version of the palette generator. Now with a better algorithm for calculating stuff and shit:

Python:
pal_final = [Color("#000"), Color("#FFF")]
pal_lim = 32
iter = 10000
init_tresh = 100
tresh = init_tresh

while len(pal_final) < pal_lim and iter >= 0:
    col_ng = False
    new_col = Color.random("srgb")
    for pal_col in pal_final:
        iter -= 1
        if new_col.delta_e(pal_col, method="hyab", space="cam16-ucs") < tresh:
            col_ng = True
            tresh *= 0.98
        if col_ng:
            break
    if not col_ng:
        print(round(tresh, 2), end=" ")
        tresh = (tresh + init_tresh) / 2
        pal_final.append(new_col)

print(end="")
iter
len(pal_final)
pal_final
 
Not Today Satan

Not Today Satan

Stretcher fetcher
May 9, 2024
909
Error: need pet snake in order to make palette (unfunny joke about python)
 
  • Yay!
Reactions: Unbearable Mr. Bear
Unbearable Mr. Bear

Unbearable Mr. Bear

Sometimes, all you need is a hug...
May 9, 2025
988
Unbearable Mr. Bear

Unbearable Mr. Bear

Sometimes, all you need is a hug...
May 9, 2025
988
New version of the palette generator! Now it shows the colors as hex values, and you can click the color to copy the value. There's also a list of all hex values at the bottom of the output. I also made it sort by hue so the output is a little bit preetier!

EDIT: OH GOD I FORGOT TO ACTUALLY CODE HOLD ON!

Python:
pal_final = [Color("#000"), Color("#FFF")]
pal_lim = 16
iter = 25000
init_tresh = 100
tresh = init_tresh

while len(pal_final) < pal_lim and iter >= 0:
    col_ng = False
    new_col = Color.random("srgb")
    for pal_col in pal_final:
        iter -= 1
        if new_col.delta_e(pal_col, method="hyab", space="cam16-ucs") < tresh:
            col_ng = True
            tresh *= 0.99
        if col_ng:
            break
    if not col_ng:
        print(round(tresh, 2), end=" ")
        tresh = (tresh + init_tresh) / 2
        pal_final.append(new_col)

print(end="")
iter
len(pal_final)
pal_final[:2]
for pal_col in sorted(pal_final[2:], key=lambda col: col.get("zcam-jmh.h")):
    print(pal_col.to_string(hex=True), end=" ")

PHEW...that was close...

Don't hesitate to call me if you want something done in Coloraide. Color theory is my passion. 🐸
 
Last edited:
  • Like
Reactions: GlassMoon
Unbearable Mr. Bear

Unbearable Mr. Bear

Sometimes, all you need is a hug...
May 9, 2025
988
Another version, this time with 2 alternate methods, if you wanna try it out.

Python:
def calcThres(col_a, col_b):
    return col_a.delta_e(col_b, method="hyab", space="cam16-ucs")

def calcThresAlt(col_a, col_b):
    return col_a.distance(col_b, space="hellwig-hk-jmh")

def calcThresAltB(col_a, col_b):
    return col_a.delta_e(col_b, method="2000", space="lab-d65")

pal_final = [Color("#000"), Color("#FFF")]
pal_lim = 64
iter = 50000
init_thres = 100
thres = init_thres

while len(pal_final) < pal_lim and iter >= 0:
    col_ng = False
    new_col = Color.random("srgb")
    for pal_col in pal_final:
        iter -= 1
        if calcThres(new_col, pal_col) < thres:
            col_ng = True
            thres *= 0.99
        if col_ng:
            break
    if not col_ng:
        print(round(thres, 0), end=" ")
        thres = (thres + init_thres) / 2
        pal_final.append(new_col)

print(end="")
iter
len(pal_final)
pal_final[:2]

for pal_col in sorted(pal_final[2:], key=lambda col: col.get("hellwig-hk-jmh.h")):
    print(pal_col.to_string(hex=True), end=" ")
 
Unbearable Mr. Bear

Unbearable Mr. Bear

Sometimes, all you need is a hug...
May 9, 2025
988
Just a minor code cleaning to make it neater. Functionally the same but I'll post cause this is probably my best program for ColorAide!
Python:
def calcThres(col_a, col_b):
    return col_a.delta_e(col_b, method="hyab", space="cam16-ucs")

def calcThresAlt(col_a, col_b):
    return col_a.distance(col_b, space="hellwig-hk-jmh")

def calcThresAltB(col_a, col_b):
    return col_a.delta_e(col_b, method="2000", space="lab-d65")

pal_final = [Color("#000"), Color("#FFF")]
pal_lim = 64
iter = 50000
init_thres = 100
thres = init_thres

while len(pal_final) < pal_lim and iter >= 0:
    col_ng = False
    new_col = Color.random("srgb")
    for pal_col in pal_final:
        iter -= 1
        if calcThres(new_col, pal_col) < thres:
            col_ng = True
            thres *= 0.99
        if col_ng:
            break
    if not col_ng:
        print(round(thres, 0), end=" ")
        thres = (thres + init_thres) / 2
        pal_final.append(new_col)

print(end="")
iter
len(pal_final)

for pal_col in pal_final[:2] + sorted(pal_final[2:], key=lambda col: col.get("hellwig-hk-jmh.h")):
    print(pal_col.to_string(hex=True), end=" ")
 
Unbearable Mr. Bear

Unbearable Mr. Bear

Sometimes, all you need is a hug...
May 9, 2025
988
Wanted to make another code to make so I get all the inversions in a given color space. After some wrestling with Duck.ai and some debugging (I still wrote most of the code btw.) This came out:
Python:
def norm(c, low, high):
    return (c - low) / (high - low)

def denorm(n, low, high):
    return n * (high - low) + low

def inv(c, low, high):
    n = norm(c, low, high)
    n_inv = 1 - n
    return denorm(n_inv, low, high)

def invhue(c):
    return (c + 180.0) % 360.0

space = "hsl"
hue = 0

channels = [
    [0], [1], [0, 1], [2], [0, 2], [1, 2], [0, 1, 2]
]
limits = Color.random(space)._space.CHANNELS
colors = [Color.random("srgb").convert(space)]
# colors[0] = Color("hsv", [30, .7, .7] )

for perm in channels:
    colors.append(colors[0].convert(space))
    for ch in perm:
        if ch == hue:
            colors[-1][ch] = invhue(colors[-1][ch])
        else:
            colors[-1][ch] = inv(colors[-1][ch], limits[ch].low, limits[ch].high)

for c in colors:
    print(
        c
        # .fit('srgb', method='minde-chroma', pspace='zcam-jmh', adaptive=10, jnd=0)
        .convert("srgb")
        .to_string(hex=True), end=" "
    )
P.S.: The hue variable is to set which channel is the hue (0 means the first channel, 1 means second and so on). Commented out stuff is optional stuff, like fitting the color to prevent out of gamut or setting a custom starter color.
 
Last edited: