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 e75f0c8fa4..ce1ae607ca 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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 literal 0 HcmV?d00001 diff --git a/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp b/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp index 24ff773710..c6f6a628e2 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;