Enet4 / dicom-rs

Rust implementation of the DICOM standard
https://dicom-rs.github.io
Apache License 2.0
403 stars 75 forks source link

to_dynamic_image method not found in `DecodedPixelData<'_>` #465

Closed codinkai closed 3 months ago

codinkai commented 3 months ago

Hi,

i am trying to run the example from https://docs.rs/dicom-pixeldata/latest/dicom_pixeldata/index.html

This is the code I run:

fn main() -> Result<(), Box<dyn std::error::Error>> {
    use dicom::object::open_file;
    use std::env;

    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        return Err("Usage: program_name <DICOM file path>".into());
    }
    let file_path = &args[1];

    let obj = open_file(file_path)?;

    use dicom_pixeldata::PixelDecoder;
    let image = obj.decode_pixel_data()?;
    let dynamic_image = image.to_dynamic_image(0)?;
    dynamic_image.save("out.png")?;

    Ok(())
}

When I run cargo build, I get the following error:

error[E0599]: no method named `to_dynamic_image` found for struct `DecodedPixelData` in the current scope
  --> src/main.rs:15:31
   |
15 |     let dynamic_image = image.to_dynamic_image(0)?;
   |                               ^^^^^^^^^^^^^^^^ method not found in `DecodedPixelData<'_>`

For more information about this error, try `rustc --explain E0599`.
error: could not compile `hello_cargo` (bin "hello_cargo") due to 1 previous error

What am I doing wrong?

codinkai commented 3 months ago

I get this error for the second example:

error[E0599]: no method named `to_ndarray` found for struct `DecodedPixelData` in the current scope
  --> src/main.rs:17:30
   |
17 |     let ndarray = pixel_data.to_ndarray::<u16>()?;
   |                              ^^^^^^^^^^ method not found in `DecodedPixelData<'_>`

For more information about this error, try `rustc --explain E0599`.
error: could not compile `hello_cargo` (bin "hello_cargo") due to 1 previous error

These are my dependencies in Cargo.toml:

[dependencies]
dicom = "0.6.3"
dicom-object = "0.6.3"
dicom-pixeldata = "0.2.2"
ndarray = "0.15.6"
Enet4 commented 3 months ago

I suspect that there is some trait version mismatch. Can you try importing open_file like this instead?

use dicom_object::open_file;
codinkai commented 3 months ago

Thank you for your quick response. Unfortunately, this did not solve the problem.

I have changed the code to:

fn main() -> Result<(), Box<dyn std::error::Error>> {
    //use dicom::object::open_file;
    use dicom_object::open_file;
    use std::env;

    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        return Err("Usage: program_name <DICOM file path>".into());
    }
    let file_path = &args[1];

    let obj = open_file(file_path)?;

    use dicom_pixeldata::PixelDecoder;
    let image = obj.decode_pixel_data()?;
    let dynamic_image = image.to_dynamic_image(0)?;
    dynamic_image.save("out.png")?;

    Ok(())
}

with this Cargo.toml

[dependencies]
dicom = "0.6.3"
dicom-object = "0.6.3"
dicom-pixeldata = "0.2.2"

cargo run results in the same error. I have also tried to run cargo clean before compiling the code.

My OS information are:

System Version: macOS 14.4
Kernel Version: Darwin 23.4.0
Enet4 commented 3 months ago

If anything, there may be something going on at the Cargo.lock. Here are a few more steps to try and resolve the situation:

  1. Run cargo tree -d to see if there are duplicate dependencies. Run cargo update and inspect the dependency tree again.
  2. If after this it still won't compile, then I would recommend removing the parent dicom crate and picking the specific crates that you need. This is the rule of thumb that I personally follow: when picking specific dicom-* crates, remove the parent crate.
codinkai commented 3 months ago

I have solved the issue. The method "to_dynamic_image" is part of the image feature of pixeldata, which seems to be not enabled by default.

It works with this dependencies:

[dependencies]
dicom-object = "0.6.3"
dicom-pixeldata = { version = "0.2.2", features = ["image"] }

I have also tried it with the dependencies dicom = "0.6.3" with use dicom::object::open_file;and use dicom::pixeldata::PixelDecoder;. I assume that the feature "image" is not activated in there.

Enet4 commented 3 months ago

Oh yes, I must have overlooked that detail in your Cargo.toml. Converting to an image object requires the image feature, since that brings an extra set of dependencies. This is mentioned in the root crate documentation.

I'm afraid that this is by design, so there isn't much one can do here, other than improve the way that documentation is generated to clarify the features required for those methods to exist.

codinkai commented 3 months ago

No worries. Thank you for your support.

How can I enable the feature in the root crate?

I have tried this, but it does not work.

[dependencies]
dicom = { version = "0.6.3", features = ["image"] }
Enet4 commented 3 months ago

For that to work, dicom itself needs to re-export the Cargo feature into its own feature table. While this parent crate was designed to facilitate simple use cases, it is true that it has some shortcomings such as this one.

If anything, one can add more Cargo features to dicom. I agree that adding image and ndarray could be useful.

codinkai commented 3 months ago

Thank you for your support. It is a great library anyway. I will close this ticket now.

Enet4 commented 3 months ago

Your feedback is appreciated! I have provided said re-exports in #469, to be delivered in the next version.