Color Science for Developers: Understanding LUTs
A deep dive into color lookup tables, their mathematical foundations, and building a color grading pipeline in Python.
Look Up Tables (LUTs) are fundamental to modern color grading, yet their inner workings remain mysterious to many developers. Let’s demystify them by building a color grading pipeline from scratch.
What is a LUT?
A LUT is essentially a function that maps input colors to output colors. Think of it as a giant lookup table where you can find any RGB input value and see what output value it should become.
The Mathematics
A 3D LUT creates a cubic lattice in color space. Each point in the cube represents a specific RGB combination, and the values stored at that point define the transformation.
import numpy as np
def apply_lut(image, lut, size=33):
"""Apply a 3D LUT to an image."""
# Normalize to 0-1 range
normalized = image / 255.0
# Scale to LUT indices
indices = normalized * (size - 1)
# Trilinear interpolation for smooth results
return trilinear_interpolate(lut, indices)
Building Cinegrade
This understanding led me to build Cinegrade, an open-source tool that generates custom LUTs based on film stock characteristics. The key insight was treating historical film data as training data for the color transformations.