diff --git a/Tests/LibGfx/TestImageDecoder.cpp b/Tests/LibGfx/TestImageDecoder.cpp index da4b3381871..01e6c3bcd57 100644 --- a/Tests/LibGfx/TestImageDecoder.cpp +++ b/Tests/LibGfx/TestImageDecoder.cpp @@ -325,6 +325,28 @@ TEST_CASE(test_jbig2_size) EXPECT_EQ(plugin_decoder->size(), Gfx::IntSize(399, 400)); } +TEST_CASE(test_jbig2_black_47x23) +{ + auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("jbig2/black_47x23.jbig2"sv))); + EXPECT(Gfx::JBIG2ImageDecoderPlugin::sniff(file->bytes())); + auto plugin_decoder = TRY_OR_FAIL(Gfx::JBIG2ImageDecoderPlugin::create(file->bytes())); + + auto frame = TRY_OR_FAIL(expect_single_frame_of_size(*plugin_decoder, { 47, 23 })); + for (auto pixel : *frame.image) + EXPECT_EQ(pixel, Gfx::Color(Gfx::Color::Black).value()); +} + +TEST_CASE(test_jbig2_white_47x23) +{ + auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("jbig2/white_47x23.jbig2"sv))); + EXPECT(Gfx::JBIG2ImageDecoderPlugin::sniff(file->bytes())); + auto plugin_decoder = TRY_OR_FAIL(Gfx::JBIG2ImageDecoderPlugin::create(file->bytes())); + + auto frame = TRY_OR_FAIL(expect_single_frame_of_size(*plugin_decoder, { 47, 23 })); + for (auto pixel : *frame.image) + EXPECT_EQ(pixel, Gfx::Color(Gfx::Color::White).value()); +} + 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 889df0628dd..3a314ac5a54 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/JBIG2Loader.cpp @@ -80,10 +80,13 @@ public: void set_bit(size_t x, size_t y, bool b); void fill(bool b); -private: - BitBuffer(Vector, size_t width, size_t height, size_t pitch); + ErrorOr> to_gfx_bitmap() const; + ErrorOr to_byte_buffer() const; - Vector m_bits; +private: + BitBuffer(ByteBuffer, size_t width, size_t height, size_t pitch); + + ByteBuffer m_bits; size_t m_width; size_t m_height; size_t m_pitch; @@ -92,8 +95,7 @@ private: ErrorOr> BitBuffer::create(size_t width, size_t height) { size_t pitch = ceil_div(width, 8ull); - Vector bits; - TRY(bits.try_resize(pitch * height)); + auto bits = TRY(ByteBuffer::create_uninitialized(pitch * height)); return adopt_nonnull_own_or_enomem(new (nothrow) BitBuffer(move(bits), width, height, pitch)); } @@ -126,11 +128,28 @@ void BitBuffer::set_bit(size_t x, size_t y, bool b) void BitBuffer::fill(bool b) { u8 fill_byte = b ? 0xff : 0; - for (auto& byte : m_bits) + for (auto& byte : m_bits.bytes()) byte = fill_byte; } -BitBuffer::BitBuffer(Vector bits, size_t width, size_t height, size_t pitch) +ErrorOr> BitBuffer::to_gfx_bitmap() const +{ + auto bitmap = TRY(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, { m_width, m_height })); + for (size_t y = 0; y < m_height; ++y) { + for (size_t x = 0; x < m_width; ++x) { + auto color = get_bit(x, y) ? Color::Black : Color::White; + bitmap->set_pixel(x, y, color); + } + } + return bitmap; +} + +ErrorOr BitBuffer::to_byte_buffer() const +{ + return ByteBuffer::copy(m_bits); +} + +BitBuffer::BitBuffer(ByteBuffer bits, size_t width, size_t height, size_t pitch) : m_bits(move(bits)) , m_width(width) , m_height(height) @@ -748,7 +767,8 @@ ErrorOr JBIG2ImageDecoderPlugin::frame(size_t index, Optio m_context->state = JBIG2LoadingContext::State::Decoded; } - return Error::from_string_literal("JBIG2ImageDecoderPlugin: Draw the rest of the owl"); + auto bitmap = TRY(m_context->page.bits->to_gfx_bitmap()); + return ImageFrameDescriptor { move(bitmap), 0 }; } ErrorOr JBIG2ImageDecoderPlugin::decode_embedded(Vector data) @@ -762,7 +782,7 @@ ErrorOr JBIG2ImageDecoderPlugin::decode_embedded(Vectorm_context)); TRY(decode_data(*plugin->m_context)); - return Error::from_string_literal("JBIG2ImageDecoderPlugin: Cannot decode embedded JBIG2 yet"); + return plugin->m_context->page.bits->to_byte_buffer(); } }