Brightness, saturation, and hue adjustment
These operations all change pixel appearance, but they are not interchangeable: brightness changes lightness, saturation changes colour intensity, and hue rotates a colour around the wheel. Each section covers one variant and pairs its image with the corresponding code.

Reference outputs were generated with govips v2.19.0 / libvips 8.17.3. pyvips and the CLI do not provide a single-call saturation/hue modulation helper and are marked not-supported for those two variants.
Brightness adjustment
Section titled “Brightness adjustment”govips.Modulate(1.25, 1, 0) raises brightness in LCh; sharp uses HSL semantics. The pyvips and CLI snippets use RGB linear multiplication as an approximation, not a pixel-equivalent implementation.


Generated with govips v2.19.0 / libvips 8.17.3.
image, err := vips.NewImageFromFile("input.jpg")if err != nil { return err }defer image.Close()if err := image.Modulate(1.25, 1, 0); err != nil { return err }data, _, err := image.ExportWebp(vips.NewWebpExportParams())if err != nil { return err }return os.WriteFile("brightness.webp", data, 0o644)await sharp('input.jpg').modulate({ brightness: 1.25 }).webp({ quality: 82 }).toFile('brightness.webp');image = pyvips.Image.new_from_file("input.jpg")bright = image.linear([1.25, 1.25, 1.25], [0, 0, 0])bright.write_to_file("brightness.webp", Q=82)vips linear input.jpg 'brightness.webp[Q=82]' 1.25 0Saturation adjustment
Section titled “Saturation adjustment”govips and sharp expose a direct Modulate / modulate entry point. Because pyvips and the CLI do not ship a single-step modulation helper, they are marked not-supported below rather than presenting an unmodified copy as a saturation transform.


Generated with govips v2.19.0 / libvips 8.17.3.
if err := image.Modulate(1, 0.35, 0); err != nil { return err }await sharp('input.jpg').modulate({ saturation: 0.35 }).webp({ quality: 82 }).toFile('saturation.webp');# pyvips has no single-call modulate helper; requires an LCh colourspace round-trip.# Marked not-supported for this variant.# The CLI has no single modulate command; requires chaining colourspace lch, linear, and colourspace srgb.# Marked not-supported for this variant.Hue adjustment
Section titled “Hue adjustment”Hue is an angular offset; 60 means a 60-degree rotation. govips performs Modulate in LCh, while sharp uses HSL/LCh modulation semantics, so equal numbers do not guarantee equal pixels.


Generated with govips v2.19.0 / libvips 8.17.3.
if err := image.Modulate(1, 1, 60); err != nil { return err }await sharp('input.jpg').modulate({ hue: 60 }).webp({ quality: 82 }).toFile('hue.webp');# Requires a manual sRGB → LCh → H-channel shift → sRGB round-trip; marked not-supported.# Requires chaining colourspace lch → hue channel shift → colourspace srgb; marked not-supported.