From f434088537e3c8a4bde836fcea3c159b44fe8983 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sat, 3 Apr 2021 22:11:58 +0100 Subject: lzw: Adapt main code handling to handle clear codes too. --- src/lzw.c | 80 +++++++++++++++++++++------------------------------------------ 1 file changed, 26 insertions(+), 54 deletions(-) diff --git a/src/lzw.c b/src/lzw.c index 518756c..ac710a7 100644 --- a/src/lzw.c +++ b/src/lzw.c @@ -223,42 +223,16 @@ static inline lzw_result lzw__read_code( /** * Clear LZW code table. * - * \param[in] ctx LZW reading context, updated. + * \param[in] ctx LZW reading context, updated. * \return LZW_OK or error code. */ -static lzw_result lzw__clear_codes( +static inline void lzw__clear_table( struct lzw_ctx *ctx) { - uint32_t code; - /* Reset table building context */ ctx->code_size = ctx->initial_code_size; ctx->code_max = (1 << ctx->initial_code_size) - 1; ctx->table_size = ctx->eoi_code + 1; - - /* There might be a sequence of clear codes, so process them all */ - do { - lzw_result res = lzw__read_code(&ctx->input, - ctx->code_size, &code); - if (res != LZW_OK) { - return res; - } - } while (code == ctx->clear_code); - - /* The initial code must be from the initial table. */ - if (code > ctx->clear_code) { - return LZW_BAD_ICODE; - } - - /* Record this initial code as "previous" code, needed during decode. */ - ctx->prev_code = code; - ctx->prev_code_first = code; - ctx->prev_code_count = 1; - - /* Reset the stack, and add first non-clear code added as first item. */ - ctx->stack_base[ctx->written++] = code; - - return LZW_OK; } @@ -298,10 +272,11 @@ lzw_result lzw_decode_init( table[i].count = 1; } - ctx->written = 0; + lzw__clear_table(ctx); + ctx->prev_code = ctx->clear_code; *stack_base_out = ctx->stack_base; - return lzw__clear_codes(ctx); + return LZW_OK; } /** @@ -355,6 +330,8 @@ lzw_result lzw_decode(struct lzw_ctx *ctx, lzw_result res; uint32_t code; + ctx->written = 0; + /* Get a new code from the input */ res = lzw__read_code(&ctx->input, ctx->code_size, &code); if (res != LZW_OK) { @@ -362,35 +339,33 @@ lzw_result lzw_decode(struct lzw_ctx *ctx, } /* Handle the new code */ - if (code == ctx->clear_code) { - /* Got Clear code */ - res = lzw__clear_codes(ctx); - if (res == LZW_OK) { - *written = ctx->written; - ctx->written = 0; - } - return res; - - } else if (code == ctx->eoi_code) { + if (code == ctx->eoi_code) { /* Got End of Information code */ return LZW_EOI_CODE; } else if (code > ctx->table_size) { /* Code is invalid */ return LZW_BAD_CODE; - } - if (ctx->table_size < LZW_TABLE_ENTRY_MAX) { - uint32_t size = ctx->table_size; - lzw__table_add_entry(ctx, (code < size) ? - ctx->table[code].first : - ctx->prev_code_first); - - /* Ensure code size is increased, if needed. */ - if (size == ctx->code_max && ctx->code_size < LZW_CODE_MAX) { - ctx->code_size++; - ctx->code_max = (1 << ctx->code_size) - 1; + } else if (code == ctx->clear_code) { + lzw__clear_table(ctx); + } else { + if (ctx->prev_code != ctx->clear_code && + ctx->table_size < LZW_TABLE_ENTRY_MAX) { + uint32_t size = ctx->table_size; + lzw__table_add_entry(ctx, (code < size) ? + ctx->table[code].first : + ctx->prev_code_first); + + /* Ensure code size is increased, if needed. */ + if (size == ctx->code_max && + ctx->code_size < LZW_CODE_MAX) { + ctx->code_size++; + ctx->code_max = (1 << ctx->code_size) - 1; + } } + + lzw__write_pixels(ctx, code); } /* Store details of this code as "previous code" to the context. */ @@ -398,10 +373,7 @@ lzw_result lzw_decode(struct lzw_ctx *ctx, ctx->prev_code_count = ctx->table[code].count; ctx->prev_code = code; - lzw__write_pixels(ctx, code); - *written = ctx->written; - ctx->written = 0; return LZW_OK; } -- cgit v1.2.3