LibGfx/JBIG2: Implement support for TPGDON

This commit is contained in:
Nico Weber 2024-03-14 22:32:18 -04:00 committed by Andreas Kling
parent edec2b9baa
commit 7650e657aa
2 changed files with 33 additions and 3 deletions

View file

@ -353,6 +353,23 @@ TEST_CASE(test_jbig2_generic_region_arithmetic_code)
EXPECT_EQ(frame.image->get_pixel(x, y), bmp_frame.image->get_pixel(x, y));
}
TEST_CASE(test_jbig2_generic_region_arithmetic_code_tpgdon)
{
auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("jbig2/bitmap-tpgdon.jbig2"sv)));
EXPECT(Gfx::JBIG2ImageDecoderPlugin::sniff(file->bytes()));
auto plugin_decoder = TRY_OR_FAIL(Gfx::JBIG2ImageDecoderPlugin::create(file->bytes()));
auto bmp_file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("bmp/bitmap.bmp"sv)));
auto bmp_plugin_decoder = TRY_OR_FAIL(Gfx::JBIG2ImageDecoderPlugin::create(file->bytes()));
auto frame = TRY_OR_FAIL(expect_single_frame_of_size(*plugin_decoder, { 399, 400 }));
auto bmp_frame = TRY_OR_FAIL(expect_single_frame_of_size(*bmp_plugin_decoder, { 399, 400 }));
for (int y = 0; y < frame.image->height(); ++y)
for (int x = 0; x < frame.image->width(); ++x)
EXPECT_EQ(frame.image->get_pixel(x, y), bmp_frame.image->get_pixel(x, y));
}
TEST_CASE(test_jbig2_arithmetic_decoder)
{
// https://www.itu.int/rec/T-REC-T.88-201808-I

View file

@ -743,9 +743,6 @@ static ErrorOr<NonnullOwnPtr<BitBuffer>> generic_region_decoding_procedure(Gener
|| inputs.adaptive_template_pixels[3].x != -2 || inputs.adaptive_template_pixels[3].y != -2)
return Error::from_string_literal("JBIG2ImageDecoderPlugin: Cannot handle custom adaptive pixels yet");
if (inputs.is_typical_prediction_used)
return Error::from_string_literal("JBIG2ImageDecoderPlugin: Cannot decode TPGDON yet");
if (inputs.is_extended_reference_template_used)
return Error::from_string_literal("JBIG2ImageDecoderPlugin: Cannot decode EXTTEMPLATE yet");
@ -785,7 +782,23 @@ static ErrorOr<NonnullOwnPtr<BitBuffer>> generic_region_decoding_procedure(Gener
Vector<JBIG2::ArithmeticDecoder::Context> contexts;
contexts.resize(1 << 16);
// Figure 8 Reused context for coding the SLTP value when GBTEMPLATE is 0
constexpr u16 sltp_context_for_template_0 = 0b10011'0110010'0101;
// 6.2.5.7 Decoding the bitmap
bool ltp = false; // "LTP" in spec. "Line (uses) Typical Prediction" maybe?
for (size_t y = 0; y < inputs.region_height; ++y) {
if (inputs.is_typical_prediction_used) {
// "SLTP" in spec. "Swap LTP" or "Switch LTP" maybe?
bool sltp = decoder.get_next_bit(contexts[sltp_context_for_template_0]);
ltp = ltp ^ sltp;
if (ltp) {
for (size_t x = 0; x < inputs.region_width; ++x)
result->set_bit(x, y, get_pixel(result, (int)x, (int)y - 1));
continue;
}
}
for (size_t x = 0; x < inputs.region_width; ++x) {
u16 context = compute_context(result, x, y);
bool bit = decoder.get_next_bit(contexts[context]);