From 39519291052243d5ab678be3da5ae12787941016 Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Mon, 5 Apr 2021 10:11:07 +0100 Subject: lzw: Return output array from decode function instead of init. --- src/libnsgif.c | 12 +++++------- src/lzw.c | 47 +++++++++++++++++++++++++++++++++++------------ src/lzw.h | 22 ++++++++++------------ 3 files changed, 50 insertions(+), 31 deletions(-) diff --git a/src/libnsgif.c b/src/libnsgif.c index 1540e1d..e0d97c0 100644 --- a/src/libnsgif.c +++ b/src/libnsgif.c @@ -639,8 +639,6 @@ gif__decode(gif_animation *gif, unsigned int *restrict colour_table) { unsigned int transparency_index; - const uint8_t *stack_base; - const uint8_t *stack_pos; uint32_t available = 0; gif_result ret = GIF_OK; lzw_result res; @@ -648,7 +646,7 @@ gif__decode(gif_animation *gif, /* Initialise the LZW decoding */ res = lzw_decode_init(gif->lzw_ctx, gif->gif_data, gif->buffer_size, gif->buffer_position, - minimum_code_size, &stack_base); + minimum_code_size); if (res != LZW_OK) { return gif_error_from_lzw(res); } @@ -657,7 +655,6 @@ gif__decode(gif_animation *gif, gif->frames[frame].transparency_index : GIF_NO_TRANSPARENCY; - stack_pos = stack_base; for (unsigned int y = 0; y < height; y++) { unsigned int x; unsigned int decode_y; @@ -672,9 +669,11 @@ gif__decode(gif_animation *gif, x = width; while (x > 0) { + const uint8_t *uncompressed; unsigned row_available; if (available == 0) { - res = lzw_decode(gif->lzw_ctx, &available); + res = lzw_decode(gif->lzw_ctx, + &uncompressed, &available); if (res != LZW_OK) { /* Unexpected end of frame, try to recover */ if (res == LZW_OK_EOD) { @@ -684,7 +683,6 @@ gif__decode(gif_animation *gif, } break; } - stack_pos = stack_base; } row_available = x < available ? x : available; @@ -692,7 +690,7 @@ gif__decode(gif_animation *gif, available -= row_available; while (row_available-- > 0) { register unsigned int colour; - colour = *stack_pos++; + colour = *uncompressed++; if (colour != transparency_index) { *frame_scanline = colour_table[colour]; } diff --git a/src/lzw.c b/src/lzw.c index a589221..035882d 100644 --- a/src/lzw.c +++ b/src/lzw.c @@ -241,8 +241,7 @@ lzw_result lzw_decode_init( const uint8_t *compressed_data, uint32_t compressed_data_len, uint32_t compressed_data_pos, - uint8_t minimum_code_size, - const uint8_t ** const stack_base_out) + uint8_t minimum_code_size) { struct lzw_table_entry *table = ctx->table; @@ -274,7 +273,6 @@ lzw_result lzw_decode_init( lzw__clear_table(ctx); ctx->prev_code = ctx->clear_code; - *stack_base_out = ctx->stack_base; return LZW_OK; } @@ -301,30 +299,45 @@ static inline void lzw__table_add_entry( /** * Write values for this code to the output stack. * - * \param[in] ctx LZW reading context, updated. - * \param[in] code LZW code to output values for. + * \param[in] ctx LZW reading context, updated. + * \param[in] output Array to write output values into. + * \param[in] code LZW code to output values for. * \return Number of pixel values written. */ static inline uint32_t lzw__write_pixels(struct lzw_ctx *ctx, + void *restrict output, uint32_t code) { - uint8_t *stack_pos = ctx->stack_base; + uint8_t *restrict output_pos = (uint8_t *)output; struct lzw_table_entry * const table = ctx->table; uint32_t count = table[code].count; - stack_pos += count; + output_pos += count; for (unsigned i = count; i != 0; i--) { struct lzw_table_entry *entry = table + code; - *--stack_pos = entry->value; + *--output_pos = entry->value; code = entry->extends; } return count; } -/* Exported function, documented in lzw.h */ -lzw_result lzw_decode(struct lzw_ctx *ctx, - uint32_t *written) +/** + * Fill the LZW stack with decompressed data + * + * Ensure anything in output is used before calling this, as anything + * on the there before this call will be trampled. + * + * \param[in] ctx LZW reading context, updated. + * \param[in] output Array to write output values into. + * \param[out] used Returns the number of values written. + * Use with `stack_base_out` value from previous + * lzw_decode_init() call. + * \return LZW_OK on success, or appropriate error code otherwise. + */ +static inline lzw_result lzw__decode(struct lzw_ctx *ctx, + uint8_t *restrict output, + uint32_t *restrict used) { lzw_result res; uint32_t code; @@ -362,7 +375,7 @@ lzw_result lzw_decode(struct lzw_ctx *ctx, } } - *written += lzw__write_pixels(ctx, code); + *used += lzw__write_pixels(ctx, output, code); } /* Store details of this code as "previous code" to the context. */ @@ -372,3 +385,13 @@ lzw_result lzw_decode(struct lzw_ctx *ctx, return LZW_OK; } + +/* Exported function, documented in lzw.h */ +lzw_result lzw_decode(struct lzw_ctx *ctx, + const uint8_t *restrict* const restrict data, + uint32_t *restrict used) +{ + *used = 0; + *data = ctx->stack_base; + return lzw__decode(ctx, ctx->stack_base, used); +} diff --git a/src/lzw.h b/src/lzw.h index a4a58fc..dd0191e 100644 --- a/src/lzw.h +++ b/src/lzw.h @@ -74,23 +74,21 @@ lzw_result lzw_decode_init( const uint8_t *compressed_data, uint32_t compressed_data_len, uint32_t compressed_data_pos, - uint8_t minimum_code_size, - const uint8_t ** const stack_base_out); + uint8_t minimum_code_size); /** - * Fill the LZW stack with decompressed data + * Read a single LZW code and write into lzw context owned output buffer. * - * Ensure anything on the stack is used before calling this, as anything - * on the stack before this call will be trampled. + * Ensure anything in output is used before calling this, as anything + * on the there before this call will be trampled. * - * \param[in] ctx LZW reading context, updated. - * \param[out] written Returns the number of values written. - * Use with `stack_base_out` value from previous - * lzw_decode_init() call. + * \param[in] ctx LZW reading context, updated. + * \param[out] data Returns pointer to array of output values. + * \param[out] used Returns the number of values written to data. * \return LZW_OK on success, or appropriate error code otherwise. */ -lzw_result lzw_decode( - struct lzw_ctx *ctx, - uint32_t *written); +lzw_result lzw_decode(struct lzw_ctx *ctx, + const uint8_t *restrict *const restrict data, + uint32_t *restrict used); #endif -- cgit v1.2.3