mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 12:17:44 +00:00
LibGfx/CCITT: Add support for images with an unknown number of lines
This commit is contained in:
parent
cefb2d65d8
commit
be5e7a360f
2 changed files with 42 additions and 19 deletions
|
@ -392,10 +392,12 @@ constexpr Array node_codes = to_array<ModeCode>({
|
||||||
{ 7, Mode::Vertical_L3, 0b0000010 },
|
{ 7, Mode::Vertical_L3, 0b0000010 },
|
||||||
});
|
});
|
||||||
|
|
||||||
ErrorOr<ModeCode> read_mode(BigEndianInputBitStream& input_bit_stream)
|
using InvalidResult = u8;
|
||||||
|
|
||||||
|
ErrorOr<Variant<ModeCode, InvalidResult>> read_mode(BigEndianInputBitStream& input_bit_stream)
|
||||||
{
|
{
|
||||||
u8 size {};
|
u8 size {};
|
||||||
u16 potential_code {};
|
u8 potential_code {};
|
||||||
while (size < 7) {
|
while (size < 7) {
|
||||||
potential_code <<= 1;
|
potential_code <<= 1;
|
||||||
potential_code |= TRY(input_bit_stream.read_bit());
|
potential_code |= TRY(input_bit_stream.read_bit());
|
||||||
|
@ -405,7 +407,7 @@ ErrorOr<ModeCode> read_mode(BigEndianInputBitStream& input_bit_stream)
|
||||||
return *maybe_mode;
|
return *maybe_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Error::from_string_literal("CCITTDecoder: Unable to find the correct mode");
|
return Variant<ModeCode, InvalidResult>(InvalidResult { potential_code });
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Search : u8 {
|
enum class Search : u8 {
|
||||||
|
@ -413,9 +415,14 @@ enum class Search : u8 {
|
||||||
B2,
|
B2,
|
||||||
};
|
};
|
||||||
|
|
||||||
ErrorOr<ReferenceLine> decode_single_ccitt_2d_line(BigEndianInputBitStream& input_bit_stream, BigEndianOutputBitStream& decoded_bits, ReferenceLine&& reference_line, u32 image_width)
|
struct CCITTStatus {
|
||||||
{
|
|
||||||
ReferenceLine current_line {};
|
ReferenceLine current_line {};
|
||||||
|
bool has_reached_eol { false };
|
||||||
|
};
|
||||||
|
|
||||||
|
ErrorOr<CCITTStatus> decode_single_ccitt_2d_line(BigEndianInputBitStream& input_bit_stream, BigEndianOutputBitStream& decoded_bits, ReferenceLine&& reference_line, u32 image_width)
|
||||||
|
{
|
||||||
|
CCITTStatus status {};
|
||||||
Color current_color { ccitt_white };
|
Color current_color { ccitt_white };
|
||||||
u32 column {};
|
u32 column {};
|
||||||
u32 remainder_from_pass_mode {};
|
u32 remainder_from_pass_mode {};
|
||||||
|
@ -453,15 +460,30 @@ ErrorOr<ReferenceLine> decode_single_ccitt_2d_line(BigEndianInputBitStream& inpu
|
||||||
current_color = invert(current_color);
|
current_color = invert(current_color);
|
||||||
remainder_from_pass_mode = 0;
|
remainder_from_pass_mode = 0;
|
||||||
|
|
||||||
TRY(current_line.try_empend(current_color, column));
|
TRY(status.current_line.try_empend(current_color, column));
|
||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
|
|
||||||
while (column < image_width) {
|
while (column < image_width) {
|
||||||
auto const mode = TRY(read_mode(input_bit_stream));
|
auto const maybe_mode = TRY(read_mode(input_bit_stream));
|
||||||
|
|
||||||
|
if (maybe_mode.has<InvalidResult>()) {
|
||||||
|
auto const partially_read_eol = maybe_mode.get<InvalidResult>();
|
||||||
|
|
||||||
|
if (partially_read_eol != 0)
|
||||||
|
return Error::from_string_literal("CCITTDecoder: Unable to find the correct mode");
|
||||||
|
|
||||||
|
auto const remaining_eol = TRY(input_bit_stream.read_bits(5));
|
||||||
|
if (remaining_eol != 1)
|
||||||
|
return Error::from_string_literal("CCITTDecoder: Unable to find the correct mode");
|
||||||
|
|
||||||
|
// We reached EOL
|
||||||
|
status.has_reached_eol = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Behavior are described here 4.2.1.3.2 Coding modes.
|
// Behavior are described here 4.2.1.3.2 Coding modes.
|
||||||
switch (mode.mode) {
|
switch (maybe_mode.get<ModeCode>().mode) {
|
||||||
case Mode::Pass: {
|
case Mode::Pass: {
|
||||||
auto const column_before = column;
|
auto const column_before = column;
|
||||||
// We search for b1.
|
// We search for b1.
|
||||||
|
@ -515,7 +537,7 @@ ErrorOr<ReferenceLine> decode_single_ccitt_2d_line(BigEndianInputBitStream& inpu
|
||||||
|
|
||||||
TRY(decoded_bits.align_to_byte_boundary());
|
TRY(decoded_bits.align_to_byte_boundary());
|
||||||
|
|
||||||
return current_line;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> decode_single_ccitt3_2d_block(BigEndianInputBitStream& input_bit_stream, BigEndianOutputBitStream& decoded_bits, u32 image_width, u32 image_height, Group3Options::UseFillBits use_fill_bits)
|
ErrorOr<void> decode_single_ccitt3_2d_block(BigEndianInputBitStream& input_bit_stream, BigEndianOutputBitStream& decoded_bits, u32 image_width, u32 image_height, Group3Options::UseFillBits use_fill_bits)
|
||||||
|
@ -528,7 +550,7 @@ ErrorOr<void> decode_single_ccitt3_2d_block(BigEndianInputBitStream& input_bit_s
|
||||||
if (next_is_1D)
|
if (next_is_1D)
|
||||||
reference_line = TRY(decode_single_ccitt3_1d_line(input_bit_stream, decoded_bits, image_width));
|
reference_line = TRY(decode_single_ccitt3_1d_line(input_bit_stream, decoded_bits, image_width));
|
||||||
else
|
else
|
||||||
reference_line = TRY(decode_single_ccitt_2d_line(input_bit_stream, decoded_bits, move(reference_line), image_width));
|
reference_line = TRY(decode_single_ccitt_2d_line(input_bit_stream, decoded_bits, move(reference_line), image_width)).current_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -590,20 +612,21 @@ ErrorOr<ByteBuffer> decode_ccitt_group4(ReadonlyBytes bytes, u32 image_width, u3
|
||||||
auto strip_stream = make<FixedMemoryStream>(bytes);
|
auto strip_stream = make<FixedMemoryStream>(bytes);
|
||||||
auto bit_stream = make<BigEndianInputBitStream>(MaybeOwned<Stream>(*strip_stream));
|
auto bit_stream = make<BigEndianInputBitStream>(MaybeOwned<Stream>(*strip_stream));
|
||||||
|
|
||||||
// Note: We put image_height extra-space to handle at most one alignment to byte boundary per line.
|
auto output_stream = make<AllocatingMemoryStream>();
|
||||||
ByteBuffer decoded_bytes = TRY(ByteBuffer::create_zeroed(ceil_div(image_width * image_height, 8) + image_height));
|
|
||||||
auto output_stream = make<FixedMemoryStream>(decoded_bytes.bytes());
|
|
||||||
auto decoded_bits = make<BigEndianOutputBitStream>(MaybeOwned<Stream>(*output_stream));
|
auto decoded_bits = make<BigEndianOutputBitStream>(MaybeOwned<Stream>(*output_stream));
|
||||||
|
|
||||||
// T.6 2.2.1 Principle of the coding scheme
|
// T.6 2.2.1 Principle of the coding scheme
|
||||||
// The reference line for the first coding line in a page is an imaginary white line.
|
// The reference line for the first coding line in a page is an imaginary white line.
|
||||||
ReferenceLine reference_line;
|
CCITTStatus status;
|
||||||
TRY(reference_line.try_empend(ccitt_black, image_width));
|
TRY(status.current_line.try_empend(ccitt_black, image_width));
|
||||||
|
|
||||||
for (u32 i = 0; i < image_height; ++i)
|
u32 i {};
|
||||||
reference_line = TRY(decode_single_ccitt_2d_line(*bit_stream, *decoded_bits, move(reference_line), image_width));
|
while (!status.has_reached_eol && (image_height == 0 || i < image_height)) {
|
||||||
|
status = TRY(decode_single_ccitt_2d_line(*bit_stream, *decoded_bits, move(status.current_line), image_width));
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
return decoded_bytes;
|
return output_stream->read_until_eof();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -316,7 +316,7 @@ PDFErrorOr<ByteBuffer> Filter::decode_ccitt(ReadonlyBytes bytes, RefPtr<DictObje
|
||||||
// achieve to decode images that have it. Figure out what to do with it.
|
// achieve to decode images that have it. Figure out what to do with it.
|
||||||
(void)end_of_block;
|
(void)end_of_block;
|
||||||
|
|
||||||
if (require_end_of_line || encoded_byte_align || damaged_rows_before_error > 0 || rows == 0)
|
if (require_end_of_line || encoded_byte_align || damaged_rows_before_error > 0)
|
||||||
return Error::rendering_unsupported_error("Unimplemented option for the CCITTFaxDecode Filter");
|
return Error::rendering_unsupported_error("Unimplemented option for the CCITTFaxDecode Filter");
|
||||||
|
|
||||||
ByteBuffer decoded {};
|
ByteBuffer decoded {};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue