SRGB

From Derivative
Jump to navigation Jump to search

Overview[edit]

sRGB colorspace is a complex subject that involves understanding how monitors display color, how pictures/movies are stored, how our eyes percieve color and brightness and how the limited precision of 8-bit images is optimized to store color information more efficiently. sRGB colorspace is very similar to a gamma 2.2 curve, with a linear portion at the low end.

Some other articles that help explain sRGB:
https://www.cambridgeincolour.com/tutorials/gamma-correction.htm
https://en.wikipedia.org/wiki/SRGB
https://blog.johnnovak.net/2016/09/21/what-every-coder-should-know-about-gamma

Monitors[edit]

Generally monitors don't display pixel values linearly. There is usually a curve to how much the brightness changes vs. the pixel's color. Many monitors use the inverse sRGB curve as their outputs, but calibration and other color adjustments affect this. This curve by default will make things darker, as is shown in the curve images in the listed articles. This is done to counter the sRGB curve that is applied to images which the monitor manufacturers know they are usually showing. The two curves essentially cancel each other out, resulting in a visually linear display of brightness.

Visualizing and understanding sRGB on Monitors[edit]

File:SRGBVisualized.9.toe

The above .toe file helps visualize what is going on with your monitor. The node 'fakedMidGrey' is a grid mix of 100% black and 100% white pixels. If you squint a little your eyes will blend these into what it perceieves as mid-grey. Notice how this image is very close is brightness to the 'realMidGrey' which has pixel values of 0.7333, and quite a bit brighter than the 'linearMidGrey' of 0.5. This is because the monitor is darkening the output using the inverse sRGB curve. Note that the monitor's curve is NOT affecting the brightness of 'fakedMidGrey' at all, because it's only showing pixels with the darkest and brightest possible values. The curve won't change these. So we've established what real mid-grey should look like as a constant color. If 'realMidGrey' does not look like 'fakedMidGrey' on your monitor, then it means your monitor curve is not sRGB (gamma 2.2).

Next, look at the 'linearRamp' node. This may look like a correct ramp, especially if you are used to seeing it in TouchDesigner. One would then expect mid-grey to be directly in the middle of this ramp. The sRGBRamp is the same ramp, converted to sRGB space. This ramp may look incorrect depending on what you are used to. Regardless, look at the Over TOPs that are comparing the correct mid-grey with the ramps. Notice how the mid-grey blends in with the sRGB ramp in its middle, while it only blends in with the linearRamp near its top end.

This example should help give a better idea how your monitor shows color values.

Image Data[edit]

Image files such as .jpg, .gif etc usually store the data in 8-bits per color channel. 8-bits per color channel only allows for 256 unique levels of information. This isn't enough information to accurately represent colors to the human eye, so tradeoffs need to be made. Human have better color perception for darks rather than brights, so more of these levels are used to encode the dark information than the bright information. This is generally done by brightening the images with a gamma or sRGB curve. This brings up the dark colors and flattens out the bright ones, giving more levels to the darks.

Consequently, sRGB isn't really a way of brightening data or color-correcting data, but is rather a way of compressing color data in a way that stores the information more efficiently for our eyes. If all images were stored as 32-bit float (or even 10-bit fixed likely), then sRGB would not be needed. It can be thought of more as an encoding rather than a color-correction. This is assuming though, that you were using a monitor that wasn't applying the inverse sRGB transform on values it was receiving. Since most monitors do this, we need to apply the sRGB transform to counteract that behavior.

sRGB Pixel Format in TouchDesigner[edit]

The sRGB Pixel Format in TouchDesigner is what OpenGL/DirectX provides as a hardware-accelerated format. When using this pixel format you will notice that this doesn't affect the brightness of the image. This is because it is only using sRGB as a way to encode the color data into the 8-bit pixels it has. When sampling the texture for viewing the GPU inverts the sRGB curve and brings the data back into its original values. This allows the data to be stored using an sRGB curve, but used in linear space, since it's converted to linear during sampling automatically.

This file helps visualize sRGB as an encoding. Notice how with sRGB encoding the same ramp is much more steppy at the bright end, and smoother at the low end. This helps keep more information at the low end, where we have better perception.

File:SRGBEncoding.toe

Higher Precision Pixel Formats[edit]

Since higher precision pixel formats have many more levels of values available to store information (10-bit has 1024 levels), using a sRGB curve to store the data isn't nesseary. These formats can stay linear, and more file formats that are storing higher bit precision data (such as .exr with 16-bit float or 32-bit float) will be storing the data linearly.

Rendering[edit]

All rendering operations are done in linear color space, and stored by default in linear space. If you are working with only 8-bit precision, you can store them in sRGB space instead by setting the pixel format to sRGB 8-bit. This will store the color information more efficiently. Downstream TOPs will automatically decode the sRGB to linear when doing their operation. When working in higher...

TouchDesigner and sRGB[edit]

TouchDesigner does not have a proper sRGB pipeline currently. A few things are done wrong by default (which we plan to fix). First, we load files that are sRGB encoded (such as JPG) as-is. Technically we should be either converting them to linear, or load them in an sRGB texture by default.

This can be fixed manually by selecting 'Input is sRGB' on the 'Image' page of the Movie File In TOP. Without doing this we are doing compositing operations (which must be done in linear space) using color data that has a sRGB curve applied to them, which is incorrect. With 'Input is sRGB' on, an sRGB texture will store the data using the sRGB curve, then when color values are sampled in the TOP for any operation, it is converted to linear space automatically.

The other thing that TouchDesigner does not do correctly currently is convert linear data back to sRGB before displaying it. In the Monitors section of this article we showed why that was nesseary. Essentially, we should 'brighten' the image to sRGB curve, to counteract the inverse sRGB curve the monitor has. Currently that can be done by using the OpenColorIO TOP.