Skip to content

Add IccProfilePlot: data-first profile visualization API + CLI#1264

Open
colourbill-ctrl wants to merge 3 commits into
InternationalColorConsortium:masterfrom
colourbill-ctrl:feature/iccprofileplot-data-api
Open

Add IccProfilePlot: data-first profile visualization API + CLI#1264
colourbill-ctrl wants to merge 3 commits into
InternationalColorConsortium:masterfrom
colourbill-ctrl:feature/iccprofileplot-data-api

Conversation

@colourbill-ctrl

@colourbill-ctrl colourbill-ctrl commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

What this is

A new, standalone command-line tool — iccProfilePlot — under Tools/CmdLine/IccProfilePlot/, built on a new data-first visualization model, IccVizModel. Where iccProfileVisualize renders a finished PDF/TIFF report, IccVizModel returns the underlying data for each visualization:

  • Graphs (tone curves, the CIE 1931 chromaticity chart, named/colorant a*b* and xy scatters) come back as point series + axis hints.
  • The nD CLUT lattice comes back as ICC-normalized samples + geometry.

A caller then draws, colour-manages, or exposes individual graphs and their data however it likes — into a PDF, an SVG, JSON, or an interactive UI.

Developed in parallel to iccProfileVisualize, on purpose

This is effectively a major refactor of the iccProfileVisualize visualization code toward a data-first API. For regression and safety, that refactor is being carried out outside the iccProfileVisualize codebase rather than in place — iccProfileVisualize is left completely untouched, so there is no risk to the actively-developed tool, and the two can be diffed and validated independently. The intent is a parallel track that can later converge, not an in-place rewrite.

Faithful to the original where it counts

As much as possible, the original guard rails, commenting, and structure have been preserved, so the two read alike:

  • the per-condition CLUT/curve/named-colour guards and their recovery behaviour are carried over,
  • the inline domain comments travel with the code they explain,
  • diagnostics emit the same text as the original (Skipping <tag>: invalid CLUT width, WARNING - tile count overflow., …).

A silent mode lets the caller turn the CLI/stderr diagnostic echo on or off to suit its context: by default the model echoes diagnostics to stderr exactly like iccProfileVisualize (so the CLI behaves identically out of the box); a library embedding (e.g. WASM/browser) calls SetSilent(true) to suppress it, while still receiving every reason as structured data. A per-call Verbosity can override the global switch either way.

The API

See the usage guide at the top of IccVizModel.hpp, echoed as a worked example in iccProfilePlot.cpp:

Enumerate(pIcc)            -> [Descriptor{ kind, output, id, title }, ...]
RenderGraph (pIcc, id)     -> Graph  { series[], xAxis, yAxis }
RenderRaster(pIcc, id)     -> Raster { width,height,channels,..., samples }

Pick a visualization by Kind, supply a CIccProfile*, and render the one you want as graph data or raster samples.

Scope note: the demo tool does not emit PDF (yet)

iccProfilePlot is a demonstration consumer of the API — it lists visualizations and serializes the returned graph/raster data (JSON / raw samples). It deliberately does not emit a PDF at this point; producing a finished report would require drawing the returned data into MiniPDF (the rendering layer iccProfileVisualize uses), which is intentionally left out so the model and this tool stay dependency-light (IccProfLib only). The commented walkthrough in iccProfilePlot.cpp shows exactly where a PDF generator would slot in.

Build / test

  • New Build/Cmake/Tools/IccProfilePlot/CMakeLists.txt, registered in the top-level CMake; builds clean against IccProfLib via the standard CMake build.
  • CLI verified: iccProfilePlot <profile> list | graph <id> | raster <id> [out.raw].

🤖 Generated with Claude Code


Update — second commit (bbd8109): a PDF/TIFF report tool on the engine

The scope note above ("the demo tool does not emit PDF yet") is now addressed: a
second tool draws finished artifacts through the engine.

iccProfileVisualize (in the same Tools/CmdLine/IccProfilePlot/ dir — a parallel,
data-first reimplementation; the standalone tool of the same name is left untouched)
reproduces that tool's PDF (tone curves, chromaticity, named-colour scatters) and
per-tag TIFF output. Instead of walking the profile and computing geometry inline,
it enumerates and renders through IccVizModel and draws the returned data with
the dependency-free Mini{PDF,SVG,TIFF} writers. The engine is the single source of
the maths; the tool is just a drawing front-end.

Changes (all under Tools/CmdLine/IccProfilePlot/, plus the tool's CMake target)

  • New iccProfileVisualize.cppprocessLuts() calls iccviz::Enumerate(),
    then per descriptor RenderGraph / RenderRaster, drawing each with the Mini
    writers (renderChromaticityGraph, renderCurveGraph, the reused
    graphNamedColorsPDF, and WriteTIFF straight from the raster). The original
    drawing primitives and reference-geometry XObjects are preserved verbatim; the
    now-superseded inline extractors were removed (lineage noted in comments).
  • New MiniPDF / MiniSVG / MiniTIFF — the dependency-free writers carried
    over from the standalone tool. No third-party libraries.
  • IccVizModel.{hpp,cpp}Enumerate(pIcc, Order order = Order::Canonical):
    Canonical is the existing fixed, cross-module/WASM-safe order; the opt-in
    Order::TagTable reorders the same descriptors to the profile's tag-table page
    sequence so a report matches the original. Also v5 named colours in
    collectNamedColors (icSigTagArrayType: NamedColorArray / ColorantInfoArray —
    PCS float arrays → Lab, names via UTF8/UTF16/Text/MLU, tint-% suffixes), with the
    PCS basis aligned to the profile header PCS.
  • Build/Cmake/Tools/IccProfilePlot/CMakeLists.txt — registers an
    iccProfileVisualizePlot executable (distinct output name so it doesn't clash
    with the standalone iccProfileVisualize on install). Verified to configure and
    build in-tree.

Testing

Built both tools against the same IccProfLib and ran them over a 90-profile corpus
(RGB matrix, CMYK / N-colour CLUT, named/spot, wide-gamut, iccMAX), comparing every
artifact byte-for-byte against the original standalone iccProfileVisualize:

Result
Crashes 0 / 0
Per-tag TIFFs 355 / 355 byte-identical
PDFs 77 / 77 byte-identical (page order matched via Order::TagTable)
Artifact-name-set mismatches 0

IccVizModel.cpp compiles clean under -Wall -Wextra. One intentional difference: a
present-but-malformed curve (e.g. bad-bluecurve.icc) is enumerated and rendered with
a diagnostic, where the original silently dropped the page — consistent with IccViz's
"surface the reason" design.

Introduces a standalone Tools/CmdLine tool, iccProfilePlot, built on a new
data-first visualization model (IccVizModel). Where iccProfileVisualize renders
a finished PDF/TIFF report, IccVizModel returns the underlying DATA for each
visualization — point series + axis hints for graphs, ICC-normalized samples +
geometry for the nD CLUT raster — so a caller can draw, colour-manage, or expose
individual graphs however it likes.

The visualization math, structure, comments and granular stderr diagnostics are
carried over from iccProfileVisualize as faithfully as possible, so the two read
alike; the tool depends only on IccProfLib.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added Tools Command-line tool or GUI tool changes Source C or C++ source code changes Configuration Repository, CMake, YAML, JSON, or tool configuration Build Build system, CMake, compiler, or packaging labels Jun 8, 2026
@xsscx xsscx removed request for maxderhak and xsscx June 8, 2026 01:12
@ChrisCoxArt

Copy link
Copy Markdown
Contributor

Note that MiniPDF and MiniTIFF don't call libraries: they are self-contained, so profileVisualize also has no additional dependencies.

@ChrisCoxArt

ChrisCoxArt commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

OK, code looks decent.
If Max agrees to this approach, we can merge. (then later try to converge source so we don't duplicate as much)

@ChrisCoxArt ChrisCoxArt requested a review from maxderhak June 8, 2026 01:45
@colourbill-ctrl

Copy link
Copy Markdown
Contributor Author

if you're ok with it, I'll start work on pulling in the rest of the functionality (minitiff, etc) up to putting together something with the same calling approach as the current iccProfileVisualize and emitting PDF.

colourbill-ctrl and others added 2 commits June 7, 2026 22:06
Add a PDF/TIFF report generator that drives off IccVizModel instead of
walking the profile inline: processLuts() enumerates via iccviz and draws
each graph/raster with the dependency-free Mini{PDF,SVG,TIFF} writers.
Reproduces the standalone iccProfileVisualize artifacts byte-for-byte over
a 90-profile corpus (355/355 per-tag TIFFs, 77/77 PDFs identical).

IccVizModel gains Enumerate(pIcc, Order) -- Order::TagTable reorders to the
profile's tag-table page sequence (Order::Canonical stays the portable
default) -- and v5 named colours (icSigTagArrayType: NamedColorArray /
ColorantInfoArray) in collectNamedColors, with the PCS basis aligned to the
profile header PCS.

Registers an iccProfileVisualizePlot CMake target.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…rewrite

The processLuts rewrite (data-first dispatch) dropped several future-work
breadcrumbs carried over from iccProfileVisualize, including the gamut-plot
TODO tied to the in-flight convex_hull2D work. Restore them (comment-only):
gamut-from-A2B/B2A (annotated to the reserved convex_hull2D/cross helpers),
named-spectra, response curves, curveSetElement/singleSampledCurve/
segmentedCurve, and the spectra->PCS note in the v5 named-colour branch.

No code change; convex_hull2D, cross(), and outputResponseCurves were already
intact (the earlier prune removed only the superseded extraction layer).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ChrisCoxArt ChrisCoxArt assigned maxderhak and unassigned ChrisCoxArt Jun 8, 2026
@xsscx

xsscx commented Jun 14, 2026

Copy link
Copy Markdown
Member

Request for Review

2026-06-14 01:55:09 UTC

@maxderhak When time permits this PR #1264 is Pending your Approval to Merge.

Thank You

@xsscx xsscx self-requested a review June 18, 2026 16:28

@xsscx xsscx left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

2026-06-18 16:27:52 UTC

Please review suggested corrections & minimization changes on Branch https://github.com/InternationalColorConsortium/iccDEV/tree/ci-refactor-cmake-pr1264

PR Dupe Files

  • MiniPDF.cpp
  • MiniPDF.hpp
  • MiniSVG.cpp
  • MiniSVG.hpp
  • MiniTIFF.cpp
  • MiniTIFF.hpp
  • spectralLocus.hpp

Remarks

  • byte-identical

Harvest Branch

  • PR net minus dupes

@xsscx xsscx self-requested a review June 18, 2026 17:19

@xsscx xsscx left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Status

2026-06-18 17:09:06 UTC

  1. PR opened Date: Sun Jun 7 22:27:40 2026 -0700
  2. PR Review Window 14 days on Sun Jun 21 22:27:40 2026 -0700

Observations

  • Maintainer Authored - @colourbill-ctrl
  • Maintainer Approved - @ChrisCoxArt
  • Valid Use Cases
  • Code Reuse
    • iccProfileVisualizer
    • Output Writers
  • Manual Code Review - @xsscx
  • Automated Code Review
  • Cleared all CI PR Checks

Resolution

  1. Label of Merge Pending will be Added
  2. Intent to Merge 30-June-2026 pending:
  • Merge Approvals Withdrawn
  • Requested Changes by ICC Leads

@xsscx xsscx added the Pending Merge Maintainer indicates Merge Pending and Requests No Further Changes label Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Build Build system, CMake, compiler, or packaging Configuration Repository, CMake, YAML, JSON, or tool configuration Pending Merge Maintainer indicates Merge Pending and Requests No Further Changes Source C or C++ source code changes Tools Command-line tool or GUI tool changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants