How do color pickers work? - HSL Panel
Tags: colorpicker, tutorial, colors, python
Published: 2020-08-29 17:54:42

# Introduction

In this part, I'll explain the theory behind colors and build the HSL Color panel, this is a first color picker I'll cover.

_Note: I will **not** explain the math behind colorspace conversions_

# What is the color?

English Wikipedia says a _Color is the visual perceptual property corresponding in humans to the categories called red, yellow, blue, etc._

In computer science, colors are defined in a lot of different ways, we have color spaces like RGB, CMYK, HSL, YCbCr, and more.

In this part, we will focus on RGB and HSL.

## Why there isn't one unified color format?

Because it's impossible! All color spaces have different properties, and they are used for different things.

Let's get an RGB and CMYK for example.

## RGB 

RGB is a color format that uses the Red Green and Blue channel to represent the color by additive color mixing. That means when you project all three colors, you'll get white.

![visual representation of RGB illumination](https://upload.wikimedia.org/wikipedia/commons/2/28/RGB_illumination.jpg)

RGB is mostly used in displays, each pixel is divided into 3 "subpixels" which are R, G, and B channels. Displays are black when turned off*, so RGB is good for the task.

_*Well, black is displayed differently on different screen types, OLED does that by turning off individual pixels, but LED can't do that, it imitates black, that's why OLED screens can achieve true blackness_

### Why Red, green, and blue?

The answer is simple, it's because of how our eye is built and how do we perceive colors. I won't dig into details, you can read more about RGB on very complex and detailed [Wikipedia article](https://en.wikipedia.org/wiki/RGB_color_model)

## CMYK

Cyan, Magenta, Yellow, and Key (Black)

CMYK, on the other hand, uses subtractive color mixing, instead of additive, when you project the Cyan, Magenta, and Yellow it will yield the black color.

![CMYK subtractive color mixing](https://upload.wikimedia.org/wikipedia/commons/c/c9/CMYK_subtractive_color_mixing.svg)

You can see that on both images, you can distinct the RGB and CMY.

CMYK color space is used mostly in printing, paper sheets are white, so you don't need any ink for white color, but you need all colors to get black, that's why RGB wouldn't work for printing. CMYK is the reason why you can't sometimes print a black document because of a lack of Magenta ink.

# Color range gradient

I bet you saw a gradient like that somewhere

![color gradient](https://raw.githubusercontent.com/PixiEditor/ColorPicker/master/src/ColorPicker/Images/ColorPalette.png)

But, how is it made?

Let me introduce you to an HSL format.

# Hue, Saturation and Lightness

This is what the name stands for. It's different from RGB and CMYK because each value doesn't describe a "separate color". 

![HSL color cylinder](https://upload.wikimedia.org/wikipedia/commons/6/6b/HSL_color_solid_cylinder_saturation_gray.png)

Hue - 0-360° - a _pure_ pigment, the main property
Saturation - 0-100% (or 0-1) - a greyness property
Lightness - 0-100% (or 0-1) - a color lightness property, where 0 is black and 100 is white

Hue values: 
![Hue values image](https://upload.wikimedia.org/wikipedia/commons/a/ad/HueScale.svg)

## Cool, but what about that?

This color space is ideal to easily represent data in 2D space. We can associate the X and Y coordinates with H and S values. By doing so, we can achieve the mentioned gradient above.

I prepared a small [gist](https://gist.github.com/flabbet/45d41e365dd59d7ea4528a8297cb0c50) in python to generate it.

```py
from PIL import Image
import colorsys

width = 360
height = 100

image = Image.new("RGB", (width, height))

for y in range(height):
    for x in range(width):
        color = colorsys.hls_to_rgb(x / 359, abs((y/100) - 1), 1)
        image.putpixel((x,y), (int(color[0] * 255), int(color[1] * 255), int(color[2] * 255)))

image.save("ColorPalette.png", "PNG")
```

Color is calculated based on X and Y coordinates from HSL, converted to RGB, and then displayed on the screen. Isn't that neat?

So whenever the user clicks on some part of this gradient, we can easily get color based on coordinates(X: Hue - 0-360, Y: Saturation - 0-100 and Lightness 100%)

We can create almost any other color picking widget by using the HSL color space.

# Conclusion

I described almost all knowledge _needed to understand single panel HSL color picker_, but there is a lot more to learn about colors, it's a huge topic and worth to dive in.

Stay tuned!