Color.Palette.Summarize
(Color v0.13.0)
Copy Markdown
Reduce an arbitrary list of colours to k representative colours by perceptually-uniform clustering.
This module is a thin wrapper over Color.Palette.Cluster. It
takes a list of colour inputs, builds initial singleton
clusters, runs the agglomerative merge to k survivors, and
picks one member from each survivor as the swatch.
Both the merge step and the rep-selection step are exposed
publicly on Color.Palette.Cluster so the
:image library's pixel
extraction pipeline can call exactly the same primitives
(after a Scholar K-means pass) without algorithmic drift.
Algorithm
Each input colour starts as its own cluster; the closest pair
(by mass-weighted Oklab distance, chromatic axes weighted
twice as much as lightness) is merged repeatedly until k
clusters remain. Each cluster's representative is then chosen
by Color.Palette.Cluster.representative/2:
chromatic centroids → highest
chroma × massmember (the most vivid example, weighted by how often it appears);achromatic centroids → member nearest the centroid in weighted Oklab, with mass as tiebreaker.
See Color.Palette.Cluster for the full algorithmic
discussion.
When to use this vs Color.Palette.Sort
Sort orders an existing list of colours; the output has the same number of colours as the input.
Summarize reduces the list to a smaller representative set. Run it before sorting when you have a large bag of near-duplicate swatches.
Complexity
Pairwise distance is recomputed each merge, giving an
O(n³) worst case. This is fine for the typical palette
sizes (tens of colours) the rest of Color.Palette works
with; for thousands of inputs (e.g. raw image pixels), use a
dedicated K-means pass upstream and call summarize/3 (or
Color.Palette.Cluster.merge_until/3) only on the resulting
cluster centroids.
Summary
Functions
Reduces a list of colours to at most k representative
colours.
Functions
@spec summarize([Color.input()], pos_integer(), keyword()) :: [Color.SRGB.t()]
Reduces a list of colours to at most k representative
colours.
Arguments
colorsis a list of values accepted byColor.new/1— hex strings, CSS named colours,%Color.SRGB{}structs, Oklch structs, etc.kis the maximum number of colours in the output. If the input has fewer thankdistinct entries, the output may be shorter.
Options
:weightsis an optional list of non-negative numbers, the same length ascolors. Each weight is the relative mass of its input colour during clustering. Default: every colour weighted1.0.:ab_weightis the multiplier on the chromatic axes(a, b)in the Oklab distance metric, relative to lightnessL. Default2.0.:rep_chroma_thresholdis the Oklch chroma above which the representative member is the highest-chroma original member of its cluster. Below this threshold, the representative is the closest to the centroid in weighted Oklab. Default0.03.
Returns
- A list of
%Color.SRGB{}structs (one per surviving cluster), in the order the merging algorithm settled on. Pipe throughColor.Palette.sort/2for a perceptually ordered strip.
Examples
iex> hexes = ["#ff0000", "#fe0202", "#0000ff", "#0202fe", "#00ff00"]
iex> result = Color.Palette.Summarize.summarize(hexes, 3)
iex> length(result)
3
iex> hexes = ["#ff0000", "#0000ff"]
iex> Color.Palette.Summarize.summarize(hexes, 5) |> length()
2