1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 05:54:58 +00:00

LibCompress: Add LZWDecoder::decode_all()

This method takes bytes as input and decompress everything to a
ByteBuffer. It uses two control codes (clear and end of data) as
described in the GIF, TIFF and PDF specifications.
This commit is contained in:
Lucas CHOLLET 2023-11-27 21:48:17 -05:00 committed by Andreas Kling
parent e9e89d7e4e
commit 2a5cb5becb
2 changed files with 30 additions and 23 deletions

View file

@ -12,6 +12,7 @@
#include <AK/Debug.h>
#include <AK/Format.h>
#include <AK/IntegralMath.h>
#include <AK/MemoryStream.h>
#include <AK/Vector.h>
namespace Compress {
@ -33,6 +34,34 @@ public:
init_code_table();
}
static ErrorOr<ByteBuffer> decode_all(ReadonlyBytes bytes, u8 initial_code_size, i32 offset_for_size_change = 0)
{
auto memory_stream = make<FixedMemoryStream>(bytes);
auto lzw_stream = make<InputStream>(MaybeOwned<Stream>(move(memory_stream)));
Compress::LZWDecoder lzw_decoder { MaybeOwned<InputStream> { move(lzw_stream) }, initial_code_size, offset_for_size_change };
ByteBuffer decoded;
u16 const clear_code = lzw_decoder.add_control_code();
u16 const end_of_data_code = lzw_decoder.add_control_code();
while (true) {
auto const code = TRY(lzw_decoder.next_code());
if (code == clear_code) {
lzw_decoder.reset();
continue;
}
if (code == end_of_data_code)
break;
TRY(decoded.try_append(lzw_decoder.get_output()));
}
return decoded;
}
u16 add_control_code()
{
u16 const control_code = m_code_table.size();

View file

@ -198,29 +198,7 @@ PDFErrorOr<ByteBuffer> Filter::handle_lzw_and_flate_parameters(ByteBuffer buffer
PDFErrorOr<ByteBuffer> Filter::decode_lzw(ReadonlyBytes bytes, int predictor, int columns, int colors, int bits_per_component, int early_change)
{
auto memory_stream = make<FixedMemoryStream>(bytes);
auto lzw_stream = make<BigEndianInputBitStream>(MaybeOwned<Stream>(move(memory_stream)));
Compress::LZWDecoder lzw_decoder { MaybeOwned<BigEndianInputBitStream> { move(lzw_stream) }, 8, -early_change };
ByteBuffer decoded;
u16 const clear_code = lzw_decoder.add_control_code();
u16 const end_of_data_code = lzw_decoder.add_control_code();
while (true) {
auto const code = TRY(lzw_decoder.next_code());
if (code == clear_code) {
lzw_decoder.reset();
continue;
}
if (code == end_of_data_code)
break;
TRY(decoded.try_append(lzw_decoder.get_output()));
}
auto decoded = TRY(Compress::LZWDecoder<BigEndianInputBitStream>::decode_all(bytes, 8, -early_change));
return handle_lzw_and_flate_parameters(move(decoded), predictor, columns, colors, bits_per_component);
}