lzw: Return output array from decode function instead of init.
This commit is contained in:
parent
01fde32f99
commit
abd8619bef
@ -634,8 +634,6 @@ gif__decode(gif_animation *gif,
|
|||||||
unsigned int *restrict colour_table)
|
unsigned int *restrict colour_table)
|
||||||
{
|
{
|
||||||
unsigned int transparency_index;
|
unsigned int transparency_index;
|
||||||
const uint8_t *stack_base;
|
|
||||||
const uint8_t *stack_pos;
|
|
||||||
uint32_t available = 0;
|
uint32_t available = 0;
|
||||||
gif_result ret = GIF_OK;
|
gif_result ret = GIF_OK;
|
||||||
lzw_result res;
|
lzw_result res;
|
||||||
@ -643,7 +641,7 @@ gif__decode(gif_animation *gif,
|
|||||||
/* Initialise the LZW decoding */
|
/* Initialise the LZW decoding */
|
||||||
res = lzw_decode_init(gif->lzw_ctx, gif->gif_data,
|
res = lzw_decode_init(gif->lzw_ctx, gif->gif_data,
|
||||||
gif->buffer_size, gif->buffer_position,
|
gif->buffer_size, gif->buffer_position,
|
||||||
minimum_code_size, &stack_base);
|
minimum_code_size);
|
||||||
if (res != LZW_OK) {
|
if (res != LZW_OK) {
|
||||||
return gif_error_from_lzw(res);
|
return gif_error_from_lzw(res);
|
||||||
}
|
}
|
||||||
@ -652,7 +650,6 @@ gif__decode(gif_animation *gif,
|
|||||||
gif->frames[frame].transparency_index :
|
gif->frames[frame].transparency_index :
|
||||||
GIF_NO_TRANSPARENCY;
|
GIF_NO_TRANSPARENCY;
|
||||||
|
|
||||||
stack_pos = stack_base;
|
|
||||||
for (unsigned int y = 0; y < height; y++) {
|
for (unsigned int y = 0; y < height; y++) {
|
||||||
unsigned int x;
|
unsigned int x;
|
||||||
unsigned int decode_y;
|
unsigned int decode_y;
|
||||||
@ -667,9 +664,11 @@ gif__decode(gif_animation *gif,
|
|||||||
|
|
||||||
x = width;
|
x = width;
|
||||||
while (x > 0) {
|
while (x > 0) {
|
||||||
|
const uint8_t *uncompressed;
|
||||||
unsigned row_available;
|
unsigned row_available;
|
||||||
if (available == 0) {
|
if (available == 0) {
|
||||||
res = lzw_decode(gif->lzw_ctx, &available);
|
res = lzw_decode(gif->lzw_ctx,
|
||||||
|
&uncompressed, &available);
|
||||||
if (res != LZW_OK) {
|
if (res != LZW_OK) {
|
||||||
/* Unexpected end of frame, try to recover */
|
/* Unexpected end of frame, try to recover */
|
||||||
if (res == LZW_OK_EOD) {
|
if (res == LZW_OK_EOD) {
|
||||||
@ -679,7 +678,6 @@ gif__decode(gif_animation *gif,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
stack_pos = stack_base;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
row_available = x < available ? x : available;
|
row_available = x < available ? x : available;
|
||||||
@ -687,7 +685,7 @@ gif__decode(gif_animation *gif,
|
|||||||
available -= row_available;
|
available -= row_available;
|
||||||
while (row_available-- > 0) {
|
while (row_available-- > 0) {
|
||||||
register unsigned int colour;
|
register unsigned int colour;
|
||||||
colour = *stack_pos++;
|
colour = *uncompressed++;
|
||||||
if (colour != transparency_index) {
|
if (colour != transparency_index) {
|
||||||
*frame_scanline = colour_table[colour];
|
*frame_scanline = colour_table[colour];
|
||||||
}
|
}
|
||||||
|
@ -241,8 +241,7 @@ lzw_result lzw_decode_init(
|
|||||||
const uint8_t *compressed_data,
|
const uint8_t *compressed_data,
|
||||||
uint32_t compressed_data_len,
|
uint32_t compressed_data_len,
|
||||||
uint32_t compressed_data_pos,
|
uint32_t compressed_data_pos,
|
||||||
uint8_t minimum_code_size,
|
uint8_t minimum_code_size)
|
||||||
const uint8_t ** const stack_base_out)
|
|
||||||
{
|
{
|
||||||
struct lzw_table_entry *table = ctx->table;
|
struct lzw_table_entry *table = ctx->table;
|
||||||
|
|
||||||
@ -274,7 +273,6 @@ lzw_result lzw_decode_init(
|
|||||||
lzw__clear_table(ctx);
|
lzw__clear_table(ctx);
|
||||||
ctx->prev_code = ctx->clear_code;
|
ctx->prev_code = ctx->clear_code;
|
||||||
|
|
||||||
*stack_base_out = ctx->stack_base;
|
|
||||||
return LZW_OK;
|
return LZW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,29 +300,44 @@ static inline void lzw__table_add_entry(
|
|||||||
* Write values for this code to the output stack.
|
* Write values for this code to the output stack.
|
||||||
*
|
*
|
||||||
* \param[in] ctx LZW reading context, updated.
|
* \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.
|
* \param[in] code LZW code to output values for.
|
||||||
* \return Number of pixel values written.
|
* \return Number of pixel values written.
|
||||||
*/
|
*/
|
||||||
static inline uint32_t lzw__write_pixels(struct lzw_ctx *ctx,
|
static inline uint32_t lzw__write_pixels(struct lzw_ctx *ctx,
|
||||||
|
void *restrict output,
|
||||||
uint32_t code)
|
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;
|
struct lzw_table_entry * const table = ctx->table;
|
||||||
uint32_t count = table[code].count;
|
uint32_t count = table[code].count;
|
||||||
|
|
||||||
stack_pos += count;
|
output_pos += count;
|
||||||
for (unsigned i = count; i != 0; i--) {
|
for (unsigned i = count; i != 0; i--) {
|
||||||
struct lzw_table_entry *entry = table + code;
|
struct lzw_table_entry *entry = table + code;
|
||||||
*--stack_pos = entry->value;
|
*--output_pos = entry->value;
|
||||||
code = entry->extends;
|
code = entry->extends;
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Exported function, documented in lzw.h */
|
/**
|
||||||
lzw_result lzw_decode(struct lzw_ctx *ctx,
|
* Fill the LZW stack with decompressed data
|
||||||
uint32_t *written)
|
*
|
||||||
|
* 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;
|
lzw_result res;
|
||||||
uint32_t code;
|
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. */
|
/* 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;
|
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);
|
||||||
|
}
|
||||||
|
@ -74,23 +74,21 @@ lzw_result lzw_decode_init(
|
|||||||
const uint8_t *compressed_data,
|
const uint8_t *compressed_data,
|
||||||
uint32_t compressed_data_len,
|
uint32_t compressed_data_len,
|
||||||
uint32_t compressed_data_pos,
|
uint32_t compressed_data_pos,
|
||||||
uint8_t minimum_code_size,
|
uint8_t minimum_code_size);
|
||||||
const uint8_t ** const stack_base_out);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
* Ensure anything in output is used before calling this, as anything
|
||||||
* on the stack before this call will be trampled.
|
* on the there before this call will be trampled.
|
||||||
*
|
*
|
||||||
* \param[in] ctx LZW reading context, updated.
|
* \param[in] ctx LZW reading context, updated.
|
||||||
* \param[out] written Returns the number of values written.
|
* \param[out] data Returns pointer to array of output values.
|
||||||
* Use with `stack_base_out` value from previous
|
* \param[out] used Returns the number of values written to data.
|
||||||
* lzw_decode_init() call.
|
|
||||||
* \return LZW_OK on success, or appropriate error code otherwise.
|
* \return LZW_OK on success, or appropriate error code otherwise.
|
||||||
*/
|
*/
|
||||||
lzw_result lzw_decode(
|
lzw_result lzw_decode(struct lzw_ctx *ctx,
|
||||||
struct lzw_ctx *ctx,
|
const uint8_t *restrict *const restrict data,
|
||||||
uint32_t *written);
|
uint32_t *restrict used);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user