appthere-color
Document-aware color management for Rust — pure Rust ICC transforms, CMYK, soft proofing, and print-ready color policies.
appthere-color fills a gap in the Rust ecosystem: a color model built for document authoring and print workflows, rather than pixel rendering. It provides named color values, CMYK ink representation, ICC profile transforms via a pure-Rust backend (moxcms), rendering intent selection, soft proofing configuration, and output intent policies — all the primitives a document editor, prepress tool, or print-aware renderer needs.
Features
- Pure Rust ICC transforms via
moxcms— no C toolchain, noliblcms2system dependency, cross-compiles cleanly to Android and WASM targets - CMYK and multi-ink color values with f32 component precision
- Named color spaces — sRGB, Display P3, Adobe RGB (1998), ProPhoto RGB, CMYK (generic and profile-bound)
- Rendering intents — Perceptual, Relative Colorimetric, Saturation, Absolute Colorimetric
- Soft proofing configuration — proof profile, simulation intent, gamut warning, paper simulation
- Document color policy — named output intent, fallback profile, per-document color state
- Profile-to-profile transforms — CMYK↔RGB, RGB↔RGB, Lab↔RGB, Gray↔RGB
no_stdcompatible (withmoxcmsbackend, disable default features)
Installation
[]
= "0.1"
No system libraries required. Everything is pure Rust.
Quick Start
Color values
use ;
// RGB color (0.0–1.0 components)
let red = Rgb;
// CMYK ink values (0.0–1.0 per channel)
let rich_black = Cmyk;
// Lab color (D50 whitepoint)
let lab = Lab ;
ICC profile transforms
use ;
let fogra39 = from_bytes?;
let srgb = srgb;
let transform = new?;
let cmyk_pixel = ;
let rgb_pixel = transform.transform_cmyk_to_rgb?;
Soft proofing
use ;
let config = builder
.output_profile
.simulation_intent
.display_profile
.gamut_warning // magenta flag
.paper_simulation
.build?;
let proofing_transform = config.build_transform?;
Document color policy
use ;
let policy = builder
.output_intent
.default_rendering_intent
.fallback_profile
.build;
// Serialize the policy into your document format's color metadata
Color Value Types
| Type | Channels | Range | Notes |
|---|---|---|---|
RgbColor |
R, G, B | 0.0–1.0 | Linear or gamma-encoded depending on profile |
CmykColor |
C, M, Y, K | 0.0–1.0 | Profile-bound ink percentages |
LabColor |
L, a, b | L: 0–100, a/b: ±128 | D50 whitepoint |
XyzColor |
X, Y, Z | 0.0–1.0 (relative) | D50 |
GrayColor |
K | 0.0–1.0 | |
ColorValue |
— | — | Enum over all of the above |
Rendering Intents
These map directly to ICC specification intents and are passed through to the moxcms transform engine without modification.
Soft Proofing
Soft proofing simulates how a document will appear when reproduced on a specific output device (typically a press or printer). appthere-color models proofing as a first-class configuration object rather than a transform flag:
Soft proofing is implemented as two chained transforms internally: source → output simulation space, then simulation space → display. This is semantically equivalent to LCMS2's proofing transform and produces the same result for standard workflows.
Gamut warning modes
ICC Profile Support
Profiles are loaded from raw ICC bytes and backed by moxcms:
// From bytes (e.g. embedded in a document or file)
let profile = from_bytes?;
// From a file path
let profile = from_file?;
// Built-in virtual profiles
let srgb = srgb;
let linear = linear_srgb;
let gray = gray_d50;
Supported transform combinations mirror moxcms capabilities: CMYK↔RGB, RGB↔RGB, Lab↔RGB, Gray↔RGB, and any Display Class profiles up to 16 inks.
Document Color Policy
A ColorPolicy captures the color management configuration for an entire document — the intended output condition, rendering intent, and fallback behavior when profiles are unavailable. This concept appears in PDF/X (OutputIntent), ODF (draw:color-profile), and EPUB (embedded ICC in images), but appthere-color represents it format-agnostically:
Format-specific serialization (e.g. writing an /OutputIntents array into a PDF or the color profile metadata into an ODF package) is the responsibility of the document format crate that depends on appthere-color.
Why not lcms2?
lcms2 is an excellent crate wrapping the mature Little CMS 2 library. If you need spot color (NamedColorList), DeviceLink profiles, or maximum compatibility with exotic real-world ICC profiles, it may be the right choice.
appthere-color uses moxcms instead because:
- No C toolchain required — clean cross-compilation to Android, WASM, and musl targets without a system
liblcms2 - Pure Rust safety guarantees — no
unsafeFFI surface - Simpler CI — no need to manage native library availability across platforms
The tradeoff: moxcms does not yet support spot/named color lookups or some exotic DeviceLink profile classes. For document authoring workflows targeting standard RGB and CMYK output conditions, this is not a practical limitation.
no_std Support
appthere-color is no_std compatible. Disable the default std feature:
[]
= { = "0.1", = false }
ICC file loading from paths requires std. Profile construction from &[u8] and all transform operations work in no_std environments.
License
Licensed under the Apache License, Version 2.0.
moxcms is also Apache 2.0. The full dependency tree is permissively licensed.
Contributing
Issues and pull requests are welcome. The scope of this crate is intentionally narrow — document-authoring color primitives and ICC transforms. Requests for PDF/ODF/EPUB serialization belong in the respective format crates.