diff --git a/Tests/LibGfx/TestImageDecoder.cpp b/Tests/LibGfx/TestImageDecoder.cpp index 8db8b059fb..da4b338187 100644 --- a/Tests/LibGfx/TestImageDecoder.cpp +++ b/Tests/LibGfx/TestImageDecoder.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -316,6 +317,14 @@ TEST_CASE(test_ilbm_malformed_frame) } } +TEST_CASE(test_jbig2_size) +{ + auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("jbig2/bitmap.jbig2"sv))); + EXPECT(Gfx::JBIG2ImageDecoderPlugin::sniff(file->bytes())); + auto plugin_decoder = TRY_OR_FAIL(Gfx::JBIG2ImageDecoderPlugin::create(file->bytes())); + EXPECT_EQ(plugin_decoder->size(), Gfx::IntSize(399, 400)); +} + TEST_CASE(test_jpeg_sof0_one_scan) { auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("jpg/rgb24.jpg"sv))); diff --git a/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp b/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp index 17c988843d..72e1157e91 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp @@ -266,6 +266,38 @@ static ErrorOr decode_segment_headers(JBIG2LoadingContext& context, Readon return {}; } +// 7.4.8 Page information segment syntax +struct [[gnu::packed]] PageInformationSegment { + BigEndian bitmap_width; + BigEndian bitmap_height; + BigEndian page_x_resolution; // In pixels/meter. + BigEndian page_y_resolution; // In pixels/meter. + u8 flags; + BigEndian striping_information; +}; +static_assert(AssertSize()); + +static ErrorOr decode_page_information_segment(ReadonlyBytes data) +{ + // 7.4.8 Page information segment syntax + if (data.size() != sizeof(PageInformationSegment)) + return Error::from_string_literal("JBIG2ImageDecoderPlugin: Invalid page information segment size"); + return *(PageInformationSegment const*)data.data(); +} + +static ErrorOr scan_for_page_size(JBIG2LoadingContext& context) +{ + // We only decode the first page at the moment. + for (auto const& segment : context.segments) { + if (segment.header.type != SegmentType::PageInformation) + continue; + auto page_information = TRY(decode_page_information_segment(segment.data)); + context.size = { page_information.bitmap_width, page_information.bitmap_height }; + return {}; + } + return Error::from_string_literal("JBIG2ImageDecoderPlugin: No page information segment found"); +} + JBIG2ImageDecoderPlugin::JBIG2ImageDecoderPlugin() { m_context = make(); @@ -289,6 +321,8 @@ ErrorOr> JBIG2ImageDecoderPlugin::create(Reado data = data.slice(sizeof(id_string) + sizeof(u8) + (plugin->m_context->number_of_pages.has_value() ? sizeof(u32) : 0)); TRY(decode_segment_headers(*plugin->m_context, data)); + TRY(scan_for_page_size(*plugin->m_context)); + return plugin; } @@ -312,6 +346,8 @@ ErrorOr JBIG2ImageDecoderPlugin::decode_embedded(Vectorm_context, segment_data)); + TRY(scan_for_page_size(*plugin->m_context)); + return Error::from_string_literal("JBIG2ImageDecoderPlugin: Cannot decode embedded JBIG2 yet"); }