Color.ICC.Profile (Color v0.4.0)

Copy Markdown

Reader for ICC v2 / v4 matrix profiles — the form used by sRGB IEC61966-2.1.icc, Display P3.icc, AdobeRGB1998.icc, Generic Lab Profile.icc, and most camera and scanner profiles.

This is intentionally a small subset of the ICC specification:

  • Only input profiles with the RGB colour space and the XYZ profile connection space are supported.

  • Only the matrix-TRC tag set is read: rXYZ, gXYZ, bXYZ, rTRC, gTRC, bTRC, plus wtpt and desc.

  • curv (LUT) and para (parametric, types 0–4) tone response curves are both supported.

  • LUT-based profiles (mft1, mft2, mAB / mBA) are not supported. Pass them through lcms2 via a NIF if you need them.

Workflow

{:ok, profile} = Color.ICC.Profile.load("/path/to/sRGB Profile.icc")
profile.description           # "sRGB IEC61966-2.1"
profile.white_point           # {0.9642, 1.0, 0.8249}  (PCS, D50)
profile.matrix                # 3x3 column-XYZ list
profile.trc.r                 # %{type: :curve, gamma: 2.4} or {:lut, list}

Once loaded, a profile can be applied to encoded RGB values:

Color.ICC.Profile.to_xyz(profile, {0.5, 0.5, 0.5})
# => {x, y, z} in the PCS (D50)

Color.ICC.Profile.from_xyz(profile, {0.9642, 1.0, 0.8249})
# => {1.0, 1.0, 1.0}

The PCS for matrix profiles is always D50 / 2° observer; this module emits raw XYZ in that frame and leaves any chromatic adaptation to the caller (Color.XYZ.adapt/3).

Summary

Types

t()

A tone response curve.

Functions

Converts a PCS (D50) XYZ triple back to encoded RGB in the profile's colour space.

Loads an ICC matrix profile from the filesystem.

Parses an ICC profile from a binary already in memory.

Converts an encoded RGB triple in the profile's colour space to PCS XYZ (D50).

Types

t()

@type t() :: %Color.ICC.Profile{
  class: atom(),
  colour_space: atom(),
  description: String.t(),
  matrix: [list()],
  pcs: atom(),
  trc: %{r: trc(), g: trc(), b: trc()},
  version: String.t(),
  white_point: {float(), float(), float()}
}

trc()

@type trc() ::
  {:gamma, float()} | {:lut, [float()]} | {:parametric, atom(), [float()]}

A tone response curve.

Functions

from_xyz(profile, arg)

@spec from_xyz(t(), {number(), number(), number()}) :: {float(), float(), float()}

Converts a PCS (D50) XYZ triple back to encoded RGB in the profile's colour space.

Arguments

  • profile is a Color.ICC.Profile struct.

  • xyz is an {x, y, z} tuple in the PCS (D50, 2° observer).

Returns

  • An {r, g, b} tuple of unit floats. May be outside [0, 1] for out-of-gamut inputs; clip or gamut-map separately.

load(path)

@spec load(Path.t()) :: {:ok, t()} | {:error, Exception.t()}

Loads an ICC matrix profile from the filesystem.

Arguments

  • path is a binary file path.

Returns

  • {:ok, %Color.ICC.Profile{}} on success.

  • {:error, exception} if the file cannot be read or is not a matrix profile.

parse(binary)

@spec parse(binary()) :: {:ok, t()} | {:error, Exception.t()}

Parses an ICC profile from a binary already in memory.

Arguments

  • binary is the full profile bytes.

Returns

  • {:ok, %Color.ICC.Profile{}} or {:error, exception}.

to_xyz(profile, arg)

@spec to_xyz(t(), {number(), number(), number()}) :: {float(), float(), float()}

Converts an encoded RGB triple in the profile's colour space to PCS XYZ (D50).

Arguments

  • profile is a Color.ICC.Profile struct.

  • rgb is an {r, g, b} tuple of unit floats [0, 1].

Returns

  • An {x, y, z} tuple of floats in the PCS (D50, 2° observer).