From b0c73d16521eaa59363ffe7d4857d10c70ff19c4 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Thu, 14 Mar 2024 21:43:11 -0400 Subject: [PATCH] LibGfx/JBIG2: Reject unimplemented combination operators In practice, everything uses white backgrounds and operators `or` or `xor` to turn them black, at least for the simple images we're about to be able to decode. To make sure we don't forget implementing this for real once needed, reject other ops, and also reject black backgrounds (because 1 | 0 is 1, not 0 like our overwrite implementation will produce). This means we have to remove a test, but since this scenario doesn't seem to happen in practice, that seems ok. --- Tests/LibGfx/TestImageDecoder.cpp | 11 ----------- .../Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp | 7 +++++++ 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/Tests/LibGfx/TestImageDecoder.cpp b/Tests/LibGfx/TestImageDecoder.cpp index 7588dadbd1f..423945d5283 100644 --- a/Tests/LibGfx/TestImageDecoder.cpp +++ b/Tests/LibGfx/TestImageDecoder.cpp @@ -325,17 +325,6 @@ TEST_CASE(test_jbig2_size) EXPECT_EQ(plugin_decoder->size(), Gfx::IntSize(399, 400)); } -TEST_CASE(test_jbig2_black_47x23) -{ - auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("jbig2/black_47x23.jbig2"sv))); - EXPECT(Gfx::JBIG2ImageDecoderPlugin::sniff(file->bytes())); - auto plugin_decoder = TRY_OR_FAIL(Gfx::JBIG2ImageDecoderPlugin::create(file->bytes())); - - auto frame = TRY_OR_FAIL(expect_single_frame_of_size(*plugin_decoder, { 47, 23 })); - for (auto pixel : *frame.image) - EXPECT_EQ(pixel, Gfx::Color(Gfx::Color::Black).value()); -} - TEST_CASE(test_jbig2_white_47x23) { auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("jbig2/white_47x23.jbig2"sv))); diff --git a/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp b/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp index d9eb1262451..d76eab5e5f7 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp @@ -846,6 +846,11 @@ static ErrorOr decode_immediate_generic_region(JBIG2LoadingContext& contex || information_field.y_location + information_field.height > (u32)context.page.size.height()) { return Error::from_string_literal("JBIG2ImageDecoderPlugin: Region bounds outsize of page bounds"); } + if (information_field.external_combination_operator() != RegionSegmentInformationField::CombinationOperator::Or + && information_field.external_combination_operator() != RegionSegmentInformationField::CombinationOperator::Xor + && information_field.external_combination_operator() != RegionSegmentInformationField::CombinationOperator::Replace) + return Error::from_string_literal("JBIG2ImageDecoderPlugin: Cannot handle external combination operator other than OR, XOR, and REPLACE yet"); + for (size_t y = 0; y < information_field.height; ++y) { for (size_t x = 0; x < information_field.width; ++x) { // FIXME: Honor segment's combination operator instead of just copying. @@ -904,6 +909,8 @@ static ErrorOr decode_page_information(JBIG2LoadingContext& context, Segme context.page.bits = TRY(BitBuffer::create(page_information.bitmap_width, height)); // "3) Fill the page buffer with the page's default pixel value." + if (default_color == 1) + return Error::from_string_literal("JBIG2ImageDecoderPlugin: Can only handle white default color for now"); context.page.bits->fill(default_color != 0); return {};