mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-08 08:10:30 -10:00
rpng: encode screenshots at deflate level 6, not 9
Both deflate backends default to level 9 and rpng_save_image_stream never
overrode it, so every screenshot was written at maximum compression.
That is the wrong trade for something the user waits on, and on the
content emulator screenshots actually contain the top levels return
almost nothing.
Measured with the BGR24 entry point task_screenshot uses, libpng 1.6.43
at its own default alongside for scale (time / file size):
libpng level 6 level 9
2D pixel art 59 ms/0.23 67 ms/0.23 591 ms/0.23
2D pixel art 4K 242 ms/0.88 272 ms/0.88 2221 ms/0.86
smooth ramp 460 ms/1.00 432 ms/1.00 2649 ms/0.92
3D scene 707 ms/2.82 458 ms/3.13 448 ms/3.13
3D scene 4K 2929 ms/11.26 1843 ms/12.49 1830 ms/12.49
menu frame 48 ms/0.01 56 ms/0.01 70 ms/0.01
Level 9's deep chain search collapses on repetitive input - flat runs,
upscaled pixel art, smooth ramps - which is most of what gets captured.
A 4K pixel-art screenshot took 2.2 seconds to write and came out 2%
smaller than a 272 ms one. Where the extra effort does earn its keep, on
noisy 3D output, level 6 matches level 9 byte for byte. The worst size
regression across the set is 80 KB, against 2.2 seconds.
The in-house backend behaves the same way, so HAVE_ZLIB=0 builds get the
same win (pixel art 666 -> 65 ms, ramp 2606 -> 423 ms, 3D unchanged).
6 is zlib's and libpng's own default, so a RetroArch screenshot is no
longer both larger and slower than what every other PNG writer produces.
This only sets the level; filter selection, which is why the 3D rows are
11% larger than libpng's, is untouched and is the next thing to look at.
Validation: 24 round-trips - four content shapes (pixel art, ramp, flat,
noise) at 1920x1080, 640x480 and 37x17, through both public entry points
- each re-decoded with libpng and with rpng and compared against the
source pixels. All exact, for HAVE_ZLIB=1 and HAVE_ZLIB=0, under
-fsanitize=address,undefined. C89 verified on x86-64 and aarch64.
This commit is contained in:
1 parent
07256dae8c
commit
13e0986c67
1 file changed
+25
@@ -393,6 +393,31 @@ bool rpng_save_image_stream(const uint8_t *data, intfstream_t* intf_s,
|
||||
GOTO_END_ERROR();
|
||||
|
||||
stream = stream_backend->stream_new();
|
||||
|
||||
/* Both deflate backends default to level 9, which is the wrong
|
||||
* trade for a screenshot: it is a foreground action the user waits
|
||||
* on, and on the content emulator screenshots actually contain the
|
||||
* top levels buy nothing. Measured at 1920x1080 and 3840x2160,
|
||||
* BGR24, against libpng at its own default for scale:
|
||||
*
|
||||
* libpng level 6 level 9
|
||||
* 2D pixel art 59 ms/0.23 67 ms/0.23 591 ms/0.23
|
||||
* pixel art 4K 242 ms/0.88 272 ms/0.88 2221 ms/0.86
|
||||
* smooth ramp 460 ms/1.00 432 ms/1.00 2649 ms/0.92
|
||||
* 3D scene 707 ms/2.82 458 ms/3.13 448 ms/3.13
|
||||
* 3D scene 4K 2929 ms/11.26 1843 ms/12.49 1830 ms/12.49
|
||||
* menu frame 48 ms/0.01 56 ms/0.01 70 ms/0.01
|
||||
*
|
||||
* Level 9's deep chain search collapses on the repetitive content -
|
||||
* flat runs, upscaled pixel art, smooth ramps - which is most of
|
||||
* what gets captured, and returns 0-8% for 6-9x the time. Where it
|
||||
* does earn its keep, on noisy 3D output, level 6 matches it
|
||||
* exactly. Worst case here is 80 KB against 2.2 seconds.
|
||||
*
|
||||
* 6 is also zlib's and libpng's own default, so a screenshot is no
|
||||
* longer larger or slower than what every other PNG writer emits. */
|
||||
if (stream)
|
||||
stream_backend->define(stream, "level", 6);
|
||||
if (!stream)
|
||||
GOTO_END_ERROR();
|
||||
|
||||
|
||||
Reference in new issue
Block a user