1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 08:54:58 +00:00
Commit graph

522 commits

Author SHA1 Message Date
Nico Weber
df9dd8ec69 LibGfx/JBIG2: Add arithmetic coding decoder
I think the context normally changes for every bit. But this here
is enough to correctly decode the test bitstream in Annex H.2 in
the spec, which seems like a good checkpoint.

The internals of the decoder use spec naming, to make the code
look virtually identical to what's in the spec. (Even so, I managed
to put in several typos that took a while to track down.)
2024-03-14 18:18:15 -06:00
Lucas CHOLLET
06665cba9c LibGfx/TIFF: Reject images with an incoherent number of BitsPerSample
Fixes oss-fuzz issue 66588:
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=66588
2024-03-14 11:12:31 -04:00
Nico Weber
98729c97f4 LibGfx/JBIG2: Simplify and restrict adaptive template pixel reading
EXTTEMPLATE=1 was added later and doesn't seem to be used much in
practice -- it doesn't appear in no simple generic regions in any PDF
I tested so far at least. Since the spec contradicts itself on what
to do with these as far as I can tell, error out on them for now and
then add support once we find actual files using this, so that we can
check our implementation actually works.

Deduplicate the data reading for the different cases, and
zero-initialize all adaptive template pixels to zero to make that
possible.

Other than prohibiting EXTTEMPLATE=1, no behavior change.
2024-03-14 10:57:57 -04:00
Nico Weber
596b06333f LibGfx/JBIG2: Add a dbgln_if(JBIG2_DEBUG) for non-MMR generic regions 2024-03-14 10:57:57 -04:00
Nico Weber
7740aeca29 LibGfx/JBIG2: Fix size bound in scan_for_immediate_generic_region_size()
The memmem() call passes `data.size() - 19 - sizeof(u32)` for big_len,
(18 prefix bytes skipped, the flag byte, and the trailing u32), so the
buffer needs to be at least that large.

Should fix https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=67332
2024-03-13 22:01:06 -06:00
MacDue
4c15c87d0c LibGfx/TinyVG: Fix decoding green channel of graphics RGB565 colors
The division was missed here, so this would produce overly bright greens
(or overflow).
2024-03-12 21:53:23 +00:00
MacDue
633f0067c1 LibGfx: Remove suspicious const& in TinyVGLoader
`decode_color_table()` returns a vector by value (not reference), so
assigning it to a const reference (while legal), seems odd.
2024-03-12 21:53:23 +00:00
Nico Weber
bc42144642 LibGfx/JBIG2: Start implementing the generic region decoding procedure
If the "MMR" bit is set, the generic region decoding procedure just
uses ITU-T T.6 (2D CCITT), which we already have an implementation of.
In practice, this is used almost never in .jbig2 files and in none of
the PDFs I have.

The two files that do use MMR are:

1.) JBIG2_ConformanceData-A20180829/F01_200_TT9.jb2
2) 042_3.jb2 from the ghostpdl tests

The first uses an immediate _lossless_ generic region, which we don't
implement yet (but I think it should just forward to the normal
immediate generic region code? Not in this commit, though). The second
uses a regular immediate generic region, and we can decode it now:

    Build/lagom/bin/image -o out.png \
        path/to/ghostpdl/tests/jbig2/042_3.jb2
2024-03-11 16:48:57 +01:00
Nico Weber
e0af3ae8d9 LibGfx/JBIG2: Implement decode_end_of_file() 2024-03-11 16:48:57 +01:00
Nico Weber
323cacc593 LibGfx/JBIG2: Implement decode_end_of_page() 2024-03-11 16:48:57 +01:00
Nico Weber
bdbc21c52d LibGfx/JBIG2: Implement conversion to Gfx::Bitmap and ByteBuffer
With this, `image` can convert any jbig2 file, as long as it's
black (or white), and LibPDF can draw jbig2 files (again, as long
as they only contain a single color stored in just a
PageInformation segment).
2024-03-10 10:10:55 -04:00
Nico Weber
54982857bd LibGfx/JBIG2: Implement decode_page_information()
Also make scan_for_page_size() not early return, so that it has the
same behavior as the main decoding look. (Multiple page information
segments for a single page are likely invalid and don't happen in
practice, so this is mostly an academic change.)

Add a BitBuffer class to store the bit image data, and introduce a
Page struct for storing data associated with a page. We currently
only handle a single page, but a) this makes it easier to decode
multiple pages in the future if we want b) it makes the code easier
to understand.
2024-03-10 10:10:55 -04:00
Nico Weber
4b01f2f158 LibGfx/JBIG2: Implement decode_extension()
Only logs the data to dbgln().

All jb2 files in ghostpdl/tests start with this segment.
2024-03-10 10:10:55 -04:00
Nico Weber
9cd0c5658e LibGfx/JBIG2: Reject files with delayed height information for now
7.4.8.2 Page bitmap height:
"In some cases, this value may not be known at the time that the page
information segment is written. In this case, this field must contain
0xFFFFFFFF, and the actual page height may be communicated later, once
it is known."
2024-03-10 10:10:55 -04:00
Nico Weber
f592a2ac72 LibPDF/JBIG2: Print a warning on files with more than one page 2024-03-10 10:10:55 -04:00
Nico Weber
2caf603836 LibGfx/JBIG2: Add scaffolding for interpreting segment data 2024-03-10 10:10:55 -04:00
Nico Weber
af20ebe4a0 LibGfx/JBIG2: Scan for page size of page "1"
Sounds like the spec guarantees that that's the number of the first
page.

(In practice, all but one of all jbig2 files I've found contain just
page 1. PDFs almost always contain just page 1, and very rarely a
page 0 for globally shared parameters.)
2024-03-10 10:10:55 -04:00
Nico Weber
8f4930f2df LibGfx/JBIG2: Scan for the first PageInformation segment and decode it
This allows `file` to correctly print the dimensions of a .jbig2 file,
and it allows us to write a test that covers much of all the code
written so far.
2024-03-09 16:01:22 +01:00
Nico Weber
1eaaa8c3e9 LibPDF+LibGfx: Support JBIG2s with /JBIG2Globals set
Several ramifications:

* /JBIG2Globals is an indirect reference, which means we now need
  a Document for unfiltering. (Technically, other decode parameters
  can also be indirect objects and we should use the Document to
  resolve() those too, but in practice it only seems to be needed
  for /JBIG2Globals.)

* Since /JBIG2Globals are so rare, we just parse once for each
  image that use them, and decode_embedded() now receives a
  Vector<ReadonlyBytes> with all sections of sequences of
  segments.

* Internally, decode_segment_headers() is now called several times
  for embedded JBIG2s with multiple such sections (e.g. PDFs with
  /JBIG2Globals).

* That means `data` is now no longer part of JBIG2LoadingContext
  and things get slightly reshuffled due to this.

This completes the LibPDF part of JBIG2 support. Once LibGfx
implements actual decoding of JBIG2s, things should start to
Just Work in PDFs.
2024-03-09 16:01:22 +01:00
Nico Weber
09ca66cb8b LibGfx/JBIG2: Scan for end of immediate generic regions of unknown size
Found e.g. in 0000033.pdf (both pages).
2024-03-09 16:01:22 +01:00
Nico Weber
379ef45688 LibGfx/JBIG2: Store location of segment data bodies
They're in different places for Sequential/Embedded (right after
the header) and RandomAccess (which has all headers first, followed
by all data bits next).

We don't do anything with the data yet, but now everything's in
place to actually process segment data.
2024-03-09 16:01:22 +01:00
Nico Weber
953f6c5d9b LibPDF+LibGfx: Pass jbig2-filtered data to JBIG2ImageDecoderPlugin
Except for /JBIG2Globals, which we bail out on for now. In my 1000
files, 13 use JBIG2, and of those, 2 use JBIG2Globals (0000372.pdf e.g.
page 11 and 0000857.pdf e.g. page 1), and only one (the latter) of the
two uses the same JBIG2Globals stream for more than a single image.

JBIG2ImageDecoderPlugin cannot decode the data yet, so no behavior
change, but with `#define JBIG2_DEBUG 1` at the top of that file,
it now prints segment header info for PDFs containing JBIG2 data :^)
2024-03-09 16:01:22 +01:00
Nico Weber
b1fdc33a22 LibGfx/JBIG2: Decode all segment headers
With `#define JBIG2_DEBUG 1` at the top of the file:

    % Build/lagom/bin/image --no-output \
       .../JBIG2_ConformanceData-A20180829/F01_200_TT10.jb2
    JBIG2LoadingContext: Organization: 0 (Sequential)
    JBIG2LoadingContext: Number of pages: 1
    Segment number: 0
    Segment type: 48
    Referred to segment count: 0
    Segment page association: 1
    Segment data length: 19
    Segment number: 1
    Segment type: 39
    Referred to segment count: 0
    Segment page association: 1
    Segment data length: 12666
    Segment number: 2
    Segment type: 49
    Referred to segment count: 0
    Segment page association: 1
    Segment data length: 0
    Runtime error: JBIG2ImageDecoderPlugin: Draw the rest of the owl
2024-03-09 16:01:22 +01:00
Nico Weber
177664cfae LibGfx/JBIG2: Add an initial decode_segment_header()
With `#define JBIG2_DEBUG 1` at the top of the file:

    % Build/lagom/bin/image --no-output \
        .../JBIG2_ConformanceData-A20180829/F01_200_TT10.jb2
    JBIG2LoadingContext: Organization: 0 (Sequential)
    JBIG2LoadingContext: Number of pages: 1
    Segment number: 0
    Segment type: 48
    Referred to segment count: 0
    Segment page association: 1
    Segment data length: 19
    Runtime error: JBIG2ImageDecoderPlugin: Draw the rest of the owl
2024-03-09 16:01:22 +01:00
Nico Weber
5cefcad2fe LibGfx/JBIG2: Decode the file header
Running `image` with `#define JBIG2_DEBUG 1` now prints number of pages.
2024-03-09 16:01:22 +01:00
Nico Weber
58838db445 LibGfx: Add the start of a JBIG2 loader
JBIG2 is infamous for two things:

1. It's used in xerox scanners were it falsifies scanned numbers:

https://www.dkriesel.com/en/blog/2013/0802_xerox-workcentres_are_switching_written_numbers_when_scanning

2. It was allegedly used in an iOS zero day, in a very cool way:

https://googleprojectzero.blogspot.com/2021/12/a-deep-dive-into-nso-zero-click.html

Needless to say, we need support for it in Serenity. (...because it's
used in PDF files.)

This adds all the scaffolding, but no actual implementation yet.

It's enough for `file` to print the mime type of .jb2 files, but `image`
can't do anything with the files yet.
2024-03-09 16:01:22 +01:00
Nico Weber
75a8d37c99 LibGfx: Make mime-based image loaders not throw away their error either
Small follow-up to #23489.
2024-03-08 08:38:31 +01:00
Nico Weber
8ec6dad449 LibGfx/TGA: Move a variable closer to its use
No behavior change.
2024-03-08 08:38:31 +01:00
Nico Weber
6607757b08 LibGfx: Make validate_before_create() create a regular bool
This is for validating that a decoder with a weak or nonexistent
sniff() method thinks it can decode an image. This should not be
treated as an error.

No behavior change.
2024-03-08 08:38:31 +01:00
Lucas CHOLLET
40cf205c81 LibGfx/TIFF: Reject images with a null value in tile's dimensions
Fixes oss-fuzz issue 66844.
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=66844&sort=-opened&q=proj%3Aserenity%20TIFF&can=1
2024-03-07 11:31:38 -05:00
Nico Weber
2e2cae26c6 LibGfx+Fallout: Make ImageDecoder return ErrorOr
...from try_create_for_raw_bytes().

If a plugin returns `true` from sniff but then fails when calling
its `create()` method, we now no longer swallow that error.

Allows `image` (and other places in the system) to print a more
actionable error if early image headers are invalid.

(We now no longer try to find another plugin that can also handle
the image.)

Fixes a regression from #20063 / #19893 -- before then, we didn't
do fallible work this early.
2024-03-07 11:20:06 -05:00
Lucas CHOLLET
be5e7a360f LibGfx/CCITT: Add support for images with an unknown number of lines 2024-03-07 11:07:20 -05:00
Lucas CHOLLET
cefb2d65d8 LibGfx/CCITT: Always accept the end of line as the next changing element 2024-03-07 11:07:20 -05:00
Lucas CHOLLET
780e230af5 LibGfx/CCITT: Don't use change's color to set current_color
No behavior change, `to_encode` always receive a `Change` with a
different color.
2024-03-07 11:07:20 -05:00
Nico Weber
ab143e9b0e LibGfx/BMP: Clear alpha in palette entries
The semantics of BGRx8888 aren't super clear and it means different
things for different parts of the codebase. In particular, the PNG
writer still writes the x channel to the alpha channel of its output.

In BMPs, the 4th palette byte is usually 0, which means after #21412 we
started writing all .bmp files with <= 8bpp as completely transparent
to PNGs.

This works around that.

(See also #19464 for previous similar workarounds.)

The added `bitmap.bmp` is a 1bpp file I drew in Photoshop and saved
using its "Save as..." saving path.
2024-03-05 21:27:41 +00:00
Lucas CHOLLET
fb81668d8f LibGfx/JPEGLoader: Check earlier for quantization tables presence
This patch brings few small QoL improvements:
 - We don't need to read the Huffman stream before returning an error
   due to a missing quantization table.
 - We check the table presence only once per scan instead of once per
   MCU.
 - `dequantize()` is now infallible.
2024-02-26 20:13:25 +00:00
Lucas CHOLLET
83f1775f15 LibGfx/CCITT: Reimplement PassMode in a less naive way
The old implementation of PassMode has only been tested with a single
image, and let's say that it didn't survive long in the wild. A few
cases were not considered:
 - We only supported VerticalMode right after PassMode.
 - It can happen that token need to be used but not consumed from the
 reference line.

 With that fix, we are able to decode every single PDF file from the
 1000-file zip "0000" (except 0000871.pdf, which uses byte alignment).
 This is massive progress compared to the hundred of errors that we were
 previously receiving.
2024-02-22 16:45:03 +01:00
Nico Weber
607880cbd3 LibGfx/JPEGLoader: Add dbgln_if() when hitting unsupported marker 2024-02-21 17:54:53 +01:00
Nico Weber
95391fafcb LibGfx/JPEGLoader: Print offset in an error dbgln() in hex 2024-02-21 17:54:53 +01:00
Nico Weber
24a469f521 Everywhere: Prefer {:#x} over 0x{:x} in format strings
The former automatically adapts the prefix to binary and octal
output, and is what we already use in the majority of cases.

Patch generated by:

    rg -l '0x\{' | xargs sed -i '' -e 's/0x{:/{:#/'

I ran it 4 times (until it stopped changing things) since each
invocation only converted one instance per line.

No behavior change.
2024-02-21 17:54:38 +01:00
Lucas CHOLLET
9ec3480207 LibGfx/TIFF: Add support for Group4Fax encoded images
Note that we don't parse the T6 option group yet.

The test case was generated with GIMP.
2024-02-21 13:49:43 +01:00
Lucas CHOLLET
d57d676425 LibGfx/CCITT: Add support for Group4
The API is currently pretty raw. Group4 has a bunch of options that we
don't support yet.
2024-02-21 13:49:43 +01:00
Lucas CHOLLET
e9dd1cda3e LibGfx/CCITT: Abstract the code to read a single CCITT 2D line 2024-02-21 13:49:43 +01:00
Lucas CHOLLET
be9ec591e7 LibGfx/CCITT: Add support for Group3 2D
The two test images were created with:
tiffcp ccit3.tiff -c g3:2d ccit3_2d.tiff
tiffcp ccit3.tiff -c g3:2d:fill ccit3_2d_fill.tiff
2024-02-19 01:40:04 +01:00
Lucas CHOLLET
9116cc3f45 LibGfx/CCITT: Put the code to read the run length in its own function
This is already nice to do for the sole purpose of the readability but
that will also become handy for the 2D decoder.
2024-02-19 01:40:04 +01:00
Lucas CHOLLET
3d63dd5c53 LibGfx/CCITT: Make get_code_from_table take a generic Array 2024-02-19 01:40:04 +01:00
Lucas CHOLLET
d54dbdae5e LibGfx/CCITT: Introduce the invert helper
This function turns Black into White and White into Black.
2024-02-19 01:40:04 +01:00
Lucas CHOLLET
ce0ac70416 LibGfx/CCITT: Declare reference colors as static variables 2024-02-19 01:40:04 +01:00
Lucas CHOLLET
45b37010b5 Revert "LibGfx/CCITT: Don't overrun the image width"
This reverts commit a4b2e5b27b.

This was just plain wrong, I remember it making sense and fixing
something but that was probably due to local changes. It should never
have landed on master, my bad.
2024-02-19 01:40:04 +01:00
Lucas CHOLLET
d375b5c2a5 LibGfx/TIFF: Also cache the result of alpha_channel_index()
This function was called over and over in `manage_extra_channels()`,
even if the result depends only on the metadata. Instead, we now call it
once and store the result.
2024-02-18 21:53:27 +01:00