Commit graph

761 commits

Author SHA1 Message Date
0x4261756D
6923008a55 JPEGLoader: Fix infinite loop on incomplete data
If the image data to decode is incomplete, e.g. a corrupt image missing
its last scanlines the decoder would previously keep looping for ever.
By breaking out of the loop if no more scanlines were produced we can at
least display the partial image up to that point.
2024-10-12 19:21:03 +02:00
Andreas Kling
cc4b3cbacc Meta: Update my e-mail address everywhere 2024-10-04 13:19:50 +02:00
Jelle Raaijmakers
768d814ffd LibGfx: Set correct alpha type for webp decoding
The libwebp decoder gives us unpremultiplied color data, so mark our
bitmaps as such.
2024-10-02 16:37:22 +01:00
Aliaksandr Kalenik
a499ece16c LibGfx+LibWeb: Replace usages of Bitmap::fill() with Gfx::Painter
Let's always mutate a bitmap using painter, because Skia likely could
do it faster than our own implementation.
2024-09-19 06:21:33 +02:00
Andreas Kling
c8f09312f7 LibGfx: Rename Path => DeprecatedPath 2024-08-20 09:30:05 +02:00
Andreas Kling
0c7670b226 LibGfx: Rename Painter => DeprecatedPainter 2024-08-20 09:30:05 +02:00
Khaled Lakehal
2d6069650a LibGfx: Enhance APNG format support
Improve handling of APNG chunks by avoiding premature termination when
encountering non-fcTL chunks. With this patch, the browser now passes
additional APNG-related tests in the "png/" Web Platform Tests (WPT)
suite.
2024-08-19 20:04:31 +02:00
Jelle Raaijmakers
a430ae6dcf LibGfx: Mark PNG bitmaps as having unpremultiplied alpha 2024-08-07 18:51:12 +02:00
Lucas CHOLLET
aba435a652 LibGfx/JPEGXL: Add support for animated images 2024-07-23 08:59:34 +02:00
Lucas CHOLLET
d9a2c62ed4 LibGfx/JPEGXL: Make JPEGXLLoadingContext non [copy,move]able 2024-07-23 08:59:34 +02:00
Lucas CHOLLET
1039561280 LibGfx: Use libjxl to decode JPEG XL images
It currently doesn't support animated image.

Note that Gfx::Bitmap has no support for get_pixel when the format is
RGBA8888. This is why it has been removed from the tests.
2024-07-22 09:15:16 +02:00
Daniel Bertalan
7fe82a1cda CMake: Add back stricter warnings used in Serenity builds
These used to be enabled in `serenity_compile_options.cmake` for
Serenity builds and were removed in 9b05fb98. This is a slightly more
conservative subset of those, with ones that are enabled by default
omitted.

This should prevent our code quality regressing in the long run.
2024-07-17 21:51:29 +02:00
doctortheemh
0140e5e9cc LibGfx: Decode WebP images with libwebp 2024-07-17 10:04:25 -06:00
doctortheemh
4ef76f3198 LibGfx: Decode AVIF images
Use libavif to decode AVIF images in LibGfx.
2024-07-09 08:15:47 +02:00
Andreas Kling
8a3dc5ea0a LibGfx: Remove home-grown PNG codec in favor of libpng+apng 2024-06-21 07:31:37 +02:00
Andreas Kling
1039acca8c LibGfx: Remove JPEG2000 image format support
This format is not supported by other browsers.
2024-06-17 21:57:35 +02:00
Andreas Kling
a34a5af939 LibGfx: Remove ILBM image format support
This format is not supported by other browsers.
2024-06-17 21:57:35 +02:00
Andreas Kling
b6daddb088 LibGfx: Remove JBIG2 image format support
This format is not supported by other browsers.
2024-06-17 21:57:35 +02:00
Andreas Kling
b7f8d7aec5 LibGfx: Remove TGA image format support
This format is not supported by other browsers.
2024-06-17 21:57:35 +02:00
Andreas Kling
681a2ac14e LibGfx: Remove support for the various "portable" image formats
These formats are not supported by other browsers.
2024-06-17 21:57:35 +02:00
Andreas Kling
7141319a7c LibGfx: Remove DDS image format support
This format is not supported by other browsers.
2024-06-17 21:57:35 +02:00
Andreas Kling
4b4254c3d0 LibGfx: Remove QOI image format support
This format is not supported by other browsers.
2024-06-17 21:57:35 +02:00
Andreas Kling
2a888ca626 LibGfx: Remove home-grown JPEG codec in favor of libjpeg-turbo 2024-06-17 17:59:54 +02:00
Daniel Bertalan
bf1f631f25 Everywhere: Write dtors for types with incomplete members out-of-line
These are rejected by Clang (19) trunk as a result of
https://github.com/llvm/llvm-project/pull/77753.
2024-06-16 07:19:56 -04:00
Andreas Kling
57906a4e1b LibGfx: Move Gfx::Painter::WindingRule => Gfx::WindingRule 2024-06-05 15:37:05 +02:00
Andreas Kling
6a96920dbc LibGfx: Remove Bitmap and Painter "scale" concept
We don't need intrinsic scale factors for Gfx::Bitmap in Ladybird,
as everything flows through the CSS / device pixel ratio mechanism.

This patch also removes various unused functions instead of adapting
them to the change.
2024-06-05 15:37:05 +02:00
Simon Wanner
6b2c459901 LibTextCodec: Fix ISO-8859-1 vs. windows-1252 handling in web contexts
The Encoding specification maps ISO-8859-1 to windows-1252 and expects
the windows-1252 translation table to be used, which differs from
ISO-8859-1 for 0x80-0x9F.

Other contexts expect to get the actual ISO-8859-1 encoding, with 1-to-1
mapping to U+0000-U+00FF, when requesting it.

`decoder_for_exact_name` is introduced, which skips the mapping from
aliases to the encoding name done by `get_standardized_encoding`.
2024-06-04 10:21:07 +02:00
Nico Weber
4e9480b719 LibGfx/WebP: Add a VERIFY() for an assumption
This should have no behavior change after the previous commit.
2024-06-03 07:48:53 +02:00
Nico Weber
857750dfed LibGfx/WebPLoader: Survive calling loop_count() before other accessors
Fixes `animation` asserting when reading a webp input.

(The other order of operations is still covered by TestImageWriter.cpp.)
2024-06-03 07:48:53 +02:00
Nico Weber
347e2831b2 LibGfx/WebPWriter: Do not write color index if only one channel varies
The benefit of the color indexing transform is to have only one
varying channel after it (the green channel, which after the
transform serves as index into the color table).

If there is only one varying channel before the transform, it's
not beneficial. (...except if there are <= 16 colors, then the
pixel bundling presumably still works.)
2024-06-01 14:52:00 +02:00
Nico Weber
533b29dde7 LibGfx/WebPWriter: Add a toggle for disabling individual transforms 2024-05-31 22:39:25 +02:00
Nico Weber
47d3245ea7 LibGfx/WebPWriter: Do not convert -inf to unsigned
Else UBSan complains about the color indexing test in this PR.
2024-05-31 22:39:25 +02:00
Nico Weber
9e61912f64 LibGfx/WebPWriter: Fix bug computing max_symbol bit length
Storing a number n needs floor(log2(n) + 1) bits, not ceil(log2(n)).
(The two expressions are identical except for when n is a power of 2.)

Serendipitously covered by the indexed color transform tests in this PR.
2024-05-31 22:39:25 +02:00
Nico Weber
5c990e87f4 LibGfx/WebPWriter: Add a dbgln_if() 2024-05-31 22:39:25 +02:00
Nico Weber
e212c20228 LibGfx/WebPWriter: Implement pixel bundling for color indexing
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 adds support for that.

My current test files all have more than 16 colors. For a 16x16
black-and-white bitmap that contains a little smiley face in the
middle, this reduces the output size from 128B to 54B.
2024-05-31 22:39:25 +02:00
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
Nico Weber
633f509eb4 LibGfx/WebP: Move TransformType to WebPSharedLossless.h 2024-05-31 22:39:25 +02:00
Nico Weber
804e85265e LibGfx/WebPWriter: Use an IsOpaque struct for tracking opacity
No behavior change, but this makes it easy to correctly set this
flag when adding an indexing transform: Opacity then needs to be
determined based on if colors in the color table have opacity,
not if the indexes into the color table do.

With this struct, only the first time something sets opacity is
honored, giving us those semantics.
2024-05-31 22:39:25 +02:00
Nico Weber
c5dedbc54a LibGfx/WebPWriter: Give write_VP8L_coded_image() a kind parameter
This way, it can be used to write entropy-coded-images too,
which will be used when writing transforms.
2024-05-31 22:39:25 +02:00
Nico Weber
b50702f490 LibGfx/WebP: Move ImageKind to WebPSharedLossless.h 2024-05-31 22:39:25 +02:00
Nico Weber
9dfb254c73 LibGfx/WebPWriter: Extract write_VP8L_coded_image() 2024-05-31 22:39:25 +02:00
Nico Weber
d9aa594e86 LibGfx/WebPWriter: Add comment for image-stream production 2024-05-31 22:39:25 +02:00
Nico Weber
286cc6f905 LibGfx/WebPLoader: Prefix a few dbgln_if()s with chunk name 2024-05-31 22:39:25 +02:00
Nico Weber
a2ddf054f2 LibGfx/WebPWriter: Remove two obsolete comments
In an early version of the huffman writing code, we always used 8 bits
here, and the comments still reflected that. Since we're now always
writing only as many bits as we need (in practice, still almost always
8), the comments are misleading.
2024-05-31 22:39:25 +02:00
Nico Weber
0ae36b9524 LibGfx/WebPWriter: Write correct alpha use hint in animation VP8L header
Since we now compute this for free, might as well fill it in.

As far as I can tell, no observable behavior difference anywhere.
2024-05-29 07:10:00 +01:00
Nico Weber
2d80a5c6ca LibGfx/WebPWriter: Let compress_VP8L_image*() return if image was opaque
We compute that as part of compression there anyways, so let's compute
it only once.

No behavior change.
2024-05-29 07:10:00 +01:00
Nico Weber
99d280a927 LibGfx/WebPLoader: Relax vp8x / vp8l alpha check
The check from 0805319d1e is too strict for animated images: It's
possible that an animation has alpha, but a frame doesn't.

(For example, if the animation is 10x10 pixels, but one frame updates
just 1x1 pixels. But even a full-sized frame could just not have alpha.)

If the VP8X header claims that the animation has alpha, we could check
that at least one frame has alpha, but for now we just don't do any
checking for animated images.
2024-05-29 07:10:00 +01:00
Nico Weber
c71b9fe6f8 LibGfx/WebPWriter: Add a comment explaining a file offset 2024-05-29 07:10:00 +01:00
Nico Weber
1a9d8e8fbe LibCompress: When limiting huffman tree depth, sacrifice bottom of tree
Deflate and WebP can store at most 15 bits per symbol, meaning their
huffman trees can be at most 15 levels deep.

During construction, when we hit this level, we used to try again
with an ever lower frequency cap per symbol. This had the effect
of giving the symbols with the highest frequency lower frequencies
first, causing the most-frequent symbols to be merged. For example,
maybe the most-frequent symbol had 1 bit, and the 2nd-frequent
two bits (and everything else at least 3). With the cap, the two
most frequent symbols might both have 2 symbols, freeing up bits
for the lower levels of the tree.

This has the effect of making the most-frequent symbols longer at
first, which isn't great for file size.

Instead of using a frequency cap, ignore ever more of the low
bits of the frequency. This sacrifices resolution where it hurts
the lower levels of the tree first, and those are stored less
frequently.

For deflate, the 64 kiB block size means this doesn't have a big
effect, but for WebP it can have a big effect:

sunset-retro.png (876K): 2.02M -> 1.73M -- now (very slightly) smaller
than twice the input size! Maybe we'll be competitive one day.

(For wow.webp and 7z7c.webp, it has no effect, since we don't hit
the "tree too deep" case there, since those have relatively few
colors.)

No behavior change other than smaller file size. (No performance
cost either, and it's less code too.)
2024-05-26 21:00:55 +02:00
Nico Weber
0711e9d749 LibGfx/WebPWriter: Use huffman compression
This implements some of basic webp compression: Huffman coding.
(The other parts of the basics are backreferences, and color cache
entries; and after that there are the four transforms -- predictor,
subtract green, color indexing, color.)

How much huffman coding helps depends on the input's entropy.
Constant-color channels are now encoded in constant space, but
otherwise a huffman code always needs at least one bit per symbol.
This means just huffman coding can at the very best reduce output
size to 1/8th of input size.

For three test input files:

sunset-retro.png (876K): 2.25M -> 2.02M
(helps fairly little; from 2.6x as big as the png input to 2.36x)

giphy.gif (184k): 11M -> 4.9M
(pretty decent, from 61x as big as the gif input to 27x as big)

7z7c.gif (11K): 775K -> 118K
(almost as good as possible an improvement for just huffman coding,
from 70x as big as the gif input to 10.7x as big)

No measurable encoding perf impact for encoding.

The code is pretty similar to Deflate.cpp in LibCompress, with just
enough differences that sharing code doesn't look like it's worth
it to me. I left comments outlining similarities.
2024-05-26 19:02:49 +02:00