diff --git a/Tests/LibGfx/TestImageDecoder.cpp b/Tests/LibGfx/TestImageDecoder.cpp index f2995627ea23a1..87f8698d166eb9 100644 --- a/Tests/LibGfx/TestImageDecoder.cpp +++ b/Tests/LibGfx/TestImageDecoder.cpp @@ -422,7 +422,9 @@ TEST_CASE(test_jbig2_decode) TEST_INPUT("jbig2/bitmap-symbol-symhuffrefineone.jbig2"sv), TEST_INPUT("jbig2/bitmap-symbol-symhuffrefineseveral.jbig2"sv), TEST_INPUT("jbig2/bitmap-symbol-symbolrefine-textrefine.jbig2"sv), + TEST_INPUT("jbig2/bitmap-symbol-symbolrefine-textrefine-export.jbig2"sv), TEST_INPUT("jbig2/bitmap-symbol-symhuffrefine-textrefine.jbig2"sv), + TEST_INPUT("jbig2/bitmap-symbol-symhuffrefine-textrefine-export.jbig2"sv), TEST_INPUT("jbig2/bitmap-symbol-textbottomleft.jbig2"sv), TEST_INPUT("jbig2/bitmap-symbol-textbottomlefttranspose.jbig2"sv), TEST_INPUT("jbig2/bitmap-symbol-textbottomright.jbig2"sv), diff --git a/Tests/LibGfx/test-inputs/jbig2/bitmap-symbol-symbolrefine-textrefine-export.jbig2 b/Tests/LibGfx/test-inputs/jbig2/bitmap-symbol-symbolrefine-textrefine-export.jbig2 new file mode 100644 index 00000000000000..18379de86a7c5e Binary files /dev/null and b/Tests/LibGfx/test-inputs/jbig2/bitmap-symbol-symbolrefine-textrefine-export.jbig2 differ diff --git a/Tests/LibGfx/test-inputs/jbig2/bitmap-symbol-symhuffrefine-textrefine-export.jbig2 b/Tests/LibGfx/test-inputs/jbig2/bitmap-symbol-symhuffrefine-textrefine-export.jbig2 new file mode 100644 index 00000000000000..ec074124bab498 Binary files /dev/null and b/Tests/LibGfx/test-inputs/jbig2/bitmap-symbol-symhuffrefine-textrefine-export.jbig2 differ diff --git a/Tests/LibGfx/test-inputs/jbig2/json/bitmap-symbol-symbolrefine-textrefine-export.json b/Tests/LibGfx/test-inputs/jbig2/json/bitmap-symbol-symbolrefine-textrefine-export.json new file mode 100644 index 00000000000000..24f0cbd046b9a3 --- /dev/null +++ b/Tests/LibGfx/test-inputs/jbig2/json/bitmap-symbol-symbolrefine-textrefine-export.json @@ -0,0 +1,374 @@ +{ + "global_header": { + "organization": "sequential", + "number_of_pages": 1 + }, + "segments": [ + { + "segment_number": 0, + "type": "page_information", + "page_association": 1, + "data": { + "page_width": 399, + "page_height": 400, + "flags": { + "is_eventually_lossless": true + } + } + }, + + { + "segment_number": 1, + "type": "symbol_dictionary", + "page_association": 1, + "retained": true, + "data": { + "flags": { + "uses_huffman_encoding": false, + "uses_refinement_or_aggregate_coding": false, + "huffman_table_selection_for_height_differences": 0, + "huffman_table_selection_for_width_differences": 0, + "huffman_table_selection_for_bitmap_sizes": 0, + "huffman_table_selection_for_number_of_symbol_instances": 0, + "is_bitmap_coding_context_used": false, + "is_bitmap_coding_context_retained": false, + "template": 0, + "refinement_template": 0 + }, + + "height_classes": [ + { + "symbols": [ + { + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 60, + "y": 265, + "width": 30, + "height": 30 + } + } + }, + { + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 50, + "y": 108, + "width": 30, + "height": 30 + } + } + } + ] + }, + { + "symbols": [ + { + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 50, + "y": 108, + "width": 40, + "height": 40 + } + } + }, + { + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 135, + "y": 160, + "width": 60, + "height": 40 + } + } + } + ] + }, + { + "symbols": [ + { + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 195, + "y": 100, + "width": 40, + "height": 60 + } + } + }, + { + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 0, + "y": 0, + "width": 59, + "height": 60 + } + } + } + ] + }, + { + "symbols": [ + { + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 232, + "y": 70, + "width": 120, + "height": 250 + } + } + } + ] + } + ] + } + }, + + { + "segment_number": 2, + "type": "symbol_dictionary", + "page_association": 1, + "retained": true, + "referred_to_segments": [ + { + "segment_number": 1, + "retained": false + } + ], + "data": { + "flags": { + "uses_huffman_encoding": false, + "uses_refinement_or_aggregate_coding": true, + "huffman_table_selection_for_height_differences": 0, + "huffman_table_selection_for_width_differences": 0, + "huffman_table_selection_for_bitmap_sizes": 0, + "huffman_table_selection_for_number_of_symbol_instances": 0, + "is_bitmap_coding_context_used": false, + "is_bitmap_coding_context_retained": false, + "template": 0, + "refinement_template": 0 + }, + + "export_flags_for_referred_to_symbols": [ true, true, false, false, false, false, true ], + + "height_classes": [ + { + "symbols": [ + { + "exported": false, + "refines_symbol_to": { + "symbol_id": 5, + "delta_x_offset": 0, + "delta_y_offset": 0, + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 146, + "y": 100, + "width": 59, + "height": 60 + } + } + } + }, + { + "exported": false, + "width": 99, + "height": 60, + "refines_using_strips": { + "initial_strip_t": -1, + "strips": [ + { + "strip_t": 0, + "instances": [ + { + "instance_s": 0, + "instance_t": 0, + "symbol_id": 7 + }, + { + "instance_s": 60, + "instance_t": 0, + "symbol_id": 4 + } + ] + } + ] + } + }, + { + "exported": false, + "refines_symbol_to": { + "symbol_id": 8, + "delta_x_offset": 0, + "delta_y_offset": 0, + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 136, + "y": 100, + "width": 99, + "height": 60 + } + } + } + } + ] + }, + { + "symbols": [ + { + "width": 100, + "height": 100, + "refines_using_strips": { + "initial_strip_t": -1, + "strips": [ + { + "strip_t": 0, + "instances": [ + { + "instance_s": 1, + "instance_t": 0, + "symbol_id": 9 + } + ] + }, + { + "strip_t": 60, + "instances": [ + { + "instance_s": 0, + "instance_t": 60, + "symbol_id": 3 + }, + { + "instance_s": 60, + "instance_t": 60, + "symbol_id": 2 + } + ] + } + ] + } + } + ] + } + ] + } + }, + + { + "segment_number": 3, + "type": "text_region", + "page_association": 1, + "referred_to_segments": [ + { + "segment_number": 2, + "retained": false + } + ], + "data": { + "region_segment_information": { + "width": 399, + "height": 400 + }, + "flags": { + "uses_huffman_encoding": false, + "uses_refinement_coding": true, + "strip_size": 2, + "reference_corner": "top_left", + "is_transposed": false, + "combination_operator": "xor", + "default_pixel_value": "white", + "delta_s_offset": 3, + "refinement_template": 0 + }, + "huffman_flags": { + "huffman_table_selection_for_first_s": 0, + "huffman_table_selection_for_subsequent_s": 0, + "huffman_table_selection_for_t": 0, + "huffman_table_selection_for_refinement_delta_width": 0, + "huffman_table_selection_for_refinement_delta_height": 0, + "huffman_table_selection_for_refinement_delta_x_offset": 0, + "huffman_table_selection_for_refinement_delta_y_offset": 0, + "huffman_table_selection_for_refinement_size_table": 0 + }, + + "initial_strip_t": -4, + "strips": [ + { + "strip_t": 70, + "instances": [ + { + "instance_s": 232, + "instance_t": 70, + "symbol_id": 2 + } + ] + }, + { + "strip_t": 100, + "instances": [ + { + "instance_s": 135, + "instance_t": 100, + "symbol_id": 3, + "instance_refines_symbol_to": { + "delta_width": 0, + "delta_height": 0, + "delta_x_offset": 0, + "delta_y_offset": 0, + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 135, + "y": 100, + "width": 100, + "height": 100 + } + } + } + } + ] + }, + { + "strip_t": 108, + "instances": [ + { + "instance_s": 50, + "instance_t": 108, + "symbol_id": 1 + } + ] + }, + { + "strip_t": 264, + "instances": [ + { + "instance_s": 60, + "instance_t": 265, + "symbol_id": 0 + } + ] + } + ] + } + }, + + { + "segment_number": 4, + "type": "end_of_page", + "page_association": 1 + } + ] +} diff --git a/Tests/LibGfx/test-inputs/jbig2/json/bitmap-symbol-symhuffrefine-textrefine-export.json b/Tests/LibGfx/test-inputs/jbig2/json/bitmap-symbol-symhuffrefine-textrefine-export.json new file mode 100644 index 00000000000000..6d09c2460ddefb --- /dev/null +++ b/Tests/LibGfx/test-inputs/jbig2/json/bitmap-symbol-symhuffrefine-textrefine-export.json @@ -0,0 +1,374 @@ +{ + "global_header": { + "organization": "sequential", + "number_of_pages": 1 + }, + "segments": [ + { + "segment_number": 0, + "type": "page_information", + "page_association": 1, + "data": { + "page_width": 399, + "page_height": 400, + "flags": { + "is_eventually_lossless": true + } + } + }, + + { + "segment_number": 1, + "type": "symbol_dictionary", + "page_association": 1, + "retained": true, + "data": { + "flags": { + "uses_huffman_encoding": true, + "uses_refinement_or_aggregate_coding": false, + "huffman_table_selection_for_height_differences": 0, + "huffman_table_selection_for_width_differences": 0, + "huffman_table_selection_for_bitmap_sizes": 0, + "huffman_table_selection_for_number_of_symbol_instances": 0, + "is_bitmap_coding_context_used": false, + "is_bitmap_coding_context_retained": false, + "template": 0, + "refinement_template": 0 + }, + + "height_classes": [ + { + "symbols": [ + { + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 60, + "y": 265, + "width": 30, + "height": 30 + } + } + }, + { + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 50, + "y": 108, + "width": 30, + "height": 30 + } + } + } + ] + }, + { + "symbols": [ + { + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 50, + "y": 108, + "width": 40, + "height": 40 + } + } + }, + { + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 135, + "y": 160, + "width": 60, + "height": 40 + } + } + } + ] + }, + { + "symbols": [ + { + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 195, + "y": 100, + "width": 40, + "height": 60 + } + } + }, + { + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 0, + "y": 0, + "width": 59, + "height": 60 + } + } + } + ] + }, + { + "symbols": [ + { + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 232, + "y": 70, + "width": 120, + "height": 250 + } + } + } + ] + } + ] + } + }, + + { + "segment_number": 2, + "type": "symbol_dictionary", + "page_association": 1, + "retained": true, + "referred_to_segments": [ + { + "segment_number": 1, + "retained": false + } + ], + "data": { + "flags": { + "uses_huffman_encoding": true, + "uses_refinement_or_aggregate_coding": true, + "huffman_table_selection_for_height_differences": 0, + "huffman_table_selection_for_width_differences": 0, + "huffman_table_selection_for_bitmap_sizes": 0, + "huffman_table_selection_for_number_of_symbol_instances": 0, + "is_bitmap_coding_context_used": false, + "is_bitmap_coding_context_retained": false, + "template": 0, + "refinement_template": 0 + }, + + "export_flags_for_referred_to_symbols": [ true, true, false, false, false, false, true ], + + "height_classes": [ + { + "symbols": [ + { + "exported": false, + "refines_symbol_to": { + "symbol_id": 5, + "delta_x_offset": 0, + "delta_y_offset": 0, + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 146, + "y": 100, + "width": 59, + "height": 60 + } + } + } + }, + { + "exported": false, + "width": 99, + "height": 60, + "refines_using_strips": { + "initial_strip_t": -1, + "strips": [ + { + "strip_t": 0, + "instances": [ + { + "instance_s": 0, + "instance_t": 0, + "symbol_id": 7 + }, + { + "instance_s": 60, + "instance_t": 0, + "symbol_id": 4 + } + ] + } + ] + } + }, + { + "exported": false, + "refines_symbol_to": { + "symbol_id": 8, + "delta_x_offset": 0, + "delta_y_offset": 0, + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 136, + "y": 100, + "width": 99, + "height": 60 + } + } + } + } + ] + }, + { + "symbols": [ + { + "width": 100, + "height": 100, + "refines_using_strips": { + "initial_strip_t": -1, + "strips": [ + { + "strip_t": 0, + "instances": [ + { + "instance_s": 1, + "instance_t": 0, + "symbol_id": 9 + } + ] + }, + { + "strip_t": 60, + "instances": [ + { + "instance_s": 0, + "instance_t": 60, + "symbol_id": 3 + }, + { + "instance_s": 60, + "instance_t": 60, + "symbol_id": 2 + } + ] + } + ] + } + } + ] + } + ] + } + }, + + { + "segment_number": 3, + "type": "text_region", + "page_association": 1, + "referred_to_segments": [ + { + "segment_number": 2, + "retained": false + } + ], + "data": { + "region_segment_information": { + "width": 399, + "height": 400 + }, + "flags": { + "uses_huffman_encoding": true, + "uses_refinement_coding": true, + "strip_size": 2, + "reference_corner": "top_left", + "is_transposed": false, + "combination_operator": "xor", + "default_pixel_value": "white", + "delta_s_offset": 3, + "refinement_template": 0 + }, + "huffman_flags": { + "huffman_table_selection_for_first_s": 0, + "huffman_table_selection_for_subsequent_s": 0, + "huffman_table_selection_for_t": 0, + "huffman_table_selection_for_refinement_delta_width": 0, + "huffman_table_selection_for_refinement_delta_height": 0, + "huffman_table_selection_for_refinement_delta_x_offset": 0, + "huffman_table_selection_for_refinement_delta_y_offset": 0, + "huffman_table_selection_for_refinement_size_table": 0 + }, + + "initial_strip_t": -4, + "strips": [ + { + "strip_t": 70, + "instances": [ + { + "instance_s": 232, + "instance_t": 70, + "symbol_id": 2 + } + ] + }, + { + "strip_t": 100, + "instances": [ + { + "instance_s": 135, + "instance_t": 100, + "symbol_id": 3, + "instance_refines_symbol_to": { + "delta_width": 0, + "delta_height": 0, + "delta_x_offset": 0, + "delta_y_offset": 0, + "image_data": { + "from_file": "bitmap.bmp", + "crop": { + "x": 135, + "y": 100, + "width": 100, + "height": 100 + } + } + } + } + ] + }, + { + "strip_t": 108, + "instances": [ + { + "instance_s": 50, + "instance_t": 108, + "symbol_id": 1 + } + ] + }, + { + "strip_t": 264, + "instances": [ + { + "instance_s": 60, + "instance_t": 265, + "symbol_id": 0 + } + ] + } + ] + } + }, + + { + "segment_number": 4, + "type": "end_of_page", + "page_association": 1 + } + ] +} diff --git a/Userland/Libraries/LibGfx/ImageFormats/JBIG2Writer.cpp b/Userland/Libraries/LibGfx/ImageFormats/JBIG2Writer.cpp index b72695f2cdd866..88f5ed23973ff4 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/JBIG2Writer.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/JBIG2Writer.cpp @@ -486,22 +486,15 @@ static ErrorOr generic_refinement_region_encoding_procedure(GenericRefinem return {}; } -static ErrorOr> symbol_image(JBIG2::SymbolDictionarySegmentData::HeightClass::Symbol const& symbol, Vector const& symbols) +static ErrorOr> get_strip_symbol_image(IntSize size, JBIG2::SymbolDictionarySegmentData::HeightClass::RefinesUsingStrips const& text_strips, Vector> const& symbols) { - if (symbol.image.has>()) - return symbol.image.get>(); - if (symbol.image.has()) - return symbol.image.get().refines_to; - - auto image = TRY(BilevelImage::create(symbol.size.width(), symbol.size.height())); + auto image = TRY(BilevelImage::create(size.width(), size.height())); image->fill(false); - auto const& text_strips = symbol.image.get(); for (auto const& strip : text_strips.strips) { for (auto const& instance : strip.symbol_instances) { if (instance.symbol_id >= symbols.size()) return Error::from_string_literal("JBIG2Writer: Invalid symbol ID in text strip symbol instance"); - auto const& instance_symbol = symbols[instance.symbol_id]; - auto instance_image = TRY(symbol_image(instance_symbol, symbols)); + auto const& instance_image = symbols[instance.symbol_id]; instance_image->composite_onto(image, { instance.s, instance.t }, BilevelImage::CompositionType::Or); } } @@ -525,8 +518,8 @@ struct TextRegionEncodingInputParameters { // Only set if uses_huffman_encoding is true. JBIG2::HuffmanTable const* symbol_id_table { nullptr }; // "SBSYMCODES" in spec. - u32 id_symbol_code_length { 0 }; // "SBSYMCODELEN" in spec. - Vector symbols {}; // "SBNUMSYMS" / "SBSYMS" in spec. + u32 id_symbol_code_length { 0 }; // "SBSYMCODELEN" in spec. + Vector> symbols {}; // "SBNUMSYMS" / "SBSYMS" in spec. bool is_transposed { false }; // "TRANSPOSED" in spec. @@ -704,7 +697,7 @@ static ErrorOr text_region_encoding_procedure(TextRegionEncodingInputParam // "If RI is 0 then set the symbol instance bitmap IBI to SBSYMS[IDI]." if (!has_refinement_image) - return symbol.size; + return IntSize { static_cast(symbol->width()), static_cast(symbol->height()) }; TRY(write_refinement_delta_width(symbol_instance.refinement_data->delta_width)); TRY(write_refinement_delta_height(symbol_instance.refinement_data->delta_height)); @@ -719,21 +712,20 @@ static ErrorOr text_region_encoding_procedure(TextRegionEncodingInputParam } // Table 12 – Parameters used to decode a symbol instance's bitmap using refinement - if (static_cast(symbol.size.width()) + symbol_instance.refinement_data->delta_width < 0) + if (static_cast(symbol->width()) + symbol_instance.refinement_data->delta_width < 0) return Error::from_string_literal("JBIG2Writer: Refinement width out of bounds"); - if (static_cast(symbol.size.height()) + symbol_instance.refinement_data->delta_height < 0) + if (static_cast(symbol->height()) + symbol_instance.refinement_data->delta_height < 0) return Error::from_string_literal("JBIG2Writer: Refinement height out of bounds"); - auto reference_bitmap = TRY(symbol_image(symbol, inputs.symbols)); GenericRefinementRegionEncodingInputParameters refinement_inputs { .image = symbol_instance.refinement_data->refines_to, - .reference_bitmap = reference_bitmap->as_subbitmap(), + .reference_bitmap = symbol->as_subbitmap(), }; // FIXME: Instead, just compute the delta here instead of having it be passed in? - if (static_cast(reference_bitmap->width()) + symbol_instance.refinement_data->delta_width != static_cast(refinement_inputs.image.width())) + if (static_cast(symbol->width()) + symbol_instance.refinement_data->delta_width != static_cast(refinement_inputs.image.width())) return Error::from_string_literal("JBIG2Writer: Refinement reference width mismatch"); - if (static_cast(reference_bitmap->height()) + symbol_instance.refinement_data->delta_height != static_cast(refinement_inputs.image.height())) + if (static_cast(symbol->height()) + symbol_instance.refinement_data->delta_height != static_cast(refinement_inputs.image.height())) return Error::from_string_literal("JBIG2Writer: Refinement reference height mismatch"); refinement_inputs.gr_template = inputs.refinement_template; @@ -909,7 +901,7 @@ struct SymbolDictionaryEncodingInputParameters { bool uses_huffman_encoding { false }; // "SDHUFF" in spec. bool uses_refinement_or_aggregate_coding { false }; // "SDREFAGG" in spec. - Vector input_symbols; // "SDNUMINSYMS", "SDINSYMS" in spec. + Vector> input_symbols; // "SDNUMINSYMS", "SDINSYMS" in spec. Vector export_flags_for_referred_to_symbols; Vector height_classes; @@ -941,7 +933,7 @@ struct SymbolContexts { } // 6.5 Symbol Dictionary Decoding Procedure, but in reverse. -static ErrorOr symbol_dictionary_encoding_procedure(SymbolDictionaryEncodingInputParameters const& inputs, Optional& generic_contexts, Optional& refinement_contexts, Vector& exported_symbols) +static ErrorOr symbol_dictionary_encoding_procedure(SymbolDictionaryEncodingInputParameters const& inputs, Optional& generic_contexts, Optional& refinement_contexts, Vector>& exported_symbols) { Optional stream; Optional bit_stream; @@ -992,13 +984,13 @@ static ErrorOr symbol_dictionary_encoding_procedure(SymbolDictionary Optional text_contexts; // This belongs in 6.5.5 1) below, but also needs to be captured by write_symbol_bitmap here. - Vector new_symbols; + Vector> new_symbols; // Likewise, this is from 6.5.8.2.3 below. Vector symbol_id_codes; Optional symbol_id_table_storage; - auto write_symbol_bitmap = [&](JBIG2::SymbolDictionarySegmentData::HeightClass::Symbol const& symbol) -> ErrorOr { + auto write_symbol_bitmap = [&](JBIG2::SymbolDictionarySegmentData::HeightClass::Symbol const& symbol) -> ErrorOr> { // 6.5.8 Symbol bitmap // 6.5.8.1 Direct-coded symbol bitmap @@ -1018,7 +1010,8 @@ static ErrorOr symbol_dictionary_encoding_procedure(SymbolDictionary for (int i = 0; i < 4; ++i) generic_inputs.adaptive_template_pixels[i] = inputs.adaptive_template_pixels[i]; generic_inputs.arithmetic_encoder = &encoder.value(); - return generic_region_encoding_procedure(generic_inputs, generic_contexts); + TRY(generic_region_encoding_procedure(generic_inputs, generic_contexts)); + return generic_inputs.image; } if (symbol.image.has>()) @@ -1053,6 +1046,10 @@ static ErrorOr symbol_dictionary_encoding_procedure(SymbolDictionary if (!text_contexts.has_value()) text_contexts = TextContexts { code_length }; + Vector> all_symbols; + all_symbols.extend(inputs.input_symbols); + all_symbols.extend(new_symbols); + if (number_of_symbol_instances > 1) { auto const& refines_using_strips = symbol.image.get(); @@ -1071,8 +1068,7 @@ static ErrorOr symbol_dictionary_encoding_procedure(SymbolDictionary // 6.5.8.2.4 Setting SBSYMS // "Set SBSYMS to an array of SDNUMINSYMS + NSYMSDECODED symbols, formed by concatenating the array // SDINSYMS and the first NSYMSDECODED entries of the array SDNEWSYMS." - text_inputs.symbols.extend(inputs.input_symbols); - text_inputs.symbols.extend(new_symbols); + text_inputs.symbols = move(all_symbols); text_inputs.is_transposed = false; text_inputs.reference_corner = JBIG2::ReferenceCorner::TopLeft; @@ -1092,7 +1088,8 @@ static ErrorOr symbol_dictionary_encoding_procedure(SymbolDictionary text_inputs.bit_stream = &bit_stream.value(); else text_inputs.arithmetic_encoder = &encoder.value(); - return text_region_encoding_procedure(text_inputs, text_contexts, refinement_contexts); + TRY(text_region_encoding_procedure(text_inputs, text_contexts, refinement_contexts)); + return get_strip_symbol_image(symbol.size, refines_using_strips, text_inputs.symbols); } // "3) If REFAGGNINST is equal to one, then decode the bitmap as described in 6.5.8.2.2." @@ -1118,10 +1115,7 @@ static ErrorOr symbol_dictionary_encoding_procedure(SymbolDictionary if (refinement_image.symbol_id >= inputs.input_symbols.size() && refinement_image.symbol_id - inputs.input_symbols.size() >= new_symbols.size()) return Error::from_string_literal("JBIG2Writer: Refinement/aggregate symbol ID out of range"); - Vector all_symbols; - all_symbols.extend(inputs.input_symbols); - all_symbols.extend(new_symbols); - auto const& IBO = TRY(symbol_image(all_symbols[refinement_image.symbol_id], all_symbols)); + auto const& IBO = all_symbols[refinement_image.symbol_id]; MQArithmeticEncoder* refinement_encoder = nullptr; Optional huffman_refinement_encoder; @@ -1151,7 +1145,7 @@ static ErrorOr symbol_dictionary_encoding_procedure(SymbolDictionary TRY(stream->write_until_depleted(data)); } - return {}; + return refinement_image.refines_to; }; auto write_height_class_collective_bitmap = [&](BilevelImage const& image, bool compress) -> ErrorOr { @@ -1254,8 +1248,8 @@ static ErrorOr symbol_dictionary_encoding_procedure(SymbolDictionary // Let BS be the decoded bitmap (this bitmap has width SYMWIDTH and height HCHEIGHT). Set: // SDNEWSYMS[NSYMSDECODED] = BS" if (!inputs.uses_huffman_encoding || inputs.uses_refinement_or_aggregate_coding) { - TRY(write_symbol_bitmap(symbol)); - new_symbols.append(symbol); + auto bitmap = TRY(write_symbol_bitmap(symbol)); + new_symbols.append(bitmap); } // "iii) If SDHUFF is 1 and SDREFAGG is 0, then set: @@ -1291,7 +1285,7 @@ static ErrorOr symbol_dictionary_encoding_procedure(SymbolDictionary auto bitmap = symbol.image.get>(); bitmap->composite_onto(collective_bitmap, { current_column, 0 }, BilevelImage::CompositionType::Replace); VERIFY(static_cast(bitmap->width()) == symbol.size.width()); - new_symbols.append(symbol); + new_symbols.append(bitmap); current_column += symbol.size.width(); } TRY(write_height_class_collective_bitmap(collective_bitmap, height_class.is_collective_bitmap_compressed)); @@ -1556,7 +1550,7 @@ struct JBIG2EncodingContext { HashMap> codes_by_segment_id; HashMap tables_by_segment_id; - HashMap> symbols_by_segment_id; + HashMap>> symbols_by_segment_id; struct BitmapCodingContextState { Optional generic_contexts; @@ -1707,7 +1701,7 @@ static ErrorOr encode_symbol_dictionary(JBIG2::SymbolDictionarySegmentData { // Get referred-to symbol and table segments off header.referred_to_segments. Vector custom_tables; - Vector input_symbols; + Vector> input_symbols; Optional last_referred_to_symbol_dictionary_segment_id; for (auto const& referred_to_segment_number : header.referred_to_segments) { auto maybe_segment = context.segment_by_id.get(referred_to_segment_number.segment_number); @@ -1787,7 +1781,7 @@ static ErrorOr encode_symbol_dictionary(JBIG2::SymbolDictionarySegmentData refinement_contexts = JBIG2::RefinementContexts(inputs.refinement_template); } - Vector exported_symbols; + Vector> exported_symbols; ByteBuffer data = TRY(symbol_dictionary_encoding_procedure(inputs, generic_contexts, refinement_contexts, exported_symbols)); u32 number_of_exported_symbols = exported_symbols.size(); @@ -1945,7 +1939,7 @@ static ErrorOr encode_text_region(JBIG2::TextRegionSegmentData const& text { // Get referred-to symbol dictionaries and tables off header.referred_to_segments. Vector custom_tables; - Vector symbols; + Vector> symbols; for (auto const& referred_to_segment_number : header.referred_to_segments) { auto maybe_segment = context.segment_by_id.get(referred_to_segment_number.segment_number); if (!maybe_segment.has_value())