image-rs / image

Encoding and decoding images in Rust
Apache License 2.0
4.9k stars 606 forks source link

PBM encoder is incorrect for ASCII, aka PnmSubtype::Bitmap(SampleEncoding::Ascii) #2242

Open timboldt opened 4 months ago

timboldt commented 4 months ago

Encoding a PNM bitmap as binary (type P4) works correctly, but encoding it as ASCII (type P1) results in the wrong sample format.

Specification: https://netpbm.sourceforge.net/doc/pbm.html

Expected

I expected a file with samples of 1s and 0s.

P1
24 7
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 0 0 1 1 1 1 0 0 1 1 1 1 0 0 1 1 1 1 0
etc.

NOTE: The spaces are optional.

Actual behaviour

I got samples with values between 0 and 255, i.e. the bits were combined into bytes and then written out as byte values in decimal.

P1
24 7
0 0 0
121  231 158
etc.

Reproduction steps

let f = File::create("pic.pbm")?;
let mut writer = BufWriter::new(f);
let encoder =
    PnmEncoder::new(&mut writer).with_subtype(PnmSubtype::Bitmap(SampleEncoding::Ascii));
imgbuf.write_with_encoder(encoder)?;

P.S. If you can point me in the right direction, I'm happy to send a PR to address this.

fintelia commented 4 months ago

The relevant code is in https://github.com/image-rs/image/blob/main/src/codecs/pnm/encoder.rs

The easiest thing might be to either step through it with a debugger or add some println! calls to see which code path is being taken