From 2d4964b945079e84c34537d49e0fe8f95a399893 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Thu, 4 Apr 2024 13:23:12 -0700 Subject: [PATCH] LibGfx/JBIG2: Support custom adaptive template pixels in refinement The implementation is very similar to #23831. I created the test exactly like in #23713, except that I replaced the last four lines in the ini file with: ``` -txt -Param -rATX1 10 -txt -Param -rATY1 -1 -txt -Param -rATX2 4 -txt -Param -rATY2 15 ``` --- Tests/LibGfx/TestImageDecoder.cpp | 1 + .../bitmap-symbol-textrefine-customat.jbig2 | Bin 0 -> 422 bytes .../LibGfx/ImageFormats/JBIG2Loader.cpp | 27 +++++++++++------- 3 files changed, 17 insertions(+), 11 deletions(-) create mode 100644 Tests/LibGfx/test-inputs/jbig2/bitmap-symbol-textrefine-customat.jbig2 diff --git a/Tests/LibGfx/TestImageDecoder.cpp b/Tests/LibGfx/TestImageDecoder.cpp index f8f3e288b80..0e1fe96ebcb 100644 --- a/Tests/LibGfx/TestImageDecoder.cpp +++ b/Tests/LibGfx/TestImageDecoder.cpp @@ -365,6 +365,7 @@ TEST_CASE(test_jbig2_decode) TEST_INPUT("jbig2/bitmap-template3-customat-tpgdon.jbig2"sv), TEST_INPUT("jbig2/bitmap-symbol.jbig2"sv), TEST_INPUT("jbig2/bitmap-symbol-textrefine.jbig2"sv), + TEST_INPUT("jbig2/bitmap-symbol-textrefine-customat.jbig2"sv), TEST_INPUT("jbig2/bitmap-symbol-symbolrefine.jbig2"sv), TEST_INPUT("jbig2/bitmap-symbol-textbottomleft.jbig2"sv), TEST_INPUT("jbig2/bitmap-symbol-textbottomlefttranspose.jbig2"sv), diff --git a/Tests/LibGfx/test-inputs/jbig2/bitmap-symbol-textrefine-customat.jbig2 b/Tests/LibGfx/test-inputs/jbig2/bitmap-symbol-textrefine-customat.jbig2 new file mode 100644 index 0000000000000000000000000000000000000000..8c31e449ec29dc1ce9ca8dc449d45a633717ac1b GIT binary patch literal 422 zcmbR4y(#zzJQ=Kp{HGyVJbkAZ=K z8HD+oUQ5n9!}{??^2gZ+ckg6>7P*qK^NmAg_;ioR>q5SBP2TO8!)||e%}nl_U(#9K zW6z}S=eB!LWoJ;hNM3&RG2SoF@91W2d+c!RNyq=XS5vJI*(mPn|1!u``-yeGTp-XUXh~@OCqBzF< zNr79u>(+iy)7-G~Ovbl+0<0mb_vE%(e?71~{67N&0~5OfBgpd(=t0B4BgOTfg`a_e zfu;AJ>y+DftWxUJ|7{nyOuqc>)5Oy(Gpd*c7u>U*RT=Uz^V{k9AhVd&K|#qNi*6JX QJY3f>g4D4Xg4Hnq05WBqZU6uP literal 0 HcmV?d00001 diff --git a/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp b/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp index dfc952e25f0..fb66f0d8bba 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp @@ -1112,9 +1112,8 @@ static ErrorOr> generic_refinement_region_decoding_proc return Error::from_string_literal("JBIG2ImageDecoderPlugin: Cannot decode typical prediction in generic refinement regions yet"); if (inputs.gr_template == 0) { - if (inputs.adaptive_template_pixels[0].x != -1 || inputs.adaptive_template_pixels[0].y != -1 - || inputs.adaptive_template_pixels[1].x != -1 || inputs.adaptive_template_pixels[1].y != -1) - return Error::from_string_literal("JBIG2ImageDecoderPlugin: Cannot handle custom adaptive pixels in refinement regions yet"); + TRY(check_valid_adaptive_template_pixel(inputs.adaptive_template_pixels[0])); + // inputs.adaptive_template_pixels[1] is allowed to contain any value. } // GRTEMPLATE 1 never uses adaptive pixels. @@ -1126,22 +1125,28 @@ static ErrorOr> generic_refinement_region_decoding_proc }; // Figure 12 – 13-pixel refinement template showing the AT pixels at their nominal locations - constexpr auto compute_context_0 = [](BitBuffer const& reference, int reference_x, int reference_y, BitBuffer const& buffer, int x, int y) -> u16 { + constexpr auto compute_context_0 = [](ReadonlySpan adaptive_pixels, BitBuffer const& reference, int reference_x, int reference_y, BitBuffer const& buffer, int x, int y) -> u16 { u16 result = 0; - for (int dy = -1; dy <= 1; ++dy) - for (int dx = -1; dx <= 1; ++dx) - result = (result << 1) | (u16)get_pixel(reference, reference_x + dx, reference_y + dy); + for (int dy = -1; dy <= 1; ++dy) { + for (int dx = -1; dx <= 1; ++dx) { + if (dy == -1 && dx == -1) + result = (result << 1) | (u16)get_pixel(reference, reference_x + adaptive_pixels[1].x, reference_y + adaptive_pixels[1].y); + else + result = (result << 1) | (u16)get_pixel(reference, reference_x + dx, reference_y + dy); + } + } - for (int i = 0; i < 3; ++i) - result = (result << 1) | (u16)get_pixel(buffer, x - 1 + i, y - 1); + result = (result << 1) | (u16)get_pixel(buffer, x + adaptive_pixels[0].x, y + adaptive_pixels[0].y); + for (int i = 0; i < 2; ++i) + result = (result << 1) | (u16)get_pixel(buffer, x + i, y - 1); result = (result << 1) | (u16)get_pixel(buffer, x - 1, y); return result; }; // Figure 13 – 10-pixel refinement template - constexpr auto compute_context_1 = [](BitBuffer const& reference, int reference_x, int reference_y, BitBuffer const& buffer, int x, int y) -> u16 { + constexpr auto compute_context_1 = [](ReadonlySpan, BitBuffer const& reference, int reference_x, int reference_y, BitBuffer const& buffer, int x, int y) -> u16 { u16 result = 0; for (int dy = -1; dy <= 1; ++dy) { @@ -1165,7 +1170,7 @@ static ErrorOr> generic_refinement_region_decoding_proc auto result = TRY(BitBuffer::create(inputs.region_width, inputs.region_height)); for (size_t y = 0; y < result->height(); ++y) { for (size_t x = 0; x < result->width(); ++x) { - u16 context = compute_context(*inputs.reference_bitmap, x - inputs.reference_x_offset, y - inputs.reference_y_offset, *result, x, y); + u16 context = compute_context(inputs.adaptive_template_pixels, *inputs.reference_bitmap, x - inputs.reference_x_offset, y - inputs.reference_y_offset, *result, x, y); bool bit = decoder.get_next_bit(contexts[context]); result->set_bit(x, y, bit); }