1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-07 20:17:34 +00:00
Commit graph

420 commits

Author SHA1 Message Date
Nico Weber
9c5a75067f LibGfx/JPEG: Reject ycck or cmyk jpegs with k subsampled for now
The decoder assumes that k's sampling factor matches y's at the moment.
Better to error out than to silently render something broken.

For ycck, covered by ycck-2111.jpg in the tests.
2023-12-29 18:55:57 +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
Lucas CHOLLET
f389c1cdba LibGfx+LibPDF: Use LibCompress' implementation of the PackBits decoder
No need to have these three copies :^)
2023-12-27 17:40:11 +01:00
Nico Weber
3c39c18440 LibGfx/JPEG: Add spec comment to read_start_of_frame() 2023-12-27 13:38:25 +00:00
Lucas CHOLLET
a31b988473 LibGfx/TIFF: Ensure baseline tags presence before decoding
This allows us to reject invalid images before trying to decode them.
The spec requires more tag to be present[1] but as we don't use them for
decoding I don't see the point.

[1] - XResolution, YResolution and ResolutionUnit
2023-12-23 20:54:07 +01: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
Nicolas Ramz
caa13d3960 LibGfx/ILBMLoader: Stop the decoding loop when plane buffer is full
This allows decoding files (eg. 24bit) that may have been badly encoded.
2023-12-21 09:19:30 +00:00
Lucas CHOLLET
caf9f00456 LibGfx/TIFF: Skip channels that we are unable to interpret
As per the specification, TIFF readers should gracefully skip samples
that they are not able to interpret.

This patch allow us to read `strike.tif` from the libtiff test suite as
an RGB image.
2023-12-20 12:19:30 +01:00
Lucas CHOLLET
a443d2955a LibGfx/TIFF: Don't use SamplesPerPixel to infer the "type" of image
The number of samples is not a good measure to deduce the type of image
we are decoding. As per the TIFF spec, the PhotometricInterpretation tag
is required and we should use that instead.
2023-12-20 12:19:30 +01: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
Lucas CHOLLET
7266d8c35d LibGfx/TIFF: Correctly upscale samples with a resolution lower than 8
As pointed out by @nico, while doing a right-shift to downscale is fine,
a left-shift to upscale gives wrong results. As an example, imagine a 2-
bits value containing 3, left-shifting it would give 192 instead of 255.
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
3ae29fdeec LibGfx/TIFF: Support WhiteIsZero parameter for grayscale images
PhotometricInterpretation::WhiteIsZero is used to inverse black and
white on bilevel and grayscale images.
2023-12-10 09:45:30 +01: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
Nicolas Ramz
8d68f94282 LibGfx/ILBMLoader: Add HAM6/HAM8 support 2023-12-07 10:08:29 -07:00
Lucas CHOLLET
2691651abf LibGfx/TIFF: Generated the code to output debug prints
When the `TIFF_DEBUG` flag is set, the TIFF decoder logs every tag and
their values. This is already useful but require the developer to have
the spec handy in order to decrypt each value to its signification. None
of this information is available at runtime, but this is known by the
Python generator. So by generating these debug logs, we drastically
increase their value.

As a bonus point, most of these functions should be useful when we will
display image's metadata in Serenity.
2023-12-07 11:10:55 +01:00
Lucas CHOLLET
1d345109c4 LibGfx/TIFF: Move Formatter<Rational>'s definition to TIFFMetadata.h
This will soon be used in TIFFTagHandler.cpp, so the definition needs to
be shared.
2023-12-07 11:10:55 +01: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
Lucas CHOLLET
ff73d5464a LibGfx/TIFF: Make loop_over_pixels autonomous for reading samples
Let's make the "read a sample" part independent of the decoder. That
will soon allow us to read samples based on the image's parameter
without duplicating the code for every decoder.
2023-12-07 08:17:46 +00:00
Lucas CHOLLET
0a80daef90 LibGfx/TIFF: Don't include the null-byte terminator when reading strings 2023-12-03 20:27:00 +01:00
Idan Horowitz
1a35621930 LibGfx: Eliminate multiplication integer overflow in planar_to_chunky
Multiplying two u16s will result in a i32 sized result, which will
overflow to negative values for large input values.

Fixes ossfuzz-64198.
2023-12-02 11:46:03 +01:00
Tim Ledbetter
10757b7787 LibGfx/TinyVG: Clamp RGBAF32 color values from 0 and 255 2023-12-02 10:47:39 +01: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
1ede4f249d LibGfx/TIFF: Decode all PackedBits beforehand
This change doesn't change much on its own. The idea behind this
refactoring is to separate the sample reading from the decoding step.
The decoder returning data byte per byte was fine as we only support
8 bits images, but this assumption won't hold for a long time. So let's
decode everything beforehand and strictly partition the sample reading
code somewhere else.
2023-12-02 10:37:07 +01:00
Lucas CHOLLET
4994609af0 LibGfx/TIFF: Add support for the ICCProfile tag 2023-12-02 10:36:02 +01:00
Lucas CHOLLET
62f28d9968 LibGfx/TIFF: Teach the generator how to handle tags of type Undefined
This tag type is a bit different as even if it fits in the general
definition given in the TIFF specification. That is the value will be of
one specified type multiplied by a known count. Having a
`Vector<Variant<u8, ...>>` will be very painful to use. So let's deviate
a bit from the normal way and use a `ByteBuffer` directly instead this
complicated type.
2023-12-02 10:36:02 +01:00
Lucas CHOLLET
e6fc18d96a LibGfx/TIFF: Support TIFF 5.0 LZW images
This makes us decode `quad-lzw.tif` from libtiff's test suite:
https://libtiff.gitlab.io/libtiff/images.html
2023-12-02 08:04:44 +01:00
Lucas CHOLLET
ce6cd4f45f LibGfx/GIF: Use LZWDecoder::decode_all() 2023-12-01 12:58:14 +01:00
Lucas CHOLLET
cc816b486c LibGfx/TIFF: Use LZWDecoder::decode_all() 2023-12-01 12:58:14 +01:00
Tim Schumacher
197331c922 AK: Reject BitStream reads beyond EOF by default
The only exception to this is the lossless WebP decoder, which
legitimately relies on this behavior, even upstream.
2023-12-01 12:48:18 +01:00
Lucas CHOLLET
9836a9ad0e LibGfx/TIFF: Introduce a code generator
This will allow us to generate code that handle and provide easy access
to metadata stored in TIFF's tags. The generator is a Python script, and
it output both TIFFMetadata.h and TIFFTagHandler.cpp files.

The generator will definitely need some update to support all TIFF and
EXIF tags, but that will still be easier than writing everything
ourselves.

Some small modifications are needed in TIFFLoader.cpp to make it
compatible with the new `Metadata` class.
2023-11-27 09:07:16 -07:00
Sam Atkins
2c24192e1f LibGfx: Move FourCC to its own file
These are used in fonts too, so let's not limit them to ImageLoader.
2023-11-24 08:42:46 +01:00
Lucas CHOLLET
1afdf7f3c7 LibGfx/TIFF: Take the TIFF value by rvalue reference in handle_tag() 2023-11-18 11:14:37 +00:00
Lucas CHOLLET
4ab2903e25 LibGfx/TIFF: Make TIFFLoadingContext::handle_tag be a free function
And move it to another file. This code is going to be generated soon, so
let's put it in another file.
2023-11-18 11:14:37 +00:00
Lucas CHOLLET
34d91dec5b LibGfx/TIFF: Extract metadata-related definition to their own file 2023-11-18 11:14:37 +00:00
Lucas CHOLLET
1d1e7abba7 LibGfx/TIFF: Put the TIFFLoadingContext class in a TIFF namespace 2023-11-18 11:14:37 +00:00
Lucas CHOLLET
b78f93d0b5 LibGfx/TIFF: Put metadata fields in their own struct 2023-11-18 11:14:37 +00:00
Nico Weber
bfe27228a3 LibPDF+LibGfx: Don't invert CMYK channels in JPEG data in PDFs
This is a hack: Ideally we'd have a CMYK Bitmap pixel format,
and we'd convert to rgb at blit time. Then we could also apply color
profiles (which for CMYK images are CMYK-based).

Also, the colors for our CMYK->RGB conversion are off for PDFs,
and we have distinct codepaths for this in Gfx::Color (for paths)
and JPEGs. So when we fix that, we'll have to fix it in two places.

But this doesn't require a lot of code and it's a huge visual
progression, so let's go with it for now.
2023-11-17 22:32:40 +00:00
Nico Weber
000d9da73c LibGfx: Allow passing FilterType::None to unfilter_scanline()
Makes calling this in LibPDF less awkward, and there's no reason
not to allow this.
2023-11-17 19:09:50 +01:00
Nico Weber
574357ef00 LibGfx: Use ceil_div() in png decoder
No behavior change, arguably easier to read.
2023-11-17 19:09:50 +01:00
Nico Weber
5a70813d11 LibGfx: Make unfilter_scanline() a static PNGImageDecoderPlugin method
That way, LibPDF will be able to call it.

No behavior change.
2023-11-17 19:09:50 +01:00
Nico Weber
588d6fab22 LibGfx+LibPDF: Create filter_type() for converting u8 to FilterType
...and use it in LibPDF.

No behavior change.
2023-11-17 19:09:50 +01:00
Nico Weber
6b2c60404d LibGfx: Use PNG::paeth_predictor() in png decoding path
Increases code reuse between encoder and decoder a tiny bit.
No behavior change.

(We should use the vectorized version in the future! But first,
we should learn to do the prediction in-place.)
2023-11-17 19:09:50 +01:00
Lucas CHOLLET
272be6b20a LibGfx/TIFF: Add support for LZW compression 2023-11-12 13:56:27 +01:00
Lucas CHOLLET
4f5a0227e2 LibGfx/TIFF: Add support for the differencing predictor
The differencing predictor is a different way to encode pixels in TIFF
images. Every pixel is encoded as a difference with the previous column
of the image, except the first column, obviously.

This parameter is materialized by a new tag for which reading was also
implemented.
2023-11-12 13:56:27 +01:00
Nicolas Ramz
68e916490b LibGfx/JPEGWriter: Fix crash on macOS when csize coefficient is 0
This fixes #21108
2023-11-09 16:07:28 +01:00
Tim Schumacher
a2f60911fe AK: Rename GenericTraits to DefaultTraits
This feels like a more fitting name for something that provides the
default values for Traits.
2023-11-09 10:05:51 -05:00