mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-24 09:57:08 -06:00
Indexed Color: no panic when forced colours fill the palette (#17)
Image > Mode > Indexed Color with Colors 2 + Forced Black and White
(or 8 + Primaries, or <=216 + Web) leaves no room for computed entries.
median_cut(.., 0) returns no centres and kmeans then indexed into the
empty list ("index out of bounds: the len is 0 but the index is 0"),
taking the command down with a panic. kmeans now returns early when
there are no centres, so the palette is just the forced colours.
1 test (algo quantize).
Co-authored-by: storybored379 <storybored379@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
storybored379
Claude Opus 5.5
parent
bf111b524e
commit
b6a95b6c8d
@@ -247,6 +247,10 @@ fn median_cut(pts: &[([f32; 3], u32)], n: usize) -> Vec<[f32; 3]> {
|
||||
|
||||
/// Lloyd refinement of `centers` over weighted points.
|
||||
fn kmeans(pts: &[([f32; 3], u32)], centers: &mut [[f32; 3]], iters: usize) {
|
||||
if centers.is_empty() {
|
||||
// No room left (the forced colours fill the palette): nothing to refine.
|
||||
return;
|
||||
}
|
||||
for _ in 0..iters {
|
||||
let mut sum = vec![[0.0f64; 3]; centers.len()];
|
||||
let mut cnt = vec![0.0f64; centers.len()];
|
||||
@@ -690,6 +694,24 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn forced_colours_filling_the_count_do_not_panic() {
|
||||
// 2 colours + Black and White (or 8 + Primaries) leaves no room for
|
||||
// computed entries; the median cut used to return no centres and
|
||||
// k-means indexed into the empty list.
|
||||
let px = vec![[1.0, 1.0, 1.0, 1.0]; 16];
|
||||
for kind in [
|
||||
PaletteKind::Adaptive,
|
||||
PaletteKind::Perceptual,
|
||||
PaletteKind::Selective,
|
||||
] {
|
||||
let pal = build_palette(&px, kind, 2, Forced::BlackWhite).unwrap();
|
||||
assert_eq!(pal, vec![[0, 0, 0], [255, 255, 255]], "{kind:?}");
|
||||
let pal = build_palette(&gradient(8, 8), kind, 8, Forced::Primaries).unwrap();
|
||||
assert_eq!(pal.len(), 8, "{kind:?}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn quantize_maps_to_palette_with_each_dither() {
|
||||
let pal = vec![[0, 0, 0], [255, 255, 255]];
|
||||
|
||||
Reference in New Issue
Block a user