1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 03:27:44 +00:00
Commit graph

399 commits

Author SHA1 Message Date
Lucas CHOLLET
1de90bf55e LibGfx/TIFF: Generate the function that returns the size of a TIFF::Type 2024-01-14 21:17:50 +01:00
Lucas CHOLLET
3124c1616c LibGfx/TIFF: Generate code for the u16 to TIFF::Type conversion 2024-01-14 21:17:50 +01: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
Nicolas Ramz
1593ff2d4c LibGfx/ILBMLoader: Don't throw too early when decoding bitplanes
We were (again) throwing even though the image could be decoded.
2024-01-10 23:41:15 +01:00
Lucas CHOLLET
f6b86096a5 LibGfx/TIFF: Prevent the CCITT decoder to run on non bilevel image 2024-01-10 23:34:44 +01:00
Lucas CHOLLET
0ef449a588 LibGfx/TIFF: Don't crash on invalid indices inside RGBPalette images
We were previously accessing a Vector's element using a user-provided
value as index input.
2024-01-10 23:34:44 +01:00
Lucas CHOLLET
58bdca96cd LibGfx/TIFF: Use a wider type for palette indices to prevent overflow
We refuse any image with a sample depth greater than 32, storing these
value as `u64` prevent any overflows. This is probably overkill as no
one in their right mind will use a 32 bits color table.
2024-01-10 23:34:44 +01:00
Lucas CHOLLET
4d1c99e414 LibGfx/TIFF: Don't crash on RGBPalette images without a ColorMap 2024-01-10 23:34:44 +01:00
Lucas CHOLLET
25c3f8cd8e LibGfx/TIFF: Prefer a verbal form over a noun 2024-01-10 23:34:44 +01:00
Nico Weber
d8ada20bae LibGfx: Allow images to report that they are originally grayscale
...and implement it in JPEGLoader.

Since it's easy to get the grayscale data off a Bitmap, don't
add a grayscale_frame() accessor.
2024-01-10 09:39:00 +01:00
Nico Weber
239da5132d LibGfx/JPEG: Make it possible to obtain raw CMYK data from JPEGs
frame() still returns a regular RGB Bitmap (now lazily converted
from internal CMYK data), but JPEGImageDecoderPlugin now also
implements cmyk_frame().
2024-01-10 09:39:00 +01:00
Nico Weber
51d5397e92 LibGfx: Give ImageDecoder an API for getting raw CMYK data
frame() still returns a regular RGB Bitmap, but it's possible to also
get at raw CMYK data instead if desired, for image formats that can
store that.
2024-01-10 09:39:00 +01:00
Nico Weber
c997ee7b9d LibGfx+ImageViewer: Replace ImageDecoder::is_vector() with an enum
That makes it easier to extend to other special frame formats.
2024-01-10 09:39:00 +01:00
Nicolas Ramz
5e7e98cd3c LibGfx/ILBMLoader: Add support for transparent color 2024-01-08 07:21:27 -07: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
367882ae23 LibGfx: Make ExifOrientedBitmap::oriented_size be public
This will be useful for image decoders to expose the image size while
considering the orientation. A rotated image might have different
dimensions.
2024-01-08 00:07:44 +01:00
Lucas CHOLLET
ef10a58522 LibGfx: Remove ExifOrientedBitmap::Orientation in favor of TIFF's enum
ExifOrientedBitmap was implemented before the introduction of the TIFF
decoder. So we had to provide a definition of the Orientation enum. Now
that we have a TIFF implementation that comes with some enum
definitions, we should prefer this source.
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
52ce887b80 LibGfx/JPEG: Introduce a struct to hold sampling factors 2024-01-06 09:08:59 +00:00
Lucas CHOLLET
6c85f937ef LibGfx/JPEG: Print debug information on subsampling for each component 2024-01-06 09:08:59 +00:00
Lucas CHOLLET
145672a8b4 LibGfx/JPEG: Print some debug information about restart markers 2024-01-06 09:08:59 +00:00
Andreas Kling
c4d75ac11a LibGfx/GIF: Avoid a silly loop in GIF logical screen parsing 2024-01-05 13:20:00 +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
4e09ee1f2f LibGfx/TIFF: Reject images that declare a sample with abnormal bit depth
Anything with a bit depth of zero or greater than 32 is outside our
working range, so let's reject them.
2024-01-02 06:52:50 -07:00
Lucas CHOLLET
ba84af7c22 LibGfx/TIFF: Move check on tag values in its own function
There is only one check for now, but the fuzzer has already found more
checks to add :^)
2024-01-02 06:52:50 -07:00
Lucas CHOLLET
31b5f17f79 LibGfx/TIFF: Reject images with invalid StripByteCounts or StripOffsets
These two arrays should have the exact same size, files not respecting
this condition should be considered as invalid.
2023-12-30 23:24:05 +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
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