1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 10:48:11 +00:00
Commit graph

172 commits

Author SHA1 Message Date
Lucas CHOLLET
75d87ccf5f LibGfx/TIFF+CCITT: Start to decode CCITT Group 3 images
We currently only support 1D Group 3, but that's a start.

The test case was generated with GIMP (it happens to be 1D by chance).
2024-01-18 14:00:56 +01:00
Lucas CHOLLET
edffdc35a9 LibGfx/TIFF+CCITT: Clarify naming of compression type 2
Type 2 <=> One-dimensional Group3, customized for TIFF
Type 3 <=> Two-dimensional Group3, uses the original 1D internally
Type 4 <=> Two-dimensional Group4

So let's clarify that this is not Group3 1D but the TIFF variant, which
is called `CCITTRLE` in libtiff. So let's stick with this name to avoid
confusion.
2024-01-18 14:00:56 +01:00
Nicolas Ramz
534eeb6c4b LibGfx/ILBMLoader: Properly display images with a bitplane mask
Images with a display mask ("stencil" as it's called in DPaint) add
an extra bitplane which acts as a mask. For now, at least skip it
properly. Later we should render masked pixels as transparent, but
this requires some refactoring.
2024-01-18 13:59:17 +01:00
Lucas CHOLLET
015c47da51 Tests/LibGfx: Use TRY_OR_FAIL more in TestImageDecoder 2024-01-15 23:16:57 -07:00
Nico Weber
3616d14c80 LibGfx/JPEG: Allow decoding more subsampling factors
We now allow all subsampling factors where the subsampling factors
of follow-on components evenly decode the ones of the first component.

In practice, this allows YCCK 2111, CMYK 2112, and CMYK 2111.
2024-01-15 11:20:11 -07:00
Nicolas Ramz
a1255cb6c9 LibGfx/ILBMLoader: Don't decode bits once full row has been decoded
We were potentially decoding more bits than needed: this could
trash the next lines if decoder didn't zero the extra bits.
2024-01-14 20:41:25 +01:00
Nico Weber
1b4f9bdbdb Tests: Add a png in Display P3 that shows up as solid color in sRGB
I created a 16-bpp RGB file in Display P3 in photoshop, filled it
with (0, 255, 0), and then drew something on it with (100, 255, 0).

(Since it's a 16-bpp image, 255 ix stored as 0xffff and 100 is stored
as 65535 * 100 / 255 == 0x6464 in the file.)

I verified that Edit->Convert to Profile...->sRGB resulted in an
image filled with (0, 255, 0) in that color space (due to gamut
clipping).

Similar to these:
* https://webkit.org/blog-files/color-gamut/Webkit-logo-P3.png
* https://www.dropbox.com/s/tgarynpj65ouafd/insta-logo.png?dl=1

...but in green instead of in red, and hand-drawn by me so no license
concerns.
2024-01-12 16:20:46 -07:00
Nico Weber
7fb32b6682 LibGfx: Fix off-by-some in Painter::draw_scaled_bitmap_with_transform()
Before this, drawing a 1x1 bitmap scaled up to MxN would only fill
M/2 x N/2 pixel, due to source_point going outside (0, 0).
2024-01-10 09:38:13 +01:00
Nicolas Ramz
fc5b6e4dda LiGfx/ILBMLoader: Don't throw if malformed bitplane can be decoded
Some apps seem to generate malformed images that are accepted
by most readers. We now only throw if malformed data would lead to
a write outside the chunky buffer.
2024-01-08 07:21:27 -07:00
Lucas CHOLLET
335097e446 LibGfx/TIFF: Modify the image according to the Orientation tag
Let's use the already existing logic (ExifOrientedBitmap) to modify the
bitmap to honor the orientation tag.
2024-01-08 00:07:44 +01:00
Lucas CHOLLET
402de2985d LibGfx/ICO: Do not try to decode a mask if we already reached EOF
When using the BMP encoding, ICO images are expected to contain a 1-bit
mask for transparency. Regardless an alpha channel is already included
in the image, the mask is always required. As stated here[1], the
mask is used to provide shadow around the image.

Unfortunately, it seems that some encoder do not include that second
transparency mask. So let's read that mask only if some data is still
remaining after decoding the image.

The test case has been generated by truncating the 64 last bytes
(originally dedicated to the mask) from the `serenity.ico` file and
changing the declared size of the image in the ICO header. The size
value is stored at the offset 0x0E in the file and I changed the value
from 0x0468 to 0x0428.

[1]: https://devblogs.microsoft.com/oldnewthing/20101021-00/?p=12483
2024-01-07 12:32:02 -05:00
Lucas CHOLLET
9c54c13744 Tests/LibGfx: Move the ICO test file to the ico directory
And add more tests on the image than just "we are able to decode it".
2024-01-07 12:32:02 -05:00
Lucas CHOLLET
75fc51bb67 Tests/LibGfx: Fix a typo 2024-01-07 10:22:59 +01:00
Andreas Kling
182a2b0c3a LibGfx/GIF: Only parse global color table if header flag is set
This fixes an issue where GIF images without a global color table would
have the first segment incorrectly interpreted as color table data.

Makes many more screenshots appear on https://virtuallyfun.com/ :^)
2024-01-05 13:20:00 +01:00
Lucas CHOLLET
b8cbc282f3 LibGfx/TIFF: Don't stop decoding when failing to decode a tag
TIFF files are made in a way that make them easily extendable and over
the years people have made sure to exploit that. In other words, it's
easy to find images with non-standard tags. Instead of returning an
error for that, let's skip them.

Note that we need to make sure to realign the reading head in the file.

The test case was originally a 10x10 checkerboard image with required
tags, and also the `DocumentName` tag. Then, I modified this tag in a
hexadecimal editor and replaced its id with 30 000 (0x3075 as a LE u16)
and the type with the same value as well. This is AFAIK, never used as
a custom TIFF tag, so this should remain an invalid tag id and type.
2024-01-04 14:27:16 +01:00
Lucas CHOLLET
73c8b4865e LibGfx/TIFF: Add AdobeDeflate compression support
This new compression is quite popular and uses a basic Zlib compression
to compress strips. Note that this is not part of the original TIFF
specification but in the Technical Notes from 2002:
https://web.archive.org/web/20160305055905/http://partners.adobe.com/public/developer/en/tiff/TIFFphotoshop.pdf

The test case was generated with GIMP.
2023-12-29 20:12:07 +01:00
Nico Weber
a2bd19fdac LibGfx/JPEG: Make ycck jpegs with just cc subsampled decode correctly
We currently assume that the K (black) channel uses the same sampling
as the Y channel already, so this already works as long as we don't
error out on it.
2023-12-29 09:45:31 -05:00
Nico Weber
4236798244 Tests/LibGfx: Add automated tests for ycck jpegs
Only one of the three test cases pass at the moment.
2023-12-29 09:45:31 -05:00
Nico Weber
e735ee5251 Tests/LibGfx: Add YCCK jpeg test files
Obtained by running:

    convert rgb_components.jpg -colorspace cmyk \
        -sampling-factor 1 ycck-1111.jpg
    convert rgb_components.jpg -colorspace cmyk \
        -sampling-factor 2 ycck-2111.jpg
    convert rgb_components.jpg -colorspace cmyk ycck-2112.jpg

where rgb_components.jpg is the file in Tests/LibGfx/test-inputs/jpg.

(I used the web version of `convert` at
https://cancerberosgx.github.io/magic/playground/index.html)

While this does indeed produce a cmyk jpg (using the YCCK encoding
internally), it uses the mathematical rgb->cmyk conversion and does
not embed an cmyk color space in the output jpg.

Normally, cmyk images are for printing and hence converting them
from cmyk to rgb using a color profile like SWOP leads to better
results. So if a cmyk image does not contain color space information,
applications might use something like SWOP instead of the simple
math transform to convert to RGB. Programs doing that will show
these images as fairly muted (and would arguably be correct doing
so).

Hence, tests using these images shouldn't check their RGB values.
Ideally, we'd add a way to get the raw cmyk data from a cmyk jpeg,
and then tests could test color values against that.

The -1111 image uses no subsampling, meaning each channel's sampling
factor is 1.

The -2111 image uses subsampling for the non-Y channels, meaning the
sampling factors are 2 for Y and 1 each for YYK.

The -2112 image uses subsampling for the two C channels, meaning the
sampling factors are 2 for Y and K and 1 each for YY.

We correctly render the -1111 variant (using e.g.
`Build/lagom/bin/image -o out.png .../ycck-1111.jpg).

We render the -2111 variant, but it looks pretty broken.

We refuse to decode the -2112 variant. This is #21259.

Manual tests for now, but having these in tree will make it easier
to write unit tests later, once things work better.
2023-12-29 08:17:10 +00:00
Lucas CHOLLET
67522fab2e LibGfx/TIFF: Add support for RGBPalette images
TIFF images with the PhotometricInterpretation tag set to RGBPalette are
based on indexed colors instead of explicitly describing the color for
each pixel. Let's add support for them.

The test case was generated with GIMP using the Indexed image mode after
adding an alpha layer. Not all decoders are able to open this image, but
GIMP can.
2023-12-23 20:41:48 +01:00
Lucas CHOLLET
2cfca633ca LibGfx/TIFF: Add support for images with UnassociatedAlpha
UnassociatedAlpha is the one used by GIMP when generating TIFF images
with transparency. Support is added for Grayscale and RGB images as it's
the two that we support right now but managing transparency should be
really straightforward for other types as well.
2023-12-22 08:08:47 +00:00
Nicolas Ramz
6ccdb1dc72 LibGfx/ILBMLoader: Add support for 24bit files 2023-12-21 09:19:30 +00:00
Lucas CHOLLET
64912d4d02 LibGfx/TIFF: Add support for images with CCITT3 1D compression
This compression (tag Compression=2) is not very popular on its own, but
a base to implement CCITT3 2D and CCITT4 compressions.

As the format has no real benefits, it is quite hard to find an app that
accepts tho encode that for you. So I used the following program that
calls `libtiff` directly:
```cpp
#include <vector>
#include <cstdlib>
#include <iostream>

#include <tiffio.h>

// An array containing 0 and 1 of length width * height.
extern std::vector<uint8_t> array;
int main() {
    // From: https://stackoverflow.com/a/34257789

    TIFF *image = TIFFOpen("input.tif", "w");
    int const width = 400;
    int const height = 300;
    TIFFSetField(image, TIFFTAG_IMAGEWIDTH, width);
    TIFFSetField(image, TIFFTAG_IMAGELENGTH, height);
    TIFFSetField(image, TIFFTAG_PHOTOMETRIC, 0);
    TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_CCITTRLE);

    TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, 1);
    TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, 1);
    TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, 1);

    std::vector<uint8_t> scan_line(width / 8 + 8, 0);
    int count = 0;
    for (int i = 0; i < height; i++) {
        std::fill(scan_line.begin(), scan_line.end(), 0);
        for (int x = 0; x < width; ++x) {
            uint8_t eight_pixels = scan_line.at(x / 8);
            eight_pixels = eight_pixels << 1;
            eight_pixels |= !array.at(i * width + x);
            scan_line.at(x / 8) = eight_pixels;
        }
        int bytes = int(width / 8.0 + 0.5);
        if (TIFFWriteScanline(image, scan_line.data(), i, bytes) != 1)
            std::cerr << "Something went wrong\n";
    }

    TIFFClose(image);
}
```
2023-12-19 21:01:24 +01:00
Ali Mohammad Pur
5e1499d104 Everywhere: Rename {Deprecated => Byte}String
This commit un-deprecates DeprecatedString, and repurposes it as a byte
string.
As the null state has already been removed, there are no other
particularly hairy blockers in repurposing this type as a byte string
(what it _really_ is).

This commit is auto-generated:
  $ xs=$(ack -l \bDeprecatedString\b\|deprecated_string AK Userland \
    Meta Ports Ladybird Tests Kernel)
  $ perl -pie 's/\bDeprecatedString\b/ByteString/g;
    s/deprecated_string/byte_string/g' $xs
  $ clang-format --style=file -i \
    $(git diff --name-only | grep \.cpp\|\.h)
  $ gn format $(git ls-files '*.gn' '*.gni')
2023-12-17 18:25:10 +03:30
Nicolas Ramz
cd6c7f3fc4 LibGfx/ILBMLoader: Add support for PC DeluxePaint files 2023-12-13 10:39:13 +00:00
Lucas CHOLLET
234d084876 LibGfx/TIFF: Add support for bit-depth up to 32 bits per sample
This makes us support every "minisblack" and "rgb-contig" images from
the depth folder of libtiff's test suite:
https://libtiff.gitlab.io/libtiff/images.html
2023-12-09 21:47:33 +01:00
Lucas CHOLLET
25993cd93b Tests: Use TRY_OR_FAIL instead of MUST in TestImageDecoder.cpp
No need to panic the executable on a test failure.
2023-12-09 19:05:45 +01:00
Nicolas Ramz
8d68f94282 LibGfx/ILBMLoader: Add HAM6/HAM8 support 2023-12-07 10:08:29 -07:00
Lucas CHOLLET
da134f6867 LibGfx/TIFF: Add support for grayscale images
Images with a single sample per pixel should be interpreted as
grayscale.
2023-12-07 08:17:46 +00:00
Nico Weber
b2a1130556 LibGfx/ICC: Implement conversion between different connection spaces
If one profile uses PCSXYZ and the other PCSLAB as connection space,
we now do the necessary XYZ/LAB conversion.

With this and the previous commits, we can now convert from profiles
that use PCSLAB with mAB, such as stress.jpeg from
https://littlecms.com/blog/2020/09/09/browser-check/ :

    % Build/lagom/icc --name sRGB --reencode-to serenity-sRGB.icc
    % Build/lagom/bin/image -o out.png \
        --convert-to-color-profile serenity-sRGB.icc \
        ~/src/jpegfiles/stress.jpeg
2023-12-04 08:02:36 +00:00
Tim Ledbetter
aa54007943 LibGfx/TinyVG: Avoid OOM if header contains a bogus color table size
This change limits the amount of memory that is initially allocated for
the color table. This prevents an OOM condition if the file contains an
incorrect color table size.
2023-12-02 10:47:39 +01:00
Lucas CHOLLET
4994609af0 LibGfx/TIFF: Add support for the ICCProfile tag 2023-12-02 10:36:02 +01:00
Lucas CHOLLET
272be6b20a LibGfx/TIFF: Add support for LZW compression 2023-11-12 13:56:27 +01:00
Tim Ledbetter
c1d7a51391 LibGfx/ICC: Avoid buffer overrun when creating TextDescriptionTagData
We now validate that the offsets used cannot overflow, preventing
possible buffer overruns.
2023-11-08 09:37:30 +01:00
Tim Ledbetter
f56ae8c0e9 LibGfx/ILBM: Ensure CMAP chunk size matches expected value
The color map should be 3 bytes per pixel and should contain
`2^nPlanes` pixels. We now return an error if the color map isn't the
size we expect.
2023-11-08 09:36:01 +01:00
Tim Ledbetter
ae6c39e501 LibGfx/ILBM: Ensure decompressed body chunk data is the correct length 2023-11-08 09:36:01 +01:00
Tim Ledbetter
39f7f1e84c Tests: Use more representative test cases for ILBM regression tests
Previously, the regression tests for OSS-Fuzz issues 62033 and 63296
used test case files directly from OSS-Fuzz. These files are invalid
in multiple ways because they have been generated by a fuzzer. This
commit replaces these files with ones that only expose the issue being
tested.
2023-11-08 09:36:01 +01:00
Lucas CHOLLET
81794df280 LibGfx/TIFF: Add support for images with PackBits compression 2023-11-08 09:28:36 +01:00
Lucas CHOLLET
ed8d82f3de Tests/LibGfx: Move the tiff image to its own folder 2023-11-08 09:28:36 +01:00
Lucas CHOLLET
404093a42e Tests/LibGfx: Add a test for the TIFF decoder 2023-11-06 12:29:30 -07:00
Tim Ledbetter
438e9e146c LibGfx/JPEG: Refill reservoir if necessary when discarding bits
This condition was hit 157 times out of the 109,233 JPEG images in the
Govdocs1 corpus. This change allows all of these
images to load correctly.
2023-11-05 09:01:15 +01:00
MacDue
50d33f79fa LibGfx: Allow extracting paths from fonts and add Gfx::Path::text()
This updates fonts so rather than rastering directly to a bitmap, you
can extract paths for glyphs. This is then used to implement a
Gfx::Path::text("some text", font) API, that if given a vector font
appends the path of the text to your Gfx::Path. This then allows
arbitrary manipulation of the text (rotation, skewing, etc), paving the
way for Word Art in Serenity.
2023-11-05 02:46:46 +01:00
Andrew Kaster
1567332e34 Userland+Tests: Remove uses of direct file loading for BitmapFont
Route them through Core::Resource APIs instead.
2023-10-29 13:12:28 -06:00
Tim Ledbetter
1a4df4ffe7 LibGfx/ICC: Avoid overflow when constructing NamedColor2TagData 2023-10-26 10:59:22 +02:00
Tim Ledbetter
52f78d07b8 LibGfx/WOFF2: Ensure numTables is within expected range
An error is now returned if `numTables` is zero or greater than 4096.
While this isn't explicitly mentioned in the specification, subsequent
calculations will be incorrect if the value falls outside this range.
2023-10-26 08:39:26 +02:00
Tim Ledbetter
2311e28d63 LibGfx/BMPLoader: Mitigate potential overflows when decoding bitmap DIB 2023-10-25 05:52:29 +02:00
Tim Ledbetter
e9be1bcd09 LibGfx/WOFF2: Reject fonts with a compressed size larger than 10MiB
This prevents a potential OOM condition when the header is malformed.
2023-10-24 13:45:01 +02:00
Tim Ledbetter
af633523af LibGfx/WOFF2: Tolerate incorrect totalSfntSize in WOFF2 header
The specification says that this value is for reference only, so we
should be able to load a file where this value is incorrect.
2023-10-24 13:45:01 +02:00
Tim Ledbetter
cb16c217b8 Tests: Add regression tests for fixed OSS-Fuzz test cases 2023-10-24 07:30:04 +02:00
Tim Ledbetter
c62dded5cc Tests: Move image decoder test PNG to its own folder 2023-10-24 07:30:04 +02:00