Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/python/src/epaper_dithering/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
BWRY_4_2,
HANSHOW_BWR,
HANSHOW_BWY,
INKPLATE_6COLOR,
MONO_4_26,
SOLUM_BWR,
SPECTRA_7_3_6COLOR,
Expand All @@ -35,4 +36,5 @@
"SOLUM_BWR",
"HANSHOW_BWR",
"HANSHOW_BWY",
"INKPLATE_6COLOR",
]
19 changes: 19 additions & 0 deletions packages/python/src/epaper_dithering/palettes.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,24 @@ class ColorScheme(Enum):
),
)

# 7-color ACeP (e.g. Inkplate 6COLOR). Color order = panel native nibbles:
# black0 white1 green2 blue3 red4 yellow5 orange6.
BWGBRYO = (
8,
ColorPalette(
colors={
"black": (0, 0, 0),
"white": (255, 255, 255),
"green": (0, 255, 0),
"blue": (0, 0, 255),
"red": (255, 0, 0),
"yellow": (255, 255, 0),
"orange": (255, 128, 0),
},
accent="red",
),
)

GRAYSCALE_4 = (
5,
ColorPalette(
Expand Down Expand Up @@ -223,3 +241,4 @@ def _load_measured_palettes() -> dict[str, "ColorPalette"]:
SOLUM_BWR: ColorPalette = _MEASURED["SOLUM_BWR"]
HANSHOW_BWR: ColorPalette = _MEASURED["HANSHOW_BWR"]
HANSHOW_BWY: ColorPalette = _MEASURED["HANSHOW_BWY"]
INKPLATE_6COLOR: ColorPalette = _MEASURED["INKPLATE_6COLOR"]
30 changes: 30 additions & 0 deletions packages/rust/core/src/measured_palettes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ pub static CATALOG: &[MeasuredPaletteEntry] = &[
scheme: ColorScheme::Bwgbry,
color_names: &["black", "white", "yellow", "red", "blue", "green"],
},
MeasuredPaletteEntry {
id: "INKPLATE_6COLOR",
palette: &INKPLATE_6COLOR,
scheme: ColorScheme::Bwgbryo,
color_names: &["black", "white", "green", "blue", "red", "yellow", "orange"],
},
MeasuredPaletteEntry {
id: "MONO_4_26",
palette: &MONO_4_26,
Expand Down Expand Up @@ -103,6 +109,30 @@ pub static SPECTRA_7_3_6COLOR_V2: Palette = Palette {
accent_idx: 3, // red
};

// ── Inkplate 6COLOR 7-color ACeP ─────────────────────────────────────────────

/// Inkplate 6COLOR (600x448 7-color ACeP, EP585C / panel_ic_type 0x0043).
/// Color order = panel native nibbles: black0 white1 green2 blue3 red4 yellow5 orange6.
/// Hue-representative values tuned 2026-06-18 so source colors select the correct ink
/// (these drive matching only; the panel always renders its own ink for each nibble).
/// Derived from a forced-nibble calibration capture, then de-washed: the panel's raw
/// inks photograph very desaturated (esp. green, contaminated by ghosting), which makes
/// nearest-color matching send vivid greens->yellow and blues->black. Boosting saturation
/// toward each ink's true hue fixes ink selection. TODO: precise per-ink measurement on a
/// ghosting-cleared panel for tone-accurate values.
pub static INKPLATE_6COLOR: Palette = Palette {
colors: Cow::Borrowed(&[
[ 45, 45, 70], // black (dark blue-gray)
[230, 230, 230], // white
[ 60, 150, 80], // green
[ 40, 70, 190], // blue
[200, 40, 40], // red
[235, 215, 90], // yellow
[225, 120, 40], // orange
]),
accent_idx: 4, // red
};

// ── Monochrome displays ───────────────────────────────────────────────────────

/// 4.26" Monochrome. TODO: measure actual display.
Expand Down
35 changes: 35 additions & 0 deletions packages/rust/core/src/palettes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ pub enum ColorScheme {
Grayscale16 = 6,
/// Reserved: 8-level grayscale, pending firmware value assignment.
Grayscale8 = 7,
/// 7-color ACeP (e.g. Inkplate 6COLOR). Color order matches the panel's
/// native nibble codes: black0 white1 green2 blue3 red4 yellow5 orange6.
Bwgbryo = 8,
}

// ── Palette data ─────────────────────────────────────────────────────────────
Expand Down Expand Up @@ -76,6 +79,14 @@ static PALETTE_BWGBRY: Palette = Palette {
]),
accent_idx: 3,
};
// 7-color ACeP. Order = panel native nibbles: black0 white1 green2 blue3 red4 yellow5 orange6.
static PALETTE_BWGBRYO: Palette = Palette {
colors: Cow::Borrowed(&[
[0, 0, 0], [255, 255, 255], [0, 255, 0], [0, 0, 255],
[255, 0, 0], [255, 255, 0], [255, 128, 0],
]),
accent_idx: 4, // red
};
static PALETTE_GRAYSCALE4: Palette = Palette {
colors: Cow::Borrowed(&[[0, 0, 0], [85, 85, 85], [170, 170, 170], [255, 255, 255]]),
accent_idx: 0,
Expand Down Expand Up @@ -110,6 +121,7 @@ impl ColorScheme {
ColorScheme::Grayscale4 => &PALETTE_GRAYSCALE4,
ColorScheme::Grayscale16 => &PALETTE_GRAYSCALE16,
ColorScheme::Grayscale8 => &PALETTE_GRAYSCALE8,
ColorScheme::Bwgbryo => &PALETTE_BWGBRYO,
}
}
}
Expand All @@ -135,6 +147,7 @@ impl TryFrom<u8> for ColorScheme {
5 => Ok(ColorScheme::Grayscale4),
6 => Ok(ColorScheme::Grayscale16),
7 => Ok(ColorScheme::Grayscale8),
8 => Ok(ColorScheme::Bwgbryo),
_ => Err(DitherError::UnknownColorScheme(v)),
}
}
Expand Down Expand Up @@ -171,5 +184,27 @@ mod tests {
assert_eq!(ColorScheme::Mono.palette().colors.len(), 2);
assert_eq!(ColorScheme::Bwgbry.palette().colors.len(), 6);
assert_eq!(ColorScheme::Grayscale16.palette().colors.len(), 16);
assert_eq!(ColorScheme::Bwgbryo.palette().colors.len(), 7);
}

#[test]
fn bwgbryo_is_value_8() {
assert_eq!(u8::from(ColorScheme::Bwgbryo), 8);
assert_eq!(ColorScheme::try_from(8), Ok(ColorScheme::Bwgbryo));
}

#[test]
fn bwgbryo_order_matches_panel_native_nibbles() {
// The dither output index is the 4bpp nibble sent to the panel, so the
// palette order MUST match the Inkplate 6COLOR's native codes:
// black0 white1 green2 blue3 red4 yellow5 orange6.
let c = &ColorScheme::Bwgbryo.palette().colors;
assert_eq!(c[0], [0, 0, 0], "idx0 black");
assert_eq!(c[1], [255, 255, 255], "idx1 white");
assert_eq!(c[2], [0, 255, 0], "idx2 green");
assert_eq!(c[3], [0, 0, 255], "idx3 blue");
assert_eq!(c[4], [255, 0, 0], "idx4 red");
assert_eq!(c[5], [255, 255, 0], "idx5 yellow");
assert_eq!(c[6], [255, 128, 0], "idx6 orange");
}
}