woelper / oculante

A fast and simple image viewer / editor for many operating systems
https://github.com/woelper/oculante
MIT License
940 stars 43 forks source link

Request: support Animated PNG (APNG) #305

Open bean-z opened 6 months ago

bean-z commented 6 months ago

Is your feature request related to a problem? Please describe. Animated PNG (APNG) is an extension of PNG and uses the same file extension (.png) and MIME type (image/png). An example APNG is a bouncing ball animation by Holger Will. The zune-png crate that Oculante uses doesn't support APNG.

Describe the solution you'd like I would like to open APNG files as if they were GIF files. The png crate ((docs and crate page) seems to be about as fast as zune-png now.

woelper commented 6 months ago

Thanks! Great idea! Do you happen to know what is required to know if a PNG is animated? The extension is the same as PNG, so I guess some pre-check for animation would need to be done.

bean-z commented 6 months ago

The way that the png docs demonstrate is creating a Decoder, calling the read_info() method (which returns a Reader), and passing a mutable reference to a vec! buffer into the Reader's next_frame() method. I think it works like this: If there is only one frame (i.e. not APNG) then the first next_frame() call will return something that matches Ok(variable_to_bind_info) (and will fill the buffer with the first frame's bytes) and a second call will return something that matches Err(Format(FormatError)) (where Format(FormatError) is a variant of the enum DecodingError).

Internally, the .png file should contain the acTL chunk (whose header contains the four hex bytes 61 63 54 4c i.e. "acTL") prior to the IDAT chunk (whose header contains the four bytes 49 44 41 54 i.e. "IDAT").

woelper commented 6 months ago

Thanks!

It seems that zune_png supports apng, it just needs manual handling. I have made a branch that successfully decodes the sample animation you linked (thank you for such a well-written feature request by the way!). I'll test this a bit more and release.

woelper commented 6 months ago

I've found one animation that looks like the offset is incorrectly calculated here: http://littlesvr.ca/apng/images/clock.png I am using https://docs.rs/zune-png/latest/zune_png/fn.post_process_image.html to do post processing, so the bug is likely there, or in the image itself. All other examples decoded correctly as far as I could see.

woelper commented 6 months ago

I've released v0.8.18 with APNG support now. Please let me know if this works as expected. Thank you again for this request.

bean-z commented 6 months ago

The bouncing ball animation has minor visual artifacts at the top and bottom edges of the ball when displayed in Oculante version 0.8.18. Here's a recording of Oculante on the left and Brave (a Chromium-based browser) on the right:

https://github.com/woelper/oculante/assets/143631489/425fb96b-4fcc-4eaf-9d6f-85938ed429dd

From what I can tell, Oculante correctly displays this brain scan animation and this elephant animation.

woelper commented 6 months ago

Well spotted!

This seems like to be an issue in zune_png. I've made a minimal example based on their example to decode an animation here:

https://github.com/woelper/apng_test

I think it looks like I need to open an issue in their repo. I could try using the png crate, but I'd love to not mix multiple libraries if possible.

woelper commented 6 months ago

I have added an issue here:

https://github.com/etemesi254/zune-image/issues/185

woelper commented 4 months ago

I've merged the latest rc from zune-png and all examples look correct now.

bean-z commented 4 months ago

Version 0.8.22 can open the clock and the MRI scan images, but I get a crash if I try to open the bouncing ball or the elephant.

I got a log in my terminal by running /Applications/oculante.app/Contents/MacOS/oculante with the environment variable RUST_BACKTRACE=1. First I dragged the MRI scan image into the app. Then I dragged in the bouncing ball.

[2024-05-20T02:04:53Z INFO  oculante::image_loader] Image is animated
[2024-05-20T02:05:04Z INFO  oculante::image_loader] Image is animated
thread '<unnamed>' panicked at /Users/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/zune-png-0.5.0-rc1/src/apng.rs:269:28:
range end index 400 out of range for slice of length 100
stack backtrace:
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Richardn2002 commented 3 months ago

Same here

thread '<unnamed>' panicked at /build/.cargo/registry/src/index.crates.io-6f17d22bba15001f/zune-png-0.5.0-rc1/src/apng.rs:269:28:
range end index 4400 out of range for slice of length 1000

File in question attached. Richardn

woelper commented 3 months ago

I've opened an issue here: https://github.com/etemesi254/zune-image/issues/210