The Artist's Husband: p5.js Colors

/2020/07/the-artists-husband-p5-colors/images/p5Colors.png

We have been using the p5.js Javascript library. Several p5.js functions take a color as a parameter. For example, you might call background(color) to set the background color, stroke(color) to set the color used to draw lines, or fill(color) to set the color used to fill in shapes. In our past examples, we’ve set various colors, but we haven’t always done so consistently.

So how do you set colors in p5.js? It turns out, pretty much any way you want to!

Grayscale

/2020/07/the-artists-husband-p5-colors/images/p5ColorsGrey.png

You can specify a single number between 0 and 255 as a color, and it will be interpreted as a shade of gray, with 0 being pure black and 255 being pure white. This is about a simple as it gets! In the example above, fill() has been called with values of 0, 100, 200, and 255 resulting in circles ranging from black to white.

RGB

RGB is a little more complicated. RGB stands for Red/Green/Blue. These are the three additive primary colors, the basic colors from which other colors may be derived by adding light sources. Other colors can be generated by mixing these three colors in various proportions. In the RGB color model used in p5.js, each of the three is represented by a value from 0 to 255, where 0 means none of the color, and 255 is the maximum amount of that color. So the total number of colors we can have is 255 x 255 x 255 = 16,581,375 – over 16 million colors! When all the numbers are equal, you get some shade of gray. You can get the same colors we had in the Grayscale example above by calling fill() with (0, 0, 0), (100, 100, 100), (200, 200, 200), and (255, 255, 255). But if you are going to go to all the trouble of typing three numbers instead of one, you may as well get some color out of it!

This example shows four colors:

/2020/07/the-artists-husband-p5-colors/images/p5ColorsRGB.png
  • Olive: (128, 128, 0)
  • A very light blue: (200, 200, 255)
  • Purple: (255, 50, 255)
  • Orange: (255, 165, 0)

RGB Color Strings

If 0 to 255 seems weird and arbitrary, you can also think of RGB in terms of percentages: each of the three numbers is between 0 and 100 instead of 0 and 255. In this case, you would specify your color with and RGB color string. These look like function calls, but are actually just strings that will be interpreted according to the colors they represent. If you wanted to fill with white, you could call fill(255, 255, 255), or use an RGB string: fill("rgb(100%. 100%, 100%)"). If you leave the percent signs out, the number is interpreted as a regular RGB value in the 0-255 range. So all of these calls to fill() specify white:

  • fill(255, 255, 255)
  • fill(“rgb(100%, 100%, 100%)”)
  • fill(“rgb(255, 255, 255)”)

The RGB examples above can be rewritten as:

  • Olive: “rgb(50%, 50%, 0%)” or “rgb(128, 128, 0)”
  • A very light blue: “rgb(78%, 70%, 100%)” or “rgb(200, 200, 255)”
  • Purple: “rgb(100%, 20%, 100%)” or “rgb(255, 50, 255)”
  • Orange: “rgb(100%, 65%, 0%)” or “rgb(255, 165, 0)”

Web Colors

Also known as hex color codes, this is just another way of specifying an RGB color. A bit of explanation is in order if you aren’t already familiar with digital representations. We are used to seeing numbers in base 10 (decimal). Digital systems use bits which have two states, 0 and 1, so they are better represented in base 2 (binary). Translating between decimal and binary is not always obvious, because 10 is not a power of 2. It is common for digital systems to deal with 8 bits at a time (this is referred to as a byte). If you have 8 bits, each of which can be either a 1 or a 0, then there are 256 different possible combinations, and therefore a byte can represent the numbers from 0 to 255. From this it is obvious that the three RGB values are all bytes of 8 bits.

Binary is a little unwieldy: the values of a byte range between 00000000 and 11111111 (0 to 255). Nobody want’s to look at all those 1s and 0s! Instead, we write this in base 16 (hexadecimal). Why 16? Because unlike 10, 16 is a power of 2, and maps to binary quite well. A single hexadecimal character maps to exactly 4 bits of binary, which can assume any of 16 values (0 to 15). But we only have 10 digits (0 to 9) so where do we get the other 6? We’ll use letters: a=10, b=11, …, f=15. So now we can represent 1 byte (8 bits) with two digits – 0 to 255 becomes 00 to ff.

The hex color codes are just the three bytes of RGB expressed as 6 hexadecimal digits. We use “#” in front of this to show that it is in fact a hex code and not some other string. So the examples from the previous section become:

  • Olive: “#808000” (128, 128, 0)
  • A very light blue: “#c8c8ff” (200, 200, 255)
  • Purple “#ff32ff” (255, 50, 255)
  • Orange “#ffa500” (255, 165, 0)

There is a shortcut which can be used in some cases. If the two hexadecimal digits for each of the RGB components are the same, you can just use 3 digits. So “#f0f” is the same as “#ff00ff”, “#582” is the same as “#558822”, etc.

These four examples show some hex color codes:

/2020/07/the-artists-husband-p5-colors/images/p5ColorsWeb.png
  • A yellow “#fc0”
  • A bright green: “#65c323”
  • A deep red: “#800000”
  • A dark blue: “#123456”

HSB

RGB isn’t the only way to think about color. The HSB model desribes color as Hue, Saturation and Brightness.

Hue is the specific color, a value between 0 and 360. Why 360? Because you are choosing the angle on a color wheel. 0 is red. As the angle increaces, the color progresses through the colors of the rainbow - orange, yellow, green, blue, purple, and back to red at 360.

Saturation is a percentage between 0 and 100 which is the richness of the color. 0 will be very pale, while 100 will be very rich.

Brightness is a percentage between 0 and 100 which is the brightness of the color. 0 will black, and 100 will be very bright.

HSB colors are specified with a color string. Here are four examples:

/2020/07/the-artists-husband-p5-colors/images/p5ColorsHSB.png
  • A mustard yellow: “hsb(45, 70%, 70%)”
  • A bright green: “hsb(135, 80%, 100%)”
  • Black “hsb(225, 90%, 0%)” (If brightness is 0, the color is always black)
  • A magenta: “hsb(315, 100%, 100%)”

HSL

HSL is very similar to HSB, but with a Lightness value instead of a Brightness value. What’s the difference? When lightness is at 50%, the color is at it brightest. Higher values tend towards white, and lower values tend towards black.

/2020/07/the-artists-husband-p5-colors/images/p5ColorsHSL.png
  • A red: “hsl(0, 50%, 50%)”
  • A green: “hsl(90, 25%, 30%)”
  • A cyan: “hsl(180, 20%, 50%)”
  • A deep purple: “hsl(270, 65%, 40%)”

Named Colors

The last way to specify color in p5.js is with named colors. Colors can be specified using the same names as are used in CSS and SVG. There are 147 of these color name, and you can see a list of them at december.com . To use these, just pass a string containing the name as the color. For example:

/2020/07/the-artists-husband-p5-colors/images/p5ColorsNamed.png
  • “lightsalmon”
  • “teal”
  • “yellowgreen”
  • “antiquewhite”

Depending on what editor you are using to write your programs, you may see that the editor recognizes some color codes, which can be quite helpful. I am using JetBrains GoLand , and when I wrote a short program to generate the example images for this, this is what the colors looked like when I typed them in:

/2020/07/the-artists-husband-p5-colors/images/p5ColorsEditor.png

It doesn’t recognize all the forms, but it does do some, especially the hex codes I normally use. This certainly helps you know you are typing in the color you expect!

It would be sad to not show any code in a post talking about programming! For reference, here is the program that generated the image at the top of this page.

const height = 600;
const width = 600;

const xSpacing = 100;
const ySpacing = 100;
let colors;
function setup() {
    createCanvas(width, height);
    background(240);

    colors = [
        color(0),
        color(100),
        color(200),
        color(255),
        color(128, 128, 0),
        color(200, 200, 255),
        color(128, 50, 128),
        color(255, 165, 0),
        color("#fc0"),
        color("#65c323"),
        color("#800000"),
        color("#123456"),
        "rgb(50%, 50%, 0%)",
        "rgb(78%, 78%, 100%)",
        "rgb(50%, 20%, 50%)",
        "rgb(100%, 65%, 0%)",
        "hsb(45, 70%, 70%)",
        "hsb(135, 80%, 100%)",
        "hsb(225, 90%, 0%)",
        "hsb(315, 100%, 100%)",
        "hsl(0, 50%, 50%)",
        "hsl(90, 25%, 30%)",
        "hsl(180, 20%, 50%)",
        "hsl(270, 65%, 40%)",
        "lightsalmon",
        "teal",
        "yellowgreen",
        "antiquewhite",
        "cornflowerblue",
        "dimgrey",
        "deeppink",
        "lavenderblush",
        "mediumturquoise",
        "midnightblue",
        "chocolate",
        "coral",
    ];
}

function draw() {

    noStroke();
    for(let y=0; y<height; y+=ySpacing) {
        for (let x=0; x<width; x+=xSpacing) {
            let color = colors.shift();
            if (color === undefined) {
                color = 'white';
            }
            fill(color);
            circle(x+xSpacing/2, y+ySpacing/2, Math.min(xSpacing, ySpacing)*.8);
        }
    }

    noLoop();
}

Those of you who are artists (yes, yes, put your hands down, I know all of you are…) may be wondering about the Red/Green/Blue primary colors. Everyone knows the primary colors are Red, Yellow and Blue… It turns out there are several sets of “primary” colors. There is a good explanation of them here .

For a good explanation of the RGB, HSB and HSL color models, see this excellent article .

In p5.js, there is more to color than I have covered here! See the p5.js color reference to learn more about color modes and alpha (transparency).

Have fun!