Skip to content
This repository was archived by the owner on Sep 1, 2025. It is now read-only.

Conversation

@twixan
Copy link

@twixan twixan commented Jul 15, 2025

Problem

Calling the old canny signature as shown in the documentation example fails to compile because the trait bound could never be satisfied:

error[E0277]: the trait bound `image::buffer_::ImageBuffer<image::color::Luma<u8>, Vec<u8>>:
    From<ImageBuffer<Luma<u8>, Vec<u8>>>` is not satisfied
   --> src\main.rs:7:9
    |
6   |     let detection = edge_detection::canny(
    |                     --------------------- required by a bound introduced by this call
7   |         source_image,
    |         ^^^^^^^^^^^^ the trait `From<ImageBuffer<Luma<u8>, Vec<u8>>>` is not implemented for `image::buffer_::ImageBuffer<image::color::Luma<u8>, Vec<u8>>`
    |
    = help: the trait `From<ImageBuffer<Luma<u8>, Vec<u8>>>` is not implemented for `image::buffer_::ImageBuffer<image::color::Luma<u8>, Vec<u8>>`
            but trait `From<image::dynimage::DynamicImage>` is implemented for it
    = help: for that trait implementation, expected `image::dynimage::DynamicImage`, found `ImageBuffer<Luma<u8>, Vec<u8>>`
    = note: required for `ImageBuffer<Luma<u8>, Vec<u8>>` to implement `Into<image::buffer_::ImageBuffer<image::color::Luma<u8>, Vec<u8>>>`

196 | pub fn canny<T: Into<image::GrayImage>>(
    |                 ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `canny`

Changes

  • Signature update
    • Changed
      - pub fn canny<T: Into<GrayImage>>(…)
      + pub fn canny<T: Into<DynamicImage>>(…)
    • Internally convert to gray with
      let dyn_img: DynamicImage = image.into();
      let gs_image: GrayImage    = dyn_img.into_luma8();
  • Documentation update
    • Removed the mandatory .to_luma8() call from the example in lib.rs.
    • Removed the mandatory .to_luma8() call from the example in README.md

Rationale

  • The old bound T: Into<GrayImage> was never satisfied by any concrete type, leading to compilation errors, the example provided by the documentation simply didn't work.
  • Accepting Into<DynamicImage> leverages existing From<Buffer> for DynamicImage implementations, allowing all common image buffers (RGB, RGBA, Luma, etc.) to be passed in.
  • Conversion to 8‑bit grayscale remains unchanged internally, preserving the algorithm’s assumptions.

Usage Examples

// 1) Explicit grayscale conversion:
let source_image = image::open("testdata/line-simple.png")
    .expect("failed to read image")
    .to_luma8();

let detection = edge_detection::canny(
    source_image,
    1.2,  // sigma
    0.2,  // strong threshold
    0.01, // weak threshold
);
// 2) Pass DynamicImage directly:
let source_image = image::open("testdata/line-simple.png")
    .expect("failed to read image");

let detection = edge_detection::canny(
    source_image,
    1.2,  // sigma
    0.2,  // strong threshold
    0.01, // weak threshold
);

Hadi added 3 commits July 15, 2025 03:20
Indicate that `canny` works with a `DynamicImage` directly or with an explicit
`.to_luma8()` call, so converting to gray up front is no longer required.
Removed the unnecessary `.to_luma()` conversion in the example code for loading an image, clarifying usage for users.
@polyfloyd
Copy link
Owner

Thanks!

@polyfloyd
Copy link
Owner

Merged by hand

@polyfloyd polyfloyd closed this Jul 15, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants