Learn / Color

What is an ICC color profile?

Why the exact same RGB numbers can look like different colors depending on where you open the file — and what the small embedded profile inside most images actually does about it.

A close-up of a printing press feeding colorful printed pages through metal rollers
Photo by Bank Phrom on Unsplash

You export the same photo from two different apps, open both files side by side, and one looks very slightly different — a little more saturated, maybe. The pixel data might be identical. The difference is almost always about whether, and how, each piece of software consulted the image's ICC profile.

What the profile actually contains

An ICC profile is a small binary blob embedded in the image file — a header, a table of tags, and the tag data itself. For a typical RGB image profile, the tags that matter most describe: a human-readable description ("sRGB IEC61966-2.1", for example), the profile connection space it maps into (almost always CIE XYZ), and — critically — the actual chromaticity coordinates of its red, green, and blue primaries (the rXYZ/gXYZ/bXYZ tags). Those primaries are the real mathematical definition of exactly which colors this file's numbers correspond to.

Why this matters in practice

RGB values are just three numbers per pixel — they don't mean anything about actual color on their own. (255, 0, 0) is only "red" once you know which color space those numbers are being measured against. Two files can have identical pixel data and represent visibly different real colors if one was authored in sRGB and the other in a wider gamut like Display P3 — see Color spaces, explained for what that actually changes.

Software that isn't color-managed reads the raw numbers and sends them straight to the display, ignoring the embedded profile entirely. If the image was actually authored in a wider gamut than the display assumes, colors can look subtly (or not so subtly) wrong — not because the file is broken, but because the viewer skipped a step.

How we read one, honestly

Classifying a profile's gamut from its raw primaries isn't exact — real-world profiles rarely land on textbook-perfect reference coordinates, even when they're functionally standard sRGB. Inspect compares an embedded profile's actual primaries against known reference gamuts (sRGB, Display P3, Rec.2020) using a defined distance tolerance, calibrated against primaries measured from a real browser-generated sRGB profile rather than a number picked and left unchecked. Outside that tolerance, it's reported as custom or unrecognized — never silently forced into the nearest guess.

This is a genuine byte-level read of the file you give it, not an inference from the file extension or camera model — the same discipline described on the site's Accuracy page.

The practical default

If you're not sure whether a specific image has a profile, or what it declares, Inspect will tell you directly — profile present or not, its description if one exists, and a gamut classification when the primaries genuinely support one. For most web use, sRGB remains the safe, universally-supported default; it's what browsers assume for untagged content and what Headroom's own tools default to when re-encoding.

Questions people actually ask

Is an ICC profile the same thing as a color space?
Related, but not identical. A color space (like sRGB or Display P3) defines a range of colors mathematically. An ICC profile is a small embedded file that tells software which color space a specific image's numbers should be interpreted in — and, for devices, how to translate between a device's native colors and a standard reference space.
What happens if an image has no ICC profile at all?
Most software assumes sRGB by default when no profile is present — it's the long-standing web default. That assumption is usually right, but not guaranteed; an untagged image really could have been authored in a wider gamut and just never got a profile embedded.
Why would two apps show the same file differently?
Usually because one of them isn't color-managed — it's reading the raw numbers and displaying them directly without consulting the embedded profile at all, while the other is properly converting through the profile to the display's actual color space. The file itself hasn't changed; only how faithfully each app interprets it has.
Can I tell what color space a specific file's ICC profile declares?
Yes, directly from the file's real bytes — Headroom's Inspect tool parses the actual ICC header and tag table (description tag, rXYZ/gXYZ/bXYZ primaries) rather than guessing, and reports a gamut classification only when the embedded primaries genuinely match a known reference within a defined tolerance.