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

Broken APNG is produced with StreamWriter #411

Open
tirr-c opened this issue Sep 3, 2023 · 2 comments
Open

Broken APNG is produced with StreamWriter #411

tirr-c opened this issue Sep 3, 2023 · 2 comments
Labels
Milestone

Comments

@tirr-c
Copy link

tirr-c commented Sep 3, 2023

This code produces broken APNG without any errors:

fn main() {
    use std::io::Write;

    let file = std::io::BufWriter::new(std::fs::File::create("out.png").unwrap());
    let mut encoder = png::Encoder::new(file, 8, 8);

    // 8-bit grayscale, 2 frames
    encoder.set_color(png::ColorType::Grayscale);
    encoder.set_depth(png::BitDepth::Eight);
    encoder.set_animated(2, 0).unwrap();
    encoder.validate_sequence(true);

    let writer = encoder.write_header().unwrap();
    let mut stream_writer = writer.into_stream_writer().unwrap();

    // Frame 0
    stream_writer.set_frame_delay(1, 1).unwrap();
    stream_writer.write_all(&[0u8; 64]).unwrap();

    // Frame 1
    stream_writer.set_frame_delay(1, 2).unwrap();
    stream_writer.write_all(&[0xffu8; 64]).unwrap();

    stream_writer.finish().unwrap();
}
$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/png-animation-test`
$ magick identify -verbose out.png
identify: IDAT: unknown compression method `out.png' @ error/png.c/MagickPNGErrorHandler/1492.
$ ffprobe out.png
ffprobe version n6.0 Copyright (c) 2007-2023 the FFmpeg developers
(... snip ...)
[apng @ 0x560b1cafb580] inflate returned error -3
Input #0, apng, from 'out.png':
  Duration: N/A, bitrate: N/A
  Stream #0:0: Video: apng, gray(pc), 8x8, 100k tbr, 100k tbn
@fintelia fintelia added the hard label Sep 3, 2023
@fintelia
Copy link
Contributor

fintelia commented Sep 4, 2023

Thanks for reporting this!

The good news is that I was able to reproduce the issue. The bad news is that I'm not sure streaming encoding of APNGs ever worked, and even after a whole bunch of digging through the code I'm really not sure where to start on figuring out what's going on. At various times it seems to write corrupt deflate streams, incorrect sequence numbers, too many fcTL chunks, and occasionally mixes up whether a frame should be encoded with IDAT or fdAT chunks. There's probably a lesson to be learned here about accepting large PRs without any tests...

At this point I'm not quite sure what to do. The fact that this wasn't noticed until years after the feature was added suggests that it isn't a particularly important feature, which makes it hard for me to justify spending the considerable amount of additional time on it that I suspect would be needed to get things into a reasonable state. Stripping out streaming APNG encoding isn't especially appealing, but may end up being the least bad option 😞

@tirr-c
Copy link
Author

tirr-c commented Sep 4, 2023

Oh, that's unfortunate... Maybe I'll write a fallback routine to buffered write when I need to write multiple frames. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants