diff --git a/server-rs/crates/platform-image/src/pixel_art_snapper.rs b/server-rs/crates/platform-image/src/pixel_art_snapper.rs index 846753f09..589a26a6f 100644 --- a/server-rs/crates/platform-image/src/pixel_art_snapper.rs +++ b/server-rs/crates/platform-image/src/pixel_art_snapper.rs @@ -28,7 +28,10 @@ const MAX_DECODE_ALLOC_BYTES: u64 = PIXEL_ART_MAX_IMAGE_PIXELS * 16; const KMEANS_SEED: u64 = 42; const MAX_KMEANS_ITERATIONS: usize = 15; const PEAK_THRESHOLD_MULTIPLIER: f64 = 0.2; -const PEAK_DISTANCE_FILTER: usize = 4; +// Two peaks can never be adjacent (the left `>=` / right `>` test forbids it), so `2` +// keeps every peak. The previous `4` merged the 2–3 px gaps of soft sub-4 px grids +// into 5–6 px ones and made every such grid come out about twice too coarse. +const PEAK_DISTANCE_FILTER: usize = 2; const STEP_SIZE_PERCENTILE: f64 = 0.3; const WALKER_SEARCH_WINDOW_RATIO: f64 = 0.35; const WALKER_MIN_SEARCH_WINDOW: f64 = 2.0; @@ -828,8 +831,12 @@ fn walk( break; } + // The window start is rounded up and never closer than 2 px to the previous cut: + // with steps of 2–3 px the fixed minimum window would otherwise reach back to + // `current + 1` and split 1 px cells off the real edge. let start = (target - search_window) - .max(current_position + 1.0) + .ceil() + .max(current_position + 2.0) .max(0.0) as usize; let end = ((target + search_window) as usize).min(limit); if end <= start {