Skip to content

Colour management and ICC profiles

Copy page

An ICC profile specifies how pixel values should be interpreted; it is not another image. A file can still decode, resize, and re-encode cleanly after its profile is dropped, ignored, or replaced, even though its visual appearance has already drifted from the source.

Typical source differences include:

  • Untagged RGB: treated by each interface either as sRGB or as raw channel values.
  • RGB with an embedded ICC profile: requires an explicit decision to retain the profile, transform to a destination space, or strip it on export.
  • CMYK: four ink-separation channels whose values do not mean the same thing as RGB; resizing CMYK directly as if it were RGB produces visibly wrong colours.
  • Wide-gamut spaces such as Display P3: can be clipped or desaturated by an unmanaged sRGB display or encoder while the output file remains structurally valid.

libvips expresses these conversions with operations such as colourspace and icc_transform. A language binding may wrap them inside import options, export options, or an explicit method call. Check the binding’s documentation for its defaults; a call that returns without error does not by itself prove that an ICC transform took place.

Ways a conversion can look successful while drifting in colour

Section titled “Ways a conversion can look successful while drifting in colour”
  • The output opens with the expected dimensions and band count, but the embedded ICC profile was silently dropped during export.
  • A CMYK input was decoded to RGB without recording or controlling the source and destination profiles.
  • A thumbnail path skips colour conversion for speed while the full-size path applies it, causing thumbnails and full-size images to disagree.
  • One libvips build includes LittleCMS (lcms2) support while another container image does not, so the same API call does not perform the same work.

To verify colour management in a production pipeline, test with a sample that genuinely carries the target profile (such as CMYK or Display P3) and check after export:

  • whether the exported header retains the expected destination ICC profile (or has been converted to the target space and stripped as intended);
  • whether the runtime libvips is built with lcms2 support;
  • whether CMYK or profiled inputs are transformed into the working colour space before resizing or compositing.

For diagnosing colour drift and missing profiles in production, see colour shifts, missing ICC profiles, and CMYK distortion. Transparency and dark fringes follow a separate mechanism: see bands, alpha, and transparency.