Generating Tons of Complementary Colors with Processing

Well, this blog should be about Processing! But no, I’m just practicing game asset creation, as I wish to become a master of all trades (and jack of none). Therefore, I’m relaxing my programming muscles a bit with Processing while I’m doing graphics. And maybe, someday, music? I dunno.

So we’ve all heard of the RGB colorspace. Back in the 90s, Apple and Microsoft created this colorspace because HSL wasn’t enough for the creative programming market. Displays were becoming a lot more sophisticated and less happened in monochrome and teletypes. So sRGB was born.

RGB has three to four channels. Red, Green, Blue nad Alpha. Each have a value between 0 and 255. The higher we go, the lighter we get. There are two ways of implementing an RGB color, HEX and Decimal. For HEX display, each channel is converted to its hexadecimal notation and then put together in succession, such as (255, 255, 255) -> #FFFFFF.

In sRGB color wheel, each opposite color go together like America and apple pie. Let me show you what I mean:

In fact, this is true about all colorspaces such as HSL and HSV and CMYK, and in fact, it’s not a new concept: in 1810, painters were already using complementary colors using the traditional RGY color spectrum (in real life, colors are made up of red, green and yellow, not red, green and blue!?).

So, is there an algorithm to generate a complementary color? Of course. Imagine each color is a angle in the unit circle of the color wheel. Imagine FF is 2PI and the color we want is PI/4. So to calculate the opposite angle, we subtract 2PI (360d) from PI/4. As easy as that -> In order to generate the opposing color, we must subtract 255 from each channel.

So how can Processing help us choose the appropriate complementary color? By generating HUNDREDS and THOUSAND of complementary colors in a jiff. Let’s see how it works:

void setup() {
size(500, 500);

}

void draw() {
float r = random(255);
float g = random(255);
float b = random(255);
color bgc = color(r, g, b);

background(bgc);
textSize(16);
text("Background: ", 20, height * 0.10);
text(r, width * 0.5, 20);
text(g, width * 0.5, 50);
text(b, width * 0.5, 80);

float comp_r = 255 - r;
float comp_g = 255 - g;
float comp_b = 255 - b;
color rc = color(comp_r, comp_g, comp_b);

fill(rc);
rect(width * 0.25, height * 0.25, 200, 200);

fill(255);
textSize(16);
text("Complement: ", 20, height * 0.90);
text(r, width * 0.5, 420);
text(g, width * 0.5, 450);
text(b, width * 0.5, 480);

saveFrame("complementary_colors#####.png");

}


In each draw() loop, we generate r, g, and b. Then we display it in the background. Then we display the channel values for reference. Then we generate the complementary color, and display it in a rectangle. You can do it with a circle too. Depends on your taste.

Then, we save it in the folder you’ve saved the .pde file using saveFrame(). That’s it!

Well, hope you’ve enjoyed this tutorial. Next up: How pixel art with Photshop.