29#define LZW_TABLE_ENTRY_MAX (1u << LZW_CODE_MAX)
130 fl::size next_block_pos = ctx->data_sb_next;
131 const fl::u8 *data_next = ctx->data + next_block_pos;
133 if (next_block_pos >= ctx->data_len) {
137 block_size = *data_next;
139 if ((next_block_pos + block_size) >= ctx->data_len) {
144 ctx->sb_bit_count = block_size * 8;
146 if (block_size == 0) {
147 ctx->data_sb_next += 1;
151 ctx->sb_data = data_next + 1;
152 ctx->data_sb_next += block_size + 1;
173 fl::u32 current_bit = ctx->sb_bit & 0x7;
175 if (ctx->sb_bit + 24 <= ctx->sb_bit_count) {
177 const fl::u8 *data = ctx->sb_data + (ctx->sb_bit >> 3);
178 code |=
static_cast<fl::u32
>(*data++) << 0;
179 code |=
static_cast<fl::u32
>(*data++) << 8;
180 code |=
static_cast<fl::u32
>(*data) << 16;
181 ctx->sb_bit += code_size;
184 fl::u8 byte_advance = (current_bit + code_size) >> 3;
186 fl::u8 bits_remaining_0 = (code_size < (8u - current_bit)) ?
187 code_size : (8u - current_bit);
188 fl::u8 bits_remaining_1 = code_size - bits_remaining_0;
191 (
fl::u8)(bits_remaining_1 < 8 ? bits_remaining_1 : 8),
192 (
fl::u8)(bits_remaining_1 - 8),
195 FL_ASSERT(byte_advance <= 2,
"Byte advance too large");
198 const fl::u8 *data = ctx->sb_data;
202 while (
byte <= byte_advance &&
203 ctx->sb_bit < ctx->sb_bit_count) {
204 code |= data[ctx->sb_bit >> 3] << (
byte << 3);
205 ctx->sb_bit += bits_used[
byte];
210 if (
byte > byte_advance) {
222 *code_out = (code >> current_bit) & ((1 << code_size) - 1);
240 ctx->code_size = ctx->initial_code_size;
241 ctx->code_max = (1 << ctx->initial_code_size) - 1;
242 ctx->table_size = ctx->eoi_code + 1;
247 ctx->code_size, &code);
251 }
while (code == ctx->clear_code);
254 if (code > ctx->clear_code) {
267 fl::size input_length,
279 ctx->input.data = input_data;
280 ctx->input.data_len = input_length;
281 ctx->input.data_sb_next = input_pos;
283 ctx->input.sb_bit = 0;
284 ctx->input.sb_bit_count = 0;
287 ctx->initial_code_size = minimum_code_size + 1;
289 ctx->clear_code = (1 << minimum_code_size) + 0;
290 ctx->eoi_code = (1 << minimum_code_size) + 1;
292 ctx->output_left = 0;
295 for (fl::u16 i = 0; i < ctx->clear_code; i++) {
307 ctx->prev_code_first = ctx->table[code].first;
308 ctx->prev_code_count = ctx->table[code].count;
309 ctx->prev_code = code;
312 ctx->output_code = code;
313 ctx->output_left = 1;
315 ctx->has_transparency =
false;
316 ctx->transparency_idx = 0;
317 ctx->colour_map =
nullptr;
326 fl::u32 transparency_idx,
327 const fl::u32 *colour_table,
329 fl::size input_length,
334 if (colour_table ==
nullptr) {
339 input_data, input_length, input_pos);
344 ctx->has_transparency = (transparency_idx <= 0xFF);
345 ctx->transparency_idx = transparency_idx;
346 ctx->colour_map = colour_table;
364 entry->
first = ctx->prev_code_first;
365 entry->
count = ctx->prev_code_count + 1;
366 entry->
extends = ctx->prev_code;
374 fl::u32 output_length,
393 fl::u32 output_length,
433 *output_written += write_fn(ctx,
434 output_data, output_length, *output_written,
463 fl::u32 output_length,
468 fl::u8 * output_pos = (
fl::u8 *)output_data + output_used;
470 fl::u32 space = output_length - output_used;
471 fl::u16 count = left;
474 left = count - space;
484 for (
unsigned i = left; i != 0; i--) {
490 for (
unsigned i = count; i != 0; i--) {
492 *--output_pos = entry->
value;
501 const fl::u8 * *
const output_data,
504 const fl::u32 output_length =
sizeof(ctx->
stack_base);
511 ctx->
stack_base, output_length, *output_written,
515 while (*output_written != output_length) {
517 ctx->
stack_base, output_length, output_written);
544 fl::u32 output_length,
549 fl::u32 * output_pos = (fl::u32 *)output_data + output_used;
551 fl::u32 space = output_length - output_used;
552 fl::u16 count = left;
555 left = count - space;
564 for (
unsigned i = left; i != 0; i--) {
571 for (
unsigned i = count; i != 0; i--) {
580 for (
unsigned i = count; i != 0; i--) {
592 fl::u32 * output_data,
593 fl::u32 output_length,
604 output_data, output_length, *output_written,
608 while (*output_written != output_length) {
610 output_data, output_length, output_written);
#define FL_ASSERT(x, MSG)
#define LZW_TABLE_ENTRY_MAX
Maximum number of lzw table entries.
#define LZW_CODE_MAX
Maximum LZW code size in bits.
LZW decompression (interface)
fl::u32(* lzw_writer_fn)(struct lzw_ctx *ctx, void *output_data, fl::u32 output_length, fl::u32 output_pos, fl::u16 code, fl::u16 left)
lzw_result lzw_decode_init(struct lzw_ctx *ctx, fl::u8 minimum_code_size, const fl::u8 *input_data, fl::size input_length, fl::size input_pos) FL_NOEXCEPT
Initialise an LZW decompression context for decoding.
lzw_result lzw_context_create(struct lzw_ctx **ctx) FL_NOEXCEPT
Create an LZW decompression context.
void lzw_context_destroy(struct lzw_ctx *ctx) FL_NOEXCEPT
Destroy an LZW decompression context.
static lzw_result lzw__decode(struct lzw_ctx *ctx, lzw_writer_fn write_fn, void *output_data, fl::u32 output_length, fl::u32 *output_written) FL_NOEXCEPT
Get the next LZW code and write its value(s) to output buffer.
static fl::u32 lzw__map_write_fn(struct lzw_ctx *ctx, void *output_data, fl::u32 output_length, fl::u32 output_used, fl::u16 code, fl::u16 left) FL_NOEXCEPT
Write colour mapped values for this code to the output.
static lzw_result lzw__read_code(struct lzw_read_ctx *ctx, fl::u16 code_size, fl::u16 *code_out) FL_NOEXCEPT
Get the next LZW code of given size from the raw input data.
lzw_result
LZW decoding response codes.
@ LZW_NO_DATA
Error: Out of data.
@ LZW_EOI_CODE
Error: End of Information code.
@ LZW_NO_COLOUR
Error: No colour map provided.
@ LZW_BAD_CODE
Error: Bad LZW code.
@ LZW_NO_MEM
Error: Out of memory.
@ LZW_BAD_PARAM
Error: Bad function parameter.
@ LZW_OK_EOD
Success; reached zero-length sub-block.
@ LZW_BAD_ICODE
Error: Bad initial LZW code.
static fl::u32 lzw__write_fn(struct lzw_ctx *ctx, void *output_data, fl::u32 output_length, fl::u32 output_used, fl::u16 code, fl::u16 left) FL_NOEXCEPT
Write values for this code to the output stack.
lzw_result lzw_decode_init_map(struct lzw_ctx *ctx, fl::u8 minimum_code_size, fl::u32 transparency_idx, const fl::u32 *colour_table, const fl::u8 *input_data, fl::size input_length, fl::size input_pos) FL_NOEXCEPT
Initialise an LZW decompression context for decoding to colour map values.
static void lzw__table_add_entry(struct lzw_ctx *ctx, fl::u16 code) FL_NOEXCEPT
Create new table entry.
lzw_result lzw_decode(struct lzw_ctx *ctx, const fl::u8 **const output_data, fl::u32 *output_written) FL_NOEXCEPT
Read input codes until end of LZW context owned output buffer.
static lzw_result lzw__handle_clear(struct lzw_ctx *ctx, fl::u16 *code_out) FL_NOEXCEPT
Handle clear code.
static lzw_result lzw__block_advance(struct lzw_read_ctx *ctx) FL_NOEXCEPT
Advance the context to the next sub-block in the input data.
lzw_result lzw_decode_map(struct lzw_ctx *ctx, fl::u32 *output_data, fl::u32 output_length, fl::u32 *output_written) FL_NOEXCEPT
Read LZW codes into client buffer, mapping output to colours.
fl::u8 first
First value in entry's entire record.
fl::u16 extends
Offset in table to previous entry.
fl::u16 table_size
Next position in table to fill.
fl::size data_sb_next
Offset to sub-block size.
fl::u16 clear_code
Special Clear code value.
const fl::u8 * sb_data
Pointer to current sub-block in data.
bool has_transparency
Whether the image is opaque.
fl::u32 sb_bit_count
Bit count in sub-block.
fl::u16 prev_code_first
First value of previous code.
struct lzw_table_entry table[LZW_TABLE_ENTRY_MAX]
LZW code table.
fl::u16 eoi_code
Special End of Information code value.
fl::size sb_bit
Current bit offset in sub-block.
fl::u16 count
Count of values in this entry's record.
const fl::u32 * colour_map
Index to colour mapping.
fl::u8 initial_code_size
Starting LZW code size.
fl::u8 transparency_idx
Index representing transparency.
fl::u8 code_size
Current LZW code size.
fl::size data_len
Input data length.
fl::u16 prev_code
Code read from input previously.
struct lzw_read_ctx input
Input reading context.
fl::u8 value
Last value for record ending at entry.
fl::u16 output_left
Number of values left for output_code.
const fl::u8 * data
Pointer to start of input data.
fl::u16 code_max
Max code value for current code size.
fl::u16 output_code
Code that has been partially output.
fl::u8 stack_base[LZW_TABLE_ENTRY_MAX]
Output value stack.
fl::u16 prev_code_count
Total values for previous code.
LZW decompression context.
Context for reading LZW data.
void * Malloc(fl::size size)
Base definition for an LED controller.