diff --git a/src/edges.rs b/src/edges.rs index 38ce3d9e..19f25602 100644 --- a/src/edges.rs +++ b/src/edges.rs @@ -129,9 +129,11 @@ fn hysteresis(input: &Image>, low_thresh: f32, high_thresh: f32) -> Im // Track neighbors until no neighbor is >= low_thresh. while let Some((nx, ny)) = edges.pop() { let neighbor_indices = [ + (nx + 1, ny - 1), (nx + 1, ny), (nx + 1, ny + 1), (nx, ny + 1), + (nx, ny - 1), (nx - 1, ny - 1), (nx - 1, ny), (nx - 1, ny + 1), @@ -142,6 +144,13 @@ fn hysteresis(input: &Image>, low_thresh: f32, high_thresh: f32) -> Im let out_neighbor = *out.get_pixel(neighbor_idx.0, neighbor_idx.1); if in_neighbor[0] >= low_thresh && out_neighbor[0] == 0 { out.put_pixel(neighbor_idx.0, neighbor_idx.1, max_brightness); + if neighbor_idx.0 == 0 + || neighbor_idx.0 >= input.width() - 1 + || neighbor_idx.1 == 0 + || neighbor_idx.1 >= input.height() - 1 + { + continue; + } edges.push((neighbor_idx.0, neighbor_idx.1)); } } diff --git a/src/filter/mod.rs b/src/filter/mod.rs index dda1fcdd..39ea71b2 100644 --- a/src/filter/mod.rs +++ b/src/filter/mod.rs @@ -810,6 +810,19 @@ mod tests { let image2 = gaussian_blur_f32(&image, 6f32); assert_pixels_eq_within!(image2, image, 1e-6); } + + #[test] + fn test_canny_zero_threshold_panic() { + let image = image::GrayImage::new(10, 10); + _ = crate::edges::canny(&image, 0.0, 0.0); + } + + #[test] + fn test_canny_one_border_pixel_panic() { + let mut image = image::GrayImage::new(10, 10); + *image.get_pixel_mut(9, 0) = Luma([255u8]); + _ = crate::edges::canny(&image, 0.0, 100.0); + } } #[cfg(not(miri))] diff --git a/tests/data/truth/zebra_canny.png b/tests/data/truth/zebra_canny.png index 48577dde..f4a8c4a0 100644 Binary files a/tests/data/truth/zebra_canny.png and b/tests/data/truth/zebra_canny.png differ