FFmpeg CLUT: Map Monochrome to Color Gradient

This guide explains how to map a monochrome or grayscale image to a custom color gradient using FFmpeg's clut (Color Look-Up Table) filter. By pairing a grayscale source with a gradient image, you can create false-color thermal maps, duotone aesthetics, and custom stylized color grading directly from the command line.

How the CLUT Filter Works

The clut filter replaces pixel values of a primary video or image stream using a secondary stream as a color lookup table. For monochrome inputs, the luminance value of each pixel (from 0 to 255) corresponds directly to a horizontal coordinate on the gradient image:

  • A pixel value of 0 (pure black) samples the leftmost edge of the gradient.
  • A pixel value of 255 (pure white) samples the rightmost edge of the gradient.
  • Midtones sample the intermediate colors proportionally across the horizontal axis.

Basic Mapping with an Existing Gradient

To apply a pre-made gradient image to a monochrome file, supply the monochrome image as the first input (0:v) and the gradient image as the second input (1:v):

ffmpeg -i input_mono.png -i gradient.png -filter_complex "[0:v][1:v]clut" output.png

For accurate 8-bit mapping, the gradient file (gradient.png) should ideally be a horizontal strip measuring 256 pixels wide by 1 pixel high (256x1), though standard multi-pixel horizontal gradients will also function.

Generating Gradients Directly in FFmpeg

You can generate a gradient dynamically without an external image file by using FFmpeg's built-in gradients filter.

To create a duotone effect mapping from dark blue (shadows) to bright yellow (highlights):

ffmpeg -i input_mono.png -filter_complex \
"gradients=s=256x1:c0=0x000033:c1=0xFFFF00[grad]; \
[0:v][grad]clut" \
output.png

Handling Pixel Format Mismatches

The clut filter requires compatible pixel formats across both inputs. If your source image is single-channel grayscale (such as gray or gray8), convert both inputs to standard RGB formats inside the filtergraph:

ffmpeg -i input_mono.png -i gradient.png -filter_complex \
"[0:v]format=rgb24[main]; \
[1:v]format=rgb24[lut]; \
[main][lut]clut" \
output.png

Changing Interpolation Modes

By default, the clut filter smoothly interpolates values between color steps. If you want hard, posterized transitions without intermediate blending, set the step option to nearest:

ffmpeg -i input_mono.png -i gradient.png -filter_complex "[0:v][1:v]clut=step=nearest" output.png