Commit graph

150 commits

Author SHA1 Message Date
Nico Weber ba7d80fcde Tests: Move tga test images into tga/ subfolder 2023-06-19 06:42:00 -04:00
Nico Weber 5d0b170f72 Tests: Move jpg test images into jpg/ subfolder 2023-06-19 06:42:00 -04:00
Nico Weber c0fe9cee97 Tests: Move webp test images into webp/ subfolder 2023-06-19 06:42:00 -04:00
Nico Weber e19892a099 WebP/Lossless: Set alpha to 0xff if is_alpha_used is false in header
simple-vp8l-alpha-used-false.webp is a copy of simple-vp8l.webp,
with the byte at offset 0x18 changed from 0x10 to 0x00 -- that
is, the bit in the VP8L header that stores `is_alpha_used` is cleared.

We would already allocated a BGRx8888 instead of a BGRA8888 bitmap,
but keep actual alpha data in the `x` channel.

That lead to at least `image` still writing a PNG with an alpha channel.
So explicitly set the alpha channel to 0xff when is_alpha_used is false,
to make sure all consumers of decoded lossless webp data have behavior
consistent with other webp readers.

In practice, webp encoders usually don't write files that have
`is_alpha_used` set to false and then write actual alpha data to their
output. So this is rarely observable. However, for example for
lossy+ALPH webp files, the lossless webp used to store the ALPH channel
has `is_alpha_used` set to false and all channels but green are 0
(since the lossless green channel stores the alpha channel of a
lossy+ALPH webp). So if we dump such a bitmap to a standalone webp
file (e.g. with the temporary debugging code in fc3249a1ca),
then without this commit here, `image` would convert that webp to
a fully transparent webp, while other webp software would correctly
display the green image with opaque alpha.
2023-06-18 18:47:47 +02:00
Nico Weber 52d17afd7e WebP: Add test for vertical ALPH chunk filtering_method 2023-06-09 04:35:19 -07:00
Nico Weber b0916d2133 WebP: Add test for gradient ALPH chunk filtering_method 2023-06-09 04:35:19 -07:00
Nico Weber 816674de36 WebP: Add test for horizontal ALPH chunk filtering_method 2023-06-09 04:35:19 -07:00
Nico Weber 661b2d394d WebP/Lossy: Clamp negative quantization indices to zero
The spec doesn't talk about this happening in the text, but
`dequant_init()` in 20.4 stores `q` in an int and clamps that
to 0 later.
2023-06-01 17:36:20 +02:00
Nico Weber a2d8de180c WebP/Lossy: Add support for images with more than one partition
Each secondary partition has an independent BooleanDecoder.
Their bitstreams interleave per macroblock row, that is the first
macroblock row is read from the first decoder, the second from the
second, ..., until it wraps around again.

All partitions share a single prediction state though: The second
macroblock row (which reads coefficients off the second decoder) is
predicted using the result of decoding the frist macroblock row (which
reads coefficients off the first decoder).

So if I understand things right, in theory the coefficient reading could
be parallelized, but prediction can't be. (IDCT can also be
parallelized, but that's true with just a single partition too.)

I created the test image by running

    examples/cwebp -low_memory -partitions 3 -o foo.webp \
        ~/src/serenity/Tests/LibGfx/test-inputs/4.webp

using a cwebp hacked up as described in #19149. Since creating
multi-partition lossy webps requires hacking up `cwebp`, they're likely
very rare in practice. (But maybe other programs using the libwebp API
create them.)

Fixes #19149.

With this, webp lossy support is complete (*) :^)

And with that, webp support is complete: Lossless, lossy, lossy with
alpha, animated lossless, animated lossy, animated lossy with alpha all
work.

(*: Loop filtering isn't implemented yet, which has a minor visual
effect on the output. But it's only visible when carefully comparing
a webp decoded without loop filtering to the same decoded with it.
But it's technically a part of the spec that's still missing.

The upsampling of UV in the YUV->RGB code is also low-quality. This
produces somewhat visible banding in practice in some images (e.g.
in the fire breather's face in 5.webp), so we should probably improve
that at some point. Our JPG decoder has the same issue.)
2023-05-31 14:07:15 +02:00
Nico Weber d1d9d7a4f3 WebP/Lossy: Use correct test image for coefficient skipping
I somehow added the wrong image here. 4.webp is the one described
by the comment in the test. Now test actually uses the image it
claims to use.

No behavior change.
2023-05-30 18:56:03 +02:00
Nico Weber b7e31ba194 WebP/Lossy: Add test for lossy webp with uncompressed alpha
The alpha channel of a lossy webp is always stored separately from
the (lossy) RGB data. Alpha is either compressed in a lossless webp
that stores just the alpha data, or it's stored completely
uncompressed. (But again, even if it's compressed, it's losslessly
compressed.)

This adds a test for uncompressed alpha, which I hadn't tested before.
It seems to work correctly, though :^)

I generated the test image by running:

    ~/Downloads/libwebp-1.3.0-mac-arm64/bin/cwebp \
      -alpha_method 0 \
      Tests/LibGfx/test-inputs/extended-lossless.webp \
      -o Tests/LibGfx/test-inputs/extended-lossy-uncompressed-alpha.webp
2023-05-30 06:14:56 +02:00
Nico Weber a22cbc9a28 WebP/Lossy: Add an additional test case
This image covers two things that aren't covered by the existing
tests, and I found it useful for testing locally. The image's license
allows redistributing it, so add it as a test case.
2023-05-30 06:14:56 +02:00
Nico Weber 358d94b57a WebP/Lossy: Add some basic tests 2023-05-29 19:44:45 +02:00
Ben Wiederhake da394abe04 LibGfx+Fuzz: Convert ImageDecoder::initialize to ErrorOr
This prevents callers from accidentally discarding the result of
initialize(), which was the root cause of this OSS Fuzz bug:

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=55896&q=label%3AProj-serenity&sort=summary
2023-05-12 09:40:24 +01:00
Lucas CHOLLET 8da9ff24e4 Tests: Add tests for 12 bits JPEGs
In this commit, two tests are added, one with a `SOF1` image, the other
with a `SOF2`.
2023-05-09 07:00:15 +02:00
Nico Weber ae7e26e095 Tests/LibGfx: Add some test coverage for animated webp decoding
Also add two FIXME comments for lossy decoding.
2023-05-07 07:08:05 +02:00
Nico Weber 95e35b7f5e LibGfx: Correctly decode webp lossless with small palette and odd width
WebP lossless files that use a color indexing transform with <= 16
colors use pixel bundling to pack 2, 4, or 8 pixels into a single pixel.

If the image's width doesn't happen to be an exact multiple of the
bundling factor, we need to:

1. Use ceil_div() instead of just dividing the width by the bundling
   factor

2. Remember the original width and use it instead of computing
   reduced width times bundling factor

This does these changes, and adds a simple test for it -- it at least
checks that the decoded images have the right size.

(I created these images myself in Photoshop, and used the same
technique as for Tests/LibGfx/test-inputs/catdog-alert-*.webp
to create images with a certain number of colors.)
2023-04-09 00:14:15 +02:00
Nico Weber f2efb97578 Tests: Add webp lossless test with color index and < 16 colors
For the test files, I opened Base/res/icons/catdog/alert.png in Adobe
Photoshop 2023, used Image->Mode->Index Color...->
Palette: Local (Perceptive) to reduce the number of colors to 13, 8, and
3 with transparency, and 2 without transparency, then converted it back
to Image->Mode->RGB Color (else it can't be saved as webp), then
File->Save a Copy... to save a WebP (mode lossless) for every palette
size.
2023-04-08 19:24:13 +02:00
Nico Weber 6151a251f5 Tests: Add test for lossless webp file using a color indexing tranform
The image is https://quakewiki.org/wiki/File:Qpalette.png in lossless
webp format with a color indexing transform.

I've created Qpalette.webp by running

    examples/cwebp -z 0 ~/src/serenity/tmp.ppm -o Qpalette.webp

built at libwebp webmproject/libwebp@0825faa4c1 (without
png support, so I first ran

    Build/lagom/image ~/Downloads/Qpalette.png -o tmp.ppm

to convert it from png to a format my cwebp binary could read).

This file also happens to explicitly set max_symbol, so it serves
as a test for that code path as well.
2023-04-08 16:50:40 +02:00
Nico Weber 61b540e737 Tests: Add another test for webp lossless decoding 2023-04-07 20:49:39 +02:00
Nico Weber 09dd9c4fad Tests: Add test for webp lossless decoding 2023-04-05 13:24:00 +02:00
Lucas CHOLLET 62290d57f7 Tests: Add a test for SOF2 JPEGs with successive approximations
This image was generated using `cjpeg` with the following scan file:

0 1 2: 0 0 0 2;
0: 1 63 0 1;
1: 1 63 0 1;
2: 1 63 0 1;
0 1 2: 0 0 2 1;
0: 1 63 1 0;
1: 1 63 1 0;
2: 1 63 1 0;
0 1 2: 0 0 1 0;
2023-04-03 17:06:21 +01:00
Lucas CHOLLET 3f9c5af553 LibGfx/JPEG: More support for scans with a single component
Introduced in 2c98eff, support for non-interleaved scans was not working
for frames with a number of MCU per line or column that is odd. Indeed,
the decoder assumed that they have scans that include a fabricated MCU
like scans with multiple components.

This patch makes the decoder handle images with a number of MCU per line
or column that is odd. To do so, as in the current decoder state we do
not know if components are interleaved at allocation time, we skip over
falsely-created macroblocks when filling them. As stated in 2c98eff,
this is probably not a good solution and a whole refactor will be
welcome.

It also comes with a test that open a square image with a side of 600px,
meaning 75 MCUs.
2023-03-25 21:31:21 +01:00
Lucas CHOLLET 496b7ffb2b LibGfx: Move all image loaders and writers to a subdirectory 2023-03-21 22:39:25 +01:00
Lucas CHOLLET af58f012be Tests: Add a test for JPEGs with RGB components 2023-03-10 22:22:36 +01:00
Lucas CHOLLET 7ddf9e9177 Tests: Replace test image with my own creation 2023-03-04 23:39:41 +00:00
Lucas CHOLLET 68cd6f5614 Tests: Add a test for SOF2 images with only spectral selection
You can generate one by using `cjpeg` with the -scan argument.

This image has been generated with the following scan file:
0 1 2: 0 0 0 0;
0: 1 9 0 0;
2: 1 63 0 0 ;
1: 1 63 0 0 ;
0: 10 63 0 0;
2023-03-04 23:39:41 +00:00
Lucas CHOLLET 8c1a409263 Tests: Add a test for SOF0 images with several scans
This type of image isn't common, and you can probably only find one by
generating it yourself. It can be done using `cjpeg` with the -scan
argument.

This image has been generated with the following scan file:
0: 0 63 0 0;
1: 0 63 0 0;
2: 0 63 0 0;
2023-02-27 13:39:22 +01:00
Lucas CHOLLET a40c7354c1 Tests: Rename "test_jpg" to "test_jpeg_sof0_one_scan" 2023-02-27 13:39:22 +01:00
MacDue 6cf8eeb7a4 LibGfx: Return bool not ErrorOr<bool> from ImageDecoderPlugin::sniff()
Nobody made use of the ErrorOr return value and it just added more
chance of confusion, since it was not clear if failing to sniff an
image should return an error or false. The answer was false, if you
returned Error you'd crash the ImageDecoder.
2023-02-26 19:43:17 +01:00
Nico Weber fa34832297 LibGfx: Implement WebPImageDecoderPlugin::loop_count()
Turns out extended-lossless-animated.webp did have a loop count of 0.
So I opened it in Hex Fiend and changed the byte at position 42
(which is the first byte of the little-endian u16 storing the loop
count) to 0x2A, so that the test can compare the loop count to something
not 0.
2023-02-26 15:54:22 +01:00
Nico Weber 3c5450b8be LibGfx: Implement is_animated() and frame_count() for webp plugin 2023-02-26 15:54:22 +01:00
Nico Weber d66f143fb7 Tests: Add webp size decoding tests for webp 2023-02-26 12:21:40 +01:00
Nico Weber 0190be9788 Tests: Use MUST more in TestImageDecoder
No behavior change.
2023-02-26 01:15:10 +01:00
Lucas CHOLLET 856d0202f2 LibGfx: Rename JPGLoader to JPEGLoader
The patch also contains modifications on several classes, functions or
files that are related to the `JPGLoader`.

Renaming include:
 - JPGLoader{.h, .cpp}
 - JPGImageDecoderPlugin
 - JPGLoadingContext
 - JPG_DEBUG
 - decode_jpg
 - FuzzJPGLoader.cpp
 - Few string literals or texts
2023-02-18 23:56:24 +01:00
Nico Weber bea3f3fc46 LibGfx: Move TestImageDecoder over to input file approach in 8cfabbcd93
Rather than reading files out of /res, put them in a subfolder of
Tests/LibGfx/ and pick the path based on AK_OS_SERENITY.

That way, the tests can also pass when run under lagom.

(I just `cp`d all the files that the test previously read from
random places into Tests/LibGfx/test-inputs.)
2023-02-01 08:56:56 -05:00
Nico Weber f4c1269d4c Tests: Modernize TestImageDecoder a bit
- Use MUST() instead of checking plugin_decoder_or_error.is_error()
- Use MappedFile::bytes()
- Don't use EXPECT_EQ when comparing to fixed bools

No intended behavior change.
2023-01-29 22:37:37 +00:00
Liav A 20033d06d8 Tests/LibGfx: Fix test_gif test case
We should expect the GIF image to be animated, therefore fix that
condition.
2023-01-20 17:05:09 +00:00
Liav A da525ccc43 Tests/LibGfx: Fix test_not_ico test case
We should expect the sniffing method and the initialize method to fail
because this test case is testing that the ICO image decoder should not
decode random data within it.
2023-01-20 17:05:09 +00:00
Liav A 57e19a7e56 LibGfx: Re-structure the whole initialization pattern for image decoders
When trying to figure out the correct implementation, we now have a very
strong distinction on plugins that are well suited for sniffing, and
plugins that need a MIME type to be chosen.

Instead of having multiple calls to non-static virtual sniff methods for
each Image decoding plugin, we have 2 static methods for each
implementation:
1. The sniff method, which in contrast to the old method, gets a
    ReadonlyBytes parameter and ensures we can figure out the result
    with zero heap allocations for most implementations.
2. The create method, which just creates a new instance so we don't
    expose the constructor to everyone anymore.

In addition to that, we have a new virtual method called initialize,
which has a per-implementation initialization pattern to actually ensure
each implementation can construct a decoder object, and then have a
correct context being applied to it for the actual decoding.
2023-01-20 15:13:31 +00:00
Liav A 71f275b5ad Tests/LibGfx: Add tests for compressed TGA images 2023-01-15 12:43:03 +01:00
Liav A 6bf2460231 Tests/LibGfx: Add tests for top-left and bottom-left TGA images 2023-01-15 12:43:03 +01:00
Ben Wiederhake 6b7ce19161 Everywhere: Remove unused includes of LibC/stdlib.h
These instances were detected by searching for files that include
stdlib.h, but don't match the regex:

\\b(_abort|abort|abs|aligned_alloc|arc4random|arc4random_buf|arc4random_
uniform|atexit|atof|atoi|atol|atoll|bsearch|calloc|clearenv|div|div_t|ex
it|_Exit|EXIT_FAILURE|EXIT_SUCCESS|free|getenv|getprogname|grantpt|labs|
ldiv|ldiv_t|llabs|lldiv|lldiv_t|malloc|malloc_good_size|malloc_size|mble
n|mbstowcs|mbtowc|mkdtemp|mkstemp|mkstemps|mktemp|posix_memalign|posix_o
penpt|ptsname|ptsname_r|putenv|qsort|qsort_r|rand|RAND_MAX|random|reallo
c|realpath|secure_getenv|serenity_dump_malloc_stats|serenity_setenv|sete
nv|setprogname|srand|srandom|strtod|strtof|strtol|strtold|strtoll|strtou
l|strtoull|system|unlockpt|unsetenv|wcstombs|wctomb)\\b

(Without the linebreaks.)

This regex is pessimistic, so there might be more files that don't
actually use anything from the stdlib.

In theory, one might use LibCPP to detect things like this
automatically, but let's do this one step after another.
2023-01-02 20:27:20 -05:00
Bruno Conde 7e9019a9c3 LibGfx: Support BMP favicons with less than 32 bpp
Adapt BMPImageDecoderPlugin to support BMP images included in ICOns.
ICOImageDecoderPlugin now uses BMPImageDecoderPlugin to decode all
BMP images instead of it's own ad-hoc decoder which only supported
32 bpp BMPs.
2022-12-20 10:26:55 +01:00
Linus Groh 6e19ab2bbc AK+Everywhere: Rename String to DeprecatedString
We have a new, improved string type coming up in AK (OOM aware, no null
state), and while it's going to use UTF-8, the name UTF8String is a
mouthful - so let's free up the String name by renaming the existing
class.
Making the old one have an annoying name will hopefully also help with
quick adoption :^)
2022-12-06 08:54:33 +01:00
sin-ack 3f3f45580a Everywhere: Add sv suffix to strings relying on StringView(char const*)
Each of these strings would previously rely on StringView's char const*
constructor overload, which would call __builtin_strlen on the string.
Since we now have operator ""sv, we can replace these with much simpler
versions. This opens the door to being able to remove
StringView(char const*).

No functional changes.
2022-07-12 23:11:35 +02:00
Andreas Kling 58fb3ebf66 LibCore+AK: Move MappedFile from AK to LibCore
MappedFile is strictly a userspace thing, so it doesn't belong in AK
(which is supposed to be user/kernel agnostic.)
2021-11-23 11:33:36 +01:00
Andreas Kling 5a79c69b02 LibGfx: Make ImageDecoderPlugin::frame() return ErrorOr<>
This is a first step towards better error propagation from image codecs.
2021-11-21 20:22:48 +01:00
Andreas Kling 09780ba7a9 Tests/LibGfx: Actually test image decoders in TestImageDecoder
We were passing raw Gfx::Bitmap objects into the various image decoders
instead of encoded image data. This made all of them fail, but the test
expectations were set up in a way that aligned with this outcome.

With this patch, we now test the codecs for real. Except ICO, since we
don't have an ICO file handy. That's a FIXME.
2021-11-11 11:20:58 +01:00
Brian Gianforcaro fd0dbd1ebf Tests: Establish root Tests directory, move Userland/Tests there
With the goal of centralizing all tests in the system, this is a
first step to establish a Tests sub-tree. It will contain all of
the unit tests and test harnesses for the various components in the
system.
2021-05-06 17:54:28 +02:00
Renamed from Userland/Tests/LibGfx/TestImageDecoder.cpp (Browse further)