serenity/Userland
Nico Weber cae672e1f9 LibGfx/WebPWriter: Implement color indexing transform
If an image has 256 or fewer colors, WebP/Lossless allows storing
the colors in a helper image, and then storing just indexes into that
helper image in the main image's green channel, while setting
r, b, and a of the main image to 0.

Since constant-color channels need to space to store in WebP,
this reduces storage needed to 1/4th (if alpha is used) or 1/3rd
(if alpha is constant across the image).

If an image has <= 16 colors, WebP lossless files pack multiple
color table indexes into a single pixel's green channel, further
reducing file size. This pixel packing is not yet implemented in
this commit.

GIFs can store at most 256 colors per frame, so animated gifs
often have 256 or fewer colors, making this effective when
transcoding gifs.

(WebP also has a "subtract green" transform, which can be used
to need to store just a single channel for grayscale images, without
having to store a color table. That's not yet implemented -- for now,
we'll now store grayscale images using this color indexing transform
instead, which wastes to storage for the color table.)

(If an image has <= 256 colors but all these colors use only a single
channel, then storing a color table for these colors is also wasteful,
at least if the image has > 16 colors too. That's rare in practice,
but maybe we can add code for it later on.)

(WebP also has a "color cache" feature where the last few used colors
can be referenced using very few bits. This is what the webp spec says
is similar to palettes as well. We don't implement color cache writing
support yet either; maybe it's better than using a color indexing
transform for some inputs.)

Some numbers on my test files:

sunset-retro.png: No performance or binary size impact. The input
quickly uses more than 256 colors.

giphy.gif (184k): 4.1M -> 3.9M, 95.5 ms ± 4.9 ms -> 106.4 ms ± 5.3 ms
Most frames use more than 256 colors, but just barely. So fairly
expensive runtime wise, with just a small win.

(See comment on #24454 for the previous 4.9 MiB -> 4.1 MiB drop.)

7z7c.gif (11K): 118K -> 40K
Every frame has less than 256 colors (but more than 16, so no packing),
and so we can cut filesize roughly to 1/3rd: We only need to store an
index per channel. From 10.7x as large as the input to 3.6x as large.
2024-05-31 22:39:25 +02:00
..
Applets Keymap: Draw the current keymap text with the correct theme color 2024-03-02 19:24:53 +00:00
Applications LibJS: Remove two unused members from ExecutionContext 2024-05-31 16:31:33 +02:00
BuggieBox Meta+Userland: Make LibELF a proper library on Serenity 2024-04-26 19:08:13 -06:00
Demos Demos: Add sleep option to CatDog 2024-05-14 15:45:33 -06:00
DevTools AK+Userland: Remove NOESCAPE 2024-05-22 21:55:34 -06:00
DynamicLoader DynamicLoader: Add an option to list all ELF loaded dependencies 2024-05-14 15:42:42 -06:00
Games Chess: Add display widget for moves 2024-05-22 23:24:45 -06:00
Libraries LibGfx/WebPWriter: Implement color indexing transform 2024-05-31 22:39:25 +02:00
Services LibWeb+LibWebView+WebContent: Add basic find in page functionality 2024-05-30 16:30:11 +02:00
Shell Everywhere: Remove uneeded short option argument where possible 2024-04-22 08:10:08 +02:00
Utilities Utilities: Add shred utility 2024-05-31 13:49:34 +01:00
CMakeLists.txt