epaper-dithering-core 4.0.1

High-quality dithering algorithms for e-paper / e-ink displays — OKLab color matching, error diffusion, ordered dithering, measured palettes
Documentation

epaper-dithering-core

High-quality dithering for e-paper / e-ink displays.

  • Weighted Cartesian OKLab color matching — perceptually accurate, hue-preserving, no achromatic-attractor bug
  • 7 error diffusion kernels — Floyd-Steinberg, Atkinson, Burkes, Stucki, Sierra, Sierra Lite, Jarvis-Judice-Ninke
  • Ordered (Bayer 4×4) dithering — perceptually-correct sRGB-space thresholding, parallelized via rayon
  • Measured palettes — calibrated colors for real displays (Spectra 7.3", BWRY 3.97", and more)
  • Pre-dither knobs — exposure, saturation, shadows, highlights, dynamic-range compression, gamut compression
  • Serpentine scanning — reduces directional artifacts in error diffusion

Examples

Frankfurt at night — Spectra 6-color, auto tone + gamut

Usage

use epaper_dithering_core::{
    dither, DitherConfig,
    enums::DitherMode,
    palettes::ColorScheme,
    types::ImageBuffer,
};

// pixels: flat RGB bytes, row-major (width × height × 3)
let img = ImageBuffer::new(&pixels, width);
let indices = dither(&img, ColorScheme::Bwr, DitherConfig {
    mode: DitherMode::FloydSteinberg,
    ..Default::default()
});

With a measured palette and pre-dither adjustments:

use epaper_dithering_core::{
    dither, DitherConfig,
    enums::{DitherMode, ToneCompression, GamutCompression},
    measured_palettes::SPECTRA_7_3_6COLOR,
    types::ImageBuffer,
};

let img = ImageBuffer::new(&pixels, width);
let indices = dither(&img, &SPECTRA_7_3_6COLOR, DitherConfig {
    mode: DitherMode::Stucki,
    saturation: 1.3,           // boost saturation
    shadows: 0.4,              // lift shadows
    tone:  ToneCompression::Auto, // opt in for photos
    gamut: GamutCompression::Auto,
    ..Default::default()
});

DitherConfig defaults: Burkes, serpentine: true, exposure: 1.0, saturation: 1.0, shadows: 0.0, highlights: 0.0, tone: Fixed(0.0), gamut: None.

Pipeline order: exposure → saturation → shadows/highlights → tone → gamut → dither.

DitherMode::None performs direct nearest-color mapping without error diffusion or ordered dithering. dither_with_canonical lets measured palettes use calibrated RGB values for matching while preserving the canonical display palette for exact-color bypass and firmware indices.

With dither_with_canonical, exact canonical display colors are also protected in ordered and error-diffusion modes when pre-processing is off: an image made entirely of display colors is returned as a direct palette-index map, and exact display-color pixels inside a mixed image keep their canonical index instead of being rematched to the measured RGB palette. Pre-processing runs before that exact-pixel check, so explicit tone/gamut compression or other adjustments may intentionally alter those pixels first.

Related packages