Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot save 16-bit images directly to PNM via save #2430

Open
Enet4 opened this issue Feb 26, 2025 · 1 comment · May be fixed by #2431
Open

Cannot save 16-bit images directly to PNM via save #2430

Enet4 opened this issue Feb 26, 2025 · 1 comment · May be fixed by #2431

Comments

@Enet4
Copy link

Enet4 commented Feb 26, 2025

This problem happens when trying to save a DynamicImage of color type L16 or Rgb16 to any PNM format (.pbm, .pgm, ppm) via its save method.

This is somewhat related with #1687, but it isn't the same because this problem also happens to grayscale images.

Expected

The encoder should be able to recognize that the data coming from the DynamicImage object contains wide samples (2 bytes per sample), and write the image with that in mind. Other encoders such as the PNG encoder can handle this well.

Actual behaviour

The PNM encoder API is funneled to the method write_image, which only accepts a &[u8] as the image buffer, and subsequently interprets the data as flat samples of u8, regardless of the color type in the original dynamic image object. As a consequence, the header dimension check fails with the error DimensionMismatch ("The Image's dimensions are either too small or too large") for finding twice the amount of expected samples.

Reproduction steps

fn main() {
    let input = std::env::args().nth(1).unwrap();
    let output = input.clone() + ".pgm";

    let img = image::open(input).expect("failed to open");
    img.save(&output).expect("failed to save");
}
❯ file basi0g16.png
basi0g16.png: PNG image data, 32 x 32, 16-bit grayscale, interlaced

❯ cargo run -- basi0g16.png 
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.23s
     Running `target\debug\to-pnm.exe basi0g16.png`

thread 'main' panicked at src\main.rs:6:23:
failed to save: Parameter(ParameterError { kind: DimensionMismatch, underlying: None })
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: process didn't exit successfully: `target\debug\to-pnm.exe basi0g16.png` (exit code: 101)

Any 16-bit grayscale image should work. Here is one from the pngsuite project.

@Enet4 Enet4 changed the title Cannot save 16-bit images directly to PNM Cannot save 16-bit images directly to PNM via save Feb 26, 2025
@fintelia
Copy link
Contributor

The write_image method also takes a ColorType value that indicates the meaning of the samples. The problem is that the buffer length is checked before confirming that the specified color type is supported.

Separately, the encoder could be improved to also support storing 16-bit images.

@Enet4 Enet4 linked a pull request Feb 27, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants