Skip to content

colourbill-ctrl/chardata

Repository files navigation

CharData — Colour Gamut Comparison Tool

Compares characterisation data from two ICC-profiling CSV files, showing 3D gamut shells, 2D gamut slices, and per-patch ΔE statistics.

Live at chardata.colourbill.com


Running locally

npm install
node server.js
# → http://localhost:3001

No build step for JS — server.js is a static file server only.


Architecture

Everything of substance is in public/index.html. The Express server only serves static files and sets the correct MIME type for .wasm.

Gamut computation (model fitting, 3D mesh, 2D slice) runs in C++ compiled to WebAssembly:

File Purpose
gamut-wasm/gamut-wrapper.cpp C++ source — three embind-exported functions
gamut-wasm/CMakeLists.txt CMake build config for Emscripten
public/wasm/chardata-gamut.mjs Emscripten JS glue (committed build artifact)
public/wasm/chardata-gamut.wasm WASM binary (committed build artifact)
public/gamut.js JS wrapper — loads WASM, exposes window.Gamut

A second, optional WASM module wraps IccProfLib (from iccDEV) for ICC profile header + tag display. It is lazy-loaded only when the user clicks Display File on an ICC slot, so the cold load stays at the gamut module's ~500 KB:

File Purpose
icc-viewer-wasm/wrapper.cpp C++ source — validateProfile + describeTag embind exports
icc-viewer-wasm/CMakeLists.txt CMake build, compiles IccProfLib sources directly
public/wasm/icc-viewer.mjs Emscripten JS glue (committed)
public/wasm/icc-viewer.wasm WASM binary (committed) — ~730 KB, lazy
public/icc-viewer.js JS wrapper — window.IccViewer.{validateProfile, describeTag}

Building the WASM module

Requires WSL (Ubuntu) with Emscripten and nlohmann-json installed.

One-time WSL setup:

# Install Emscripten
git clone https://github.com/emscripten-core/emsdk.git ~/emsdk-install/emsdk
cd ~/emsdk-install/emsdk && ./emsdk install latest && ./emsdk activate latest
source ~/emsdk-install/emsdk/emsdk_env.sh

# Install nlohmann/json
sudo apt install nlohmann-json3-dev

Build:

# From WSL, at the repo root:
scripts/build-wasm.sh              # gamut module (lcms2)
scripts/build-icc-viewer-wasm.sh   # ICC viewer module (IccProfLib from iccDEV)

The ICC viewer build expects iccDEV at /home/colour/code/iccdev (override with ICCDEV_ROOT=...). Artifacts are written to public/wasm/. Commit them alongside any C++ source changes — the Lightsail server has no build toolchain.

The pre-commit hook handles this automatically: if any file under gamut-wasm/ or icc-viewer-wasm/ is staged, the hook runs the matching build script via WSL and stages the rebuilt artifacts before the commit completes. A build failure aborts the commit.


Fresh clone setup

After cloning, run once to activate the pre-commit hook:

git config core.hooksPath hooks

The hook script is tracked in hooks/pre-commit; only the git config pointer needs to be set manually.


Deployment

Pushes to main auto-deploy to Lightsail via GitHub Actions (.github/workflows/deploy.yml). The workflow SSHs into the server, does git pull, runs npm install --omit=dev, and restarts the pm2 process. No build step on the server.

Required GitHub Actions secrets: SSH_HOST, SSH_USER, SSH_PRIVATE_KEY.

To roll back to the pure-JS version, check out the legacy/compare branch — that preserves the app as it was before the WASM migration.


CSV format

Required columns: CYAN, MAGENTA, YELLOW, BLACK, LAB_L, LAB_A, LAB_B

About

Char data NodeJS app

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors