diff --git a/Tests/LibGfx/TestImageDecoder.cpp b/Tests/LibGfx/TestImageDecoder.cpp index 8bdcd69e5bfc1a..286e650fa83a32 100644 --- a/Tests/LibGfx/TestImageDecoder.cpp +++ b/Tests/LibGfx/TestImageDecoder.cpp @@ -353,6 +353,23 @@ TEST_CASE(test_jbig2_generic_region_arithmetic_code) EXPECT_EQ(frame.image->get_pixel(x, y), bmp_frame.image->get_pixel(x, y)); } +TEST_CASE(test_jbig2_generic_region_arithmetic_code_tpgdon) +{ + auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("jbig2/bitmap-tpgdon.jbig2"sv))); + EXPECT(Gfx::JBIG2ImageDecoderPlugin::sniff(file->bytes())); + auto plugin_decoder = TRY_OR_FAIL(Gfx::JBIG2ImageDecoderPlugin::create(file->bytes())); + + auto bmp_file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("bmp/bitmap.bmp"sv))); + auto bmp_plugin_decoder = TRY_OR_FAIL(Gfx::JBIG2ImageDecoderPlugin::create(file->bytes())); + + auto frame = TRY_OR_FAIL(expect_single_frame_of_size(*plugin_decoder, { 399, 400 })); + auto bmp_frame = TRY_OR_FAIL(expect_single_frame_of_size(*bmp_plugin_decoder, { 399, 400 })); + + for (int y = 0; y < frame.image->height(); ++y) + for (int x = 0; x < frame.image->width(); ++x) + EXPECT_EQ(frame.image->get_pixel(x, y), bmp_frame.image->get_pixel(x, y)); +} + TEST_CASE(test_jbig2_arithmetic_decoder) { // https://www.itu.int/rec/T-REC-T.88-201808-I diff --git a/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp b/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp index 7a59a07c15d9b5..5f398a061f4677 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp @@ -743,9 +743,6 @@ static ErrorOr> generic_region_decoding_procedure(Gener || inputs.adaptive_template_pixels[3].x != -2 || inputs.adaptive_template_pixels[3].y != -2) return Error::from_string_literal("JBIG2ImageDecoderPlugin: Cannot handle custom adaptive pixels yet"); - if (inputs.is_typical_prediction_used) - return Error::from_string_literal("JBIG2ImageDecoderPlugin: Cannot decode TPGDON yet"); - if (inputs.is_extended_reference_template_used) return Error::from_string_literal("JBIG2ImageDecoderPlugin: Cannot decode EXTTEMPLATE yet"); @@ -785,7 +782,23 @@ static ErrorOr> generic_region_decoding_procedure(Gener Vector contexts; contexts.resize(1 << 16); + // Figure 8 – Reused context for coding the SLTP value when GBTEMPLATE is 0 + constexpr u16 sltp_context_for_template_0 = 0b10011'0110010'0101; + + // 6.2.5.7 Decoding the bitmap + bool ltp = false; // "LTP" in spec. "Line (uses) Typical Prediction" maybe? for (size_t y = 0; y < inputs.region_height; ++y) { + if (inputs.is_typical_prediction_used) { + // "SLTP" in spec. "Swap LTP" or "Switch LTP" maybe? + bool sltp = decoder.get_next_bit(contexts[sltp_context_for_template_0]); + ltp = ltp ^ sltp; + if (ltp) { + for (size_t x = 0; x < inputs.region_width; ++x) + result->set_bit(x, y, get_pixel(result, (int)x, (int)y - 1)); + continue; + } + } + for (size_t x = 0; x < inputs.region_width; ++x) { u16 context = compute_context(result, x, y); bool bit = decoder.get_next_bit(contexts[context]);