From 3f9c5af5537b1d49bd09a4eee41c48724744a795 Mon Sep 17 00:00:00 2001 From: Lucas CHOLLET Date: Fri, 3 Mar 2023 23:45:47 -0500 Subject: [PATCH] LibGfx/JPEG: More support for scans with a single component Introduced in 2c98eff, support for non-interleaved scans was not working for frames with a number of MCU per line or column that is odd. Indeed, the decoder assumed that they have scans that include a fabricated MCU like scans with multiple components. This patch makes the decoder handle images with a number of MCU per line or column that is odd. To do so, as in the current decoder state we do not know if components are interleaved at allocation time, we skip over falsely-created macroblocks when filling them. As stated in 2c98eff, this is probably not a good solution and a whole refactor will be welcome. It also comes with a test that open a square image with a side of 600px, meaning 75 MCUs. --- Tests/LibGfx/TestImageDecoder.cpp | 11 +++++++++++ .../several_scans_odd_number_mcu.jpg | Bin 0 -> 12563 bytes .../LibGfx/ImageFormats/JPEGLoader.cpp | 14 +++++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 Tests/LibGfx/test-inputs/several_scans_odd_number_mcu.jpg diff --git a/Tests/LibGfx/TestImageDecoder.cpp b/Tests/LibGfx/TestImageDecoder.cpp index e75f0c8fa42..ce1ae607ca9 100644 --- a/Tests/LibGfx/TestImageDecoder.cpp +++ b/Tests/LibGfx/TestImageDecoder.cpp @@ -134,6 +134,17 @@ TEST_CASE(test_jpeg_sof2_spectral_selection) EXPECT_EQ(frame.image->size(), Gfx::IntSize(592, 800)); } +TEST_CASE(test_jpeg_sof0_several_scans_odd_number_mcu) +{ + auto file = MUST(Core::MappedFile::map(TEST_INPUT("several_scans_odd_number_mcu.jpg"sv))); + EXPECT(Gfx::JPEGImageDecoderPlugin::sniff(file->bytes())); + auto plugin_decoder = MUST(Gfx::JPEGImageDecoderPlugin::create(file->bytes())); + EXPECT(plugin_decoder->initialize()); + + auto frame = MUST(plugin_decoder->frame(0)); + EXPECT_EQ(frame.image->size(), Gfx::IntSize(600, 600)); +} + TEST_CASE(test_pbm) { auto file = MUST(Core::MappedFile::map(TEST_INPUT("buggie-raw.pbm"sv))); diff --git a/Tests/LibGfx/test-inputs/several_scans_odd_number_mcu.jpg b/Tests/LibGfx/test-inputs/several_scans_odd_number_mcu.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2e775e6b1c5af713f79abe43719003830e5264d6 GIT binary patch literal 12563 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 b0+z@V+}&`=MlXN-Ktb5Z5Tjv9Ccph3BXAS6 literal 0 HcmV?d00001 diff --git a/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp b/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp index 24ff7737100..c6f6a628e2c 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp @@ -446,9 +446,21 @@ static ErrorOr build_macroblocks(JPEGLoadingContext& context, Vector= context.mblock_meta.hcount && macroblock_index % context.mblock_meta.hpadded_count >= context.mblock_meta.hcount) + continue; + // Vertically + if (macroblock_index >= context.mblock_meta.hpadded_count * context.mblock_meta.vcount) + continue; + } + // G.1.2.2 - Progressive encoding of AC coefficients with Huffman coding if (context.current_scan.end_of_bands_run_count > 0) { --context.current_scan.end_of_bands_run_count;