# What do YUV and Yxy look like?

Some times one needs to detach the luminance from the chrominance in an image. For example, some tonemapping operators compress the luminance of HDR radiances down to a displayable range, and then add the chrominances back. Another situation when splitting information in luminance and chrominance is fundamental is image/video compression (more on this at the end of this post).

Assuming that one starts with colors in RGB, there are different ways to extract the luminance and chrominance values. Let’s start by saying that color spaces are three-dimensional, so no matter what basis you use to encode colors, you will always end up with (at least) three numbers. Actually, typical encodings for luminance/chrominance use one coordinate for the luminance, and two coordinates for the chrominance (e.g., YCrCb, YUV, Yxy, …).

Arion 2 bunny render

I will use this Arion 3 render for this little dissertation. The image uses green predominantly, and there’s little or no blue, so it probably isn’t the best choice ever to talk about colors. But I find the image pretty anyway.

If we split the three R,G,B components of the image, this is what we get:

Red component

Green component

Blue component

Each component looks like a separate grayscale image.

YUV encoding:

The RGB->YUV transform is a simple 3×3 matrix product (i.e., an affine three-dimensional transform). The exact coefficients of the 3×3 matrix vary from one standard to another. Take a look at Wikipedia for more details.

YUV’s Y component

YUV’s U component

YUV’s V component

Interestingly, the Y (luminance) field is a grayscale version of the original image (as expected), but the U,V chrominance fields look like a mid-tone, dumbed-down version of the original.

Note that the 3×3 matrix used to convert from RGB to YUV has negative values which affect the chrominance output. Actually, the U,V values are typically centered around 0 and can be either positive or negative. The luminance component can only be positive, though. For the images shown on this post, U and V were offset to +0.5.

Yxy encoding:

The Yxy system is a bit more complicated. First, one must go from RGB to CIE XYZ. Again, the exact coefficients depend on the color space, but we’re speaking of another affine transform. One that only has positive coefficients, this time. Wikipedia explains how to go from XYZ to Yxy in this page.

The chrominance values x,y are normalized. We’ll get to the implications of this in a minute.

Yxy’s Y component

Yxy’s x component

Yxy’s y component

Again, the chrominance fields look like mostly mid-gray images, with little contrast.

I mentioned normalization a few sentences ago. Let’s see what happens when we compute the YUV and Yxy fields when the intensity of the original image is divided by 2:

YUV’s U component at 50% power — got less contrasted

YUV’s V component at 50% power — got less contrasted

Yxy’s x component at 50% power — not affected

Yxy’s y component at 50% power — not affected

As both luminance fields got half as bright, the chrominance fields got less contrasted in YUV, but remained completely unaffected in Yxy. This is the effect of normalization. The chrominance fields in Yxy are independent of the luminance power. This is not true to YUV.

This is a very important property that makes Yxy suitable for cases of use where one is going to modify the luminance field, and then expects to be able to restore colors regardless of what the changes in luminance have been. A perfect example of this is Arion’s framebuffer tonemapping. Other examples worth mentioning are luminance-based image sharpening and denoising. Sharpening the luminance of an image leads to better results (fewer chromatic artifacts) than sharpening the RGB channels directly.

Below you can see what YUV and Yxy look like in RCSDK’s color chart, which covers the whole RGB range.

RCSDK’s color chart

YUV’s Y component

YUV’s U component

YUV’s V component

Yxy’s Y component

Yxy’s x component

Yxy’s y component

Bonus remark: Back in the late 90’s I spent a lot of time doing research on image and video compression using fractals, wavelets, and other exotic techniques. So I love the subject of data encoding.

Standards such as JPEG and MPEG make use of color spaces like YUV for two reasons:

1- Our eyes are far less sensitive to changes in chrominance than they are to changes in luminance. So it makes sense to spend fewer bits encoding the chrominance fields. It is even normal to downsample the chrominance fields to kill directly some information that your eyes and brain will (literally) overlook.

2- As seen above, it is evident that an encoding like YUV exhibits less entropy than the raw RGB channels, which look like 3 separate grayscale images. Once properly color-encoded, the same information retains most of the variance in the luminance field.

So, from at least two points of view (the human perceptual system and pure Information Theory) encodings that split luminance and chrominance are key.

# My color chart

This is the code-generated color chart that I use for everything that has to do with color calibration in Arion.

RCSDK’s color chart