Add APNG R/W Support via libpng#4944
Conversation
|
Btw. I also opened a PR for spng (which libvips also supports) to add APNG R/W support at randy408/libspng#283, but it looks like the library is unmaintained since 2023. |
|
This is great @felixbuenemann! Yes, libspng seems to have gone, sadly, so libpng only is fine. I'm trapped in a horrible deadline right now (I must submit a paper in a month presenting work I've still not finished), but after that, and a beer, I'll be back on libvips. |
|
@jcupitt That's fine. Do you prefer if I split the quantiser into a separate PR? |
|
I'm ok with one PR, but maybe someone else will review. I'll defer to them. |
|
Getting rid of a dependency sounds great, especially if we save time and memory. There's an issue somewhere asking for a "find $N most significant colours" operation, which is difficult with libimagequant because of the API. If we had our own cluster finder we could (probably?) add stuff like this relatively easily. |
That shouldn't be too hard to do, but currently the built-in quantizer is only used as a fallback, when neither quantizr nor libimagequant are found. I also have another optimization in the pipeline, that remaps pixels with a fully transparent alpha, but different rgb values to a single 0,0,0,0 alpha palette entry to ensure remaining palette entries are not wasted. I just haven;t come around to generating good test images to exercise the code. |
07922c0 to
a3801a9
Compare
|
I pushed the optimisation that replaces all fully transparent pixels with a single |
|
I also discovered #4971 while working on this. |
|
I fixed the fuzzer errors by checking sub-frame dimensions and frame counts before allocating. |
|
@jcupitt you said:
We can get just the palette with all three quantizers (built-in, libimagequant, quantizr) and return it as RGBA strip or what was the intended API? |
bdb8cae to
3cfc5b9
Compare
|
I amended the quantizer commit, because cgif was disabled with the built-in quantizer and also added an error handling bugfix for the quantizr lib in a separate commit. |
3cfc5b9 to
cfa3009
Compare
Add animated PNG (APNG) support to the libpng backend, gated behind PNG_APNG_SUPPORTED (libpng 1.6+APNG patch or libpng 1.8+). Load: - Extend Read struct with APNG fields (page/n, canvas, dispose state) - Add page/n parameters to pngload (matching GIF/WebP loaders) - Detect acTL chunk and set animation metadata (n-pages, page-height, delay, loop) - Scan raw PNG chunks via vips_source_map to extract fcTL delays at header time, matching how GIF/WebP loaders handle delay metadata - Frame compositing with DISPOSE_OP_NONE/BACKGROUND/PREVIOUS and BLEND_OP_SOURCE/OVER for both 8-bit and 16-bit - Sequential generate callback for frame-by-frame reading - Compat defines for constant naming differences between libpng 1.6 APNG patch (PNG_DISPOSE_OP_NONE) and 1.8+ (PNG_fcTL_DISPOSE_OP_NONE) - Non-animated PNG fallthrough avoids duplicate png_read_update_info call (rejected by libpng 1.8) Save: - Detect animation via page-height metadata - Write APNG with acTL/fcTL/fdAT chunks via sink_disc callback - Disable interlace for animated output with warning - Palette mode support via quantisation Tests: - Add cogs-apng.png test image (indexed APNG converted from cogs.gif) - Add hand-crafted APNG test images for compositing: dispose-background, dispose-previous, and alpha blend-over - Add test_apng_load: metadata, page handling, single/multi-frame - Add test_apng_dispose_background: verify BACKGROUND dispose clears canvas to transparent - Add test_apng_dispose_previous: verify PREVIOUS dispose restores canvas, including spec rule that PREVIOUS on frame 0 = BACKGROUND - Add test_apng_blend_over: verify alpha-over compositing of semi-transparent frames - Add test_apng_save: lossless round-trip, palette round-trip, GIF to APNG conversion - Add have_apng() / skip_if_no_apng for builds without APNG support
cfa3009 to
95b6039
Compare
Summary
Add APNG (animated PNG) load/save support via libpng.
Adds animated PNG to the existing libpng backend, gated behind
PNG_APNG_SUPPORTED(libpng 1.6+APNG patch or libpng 1.8+). The loader supportspage/nparameters matching the GIF/WebP loaders, full frame compositing (all dispose and blend ops, 8-bit and 16-bit), and sequential access. The saver writes APNG viasink_discwith palette mode support. Non-animated PNGs are unaffected — the only overhead is anacTLchunk check.