Description
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.