Gitweb links:
...log
http://git.netsurf-browser.org/libnsgif.git/shortlog/eca5a0cf19e5d9efab647c6a6d537c4827553ea1
...commit
http://git.netsurf-browser.org/libnsgif.git/commit/eca5a0cf19e5d9efab647c6a6d537c4827553ea1
...tree
http://git.netsurf-browser.org/libnsgif.git/tree/eca5a0cf19e5d9efab647c6a6d537c4827553ea1
The branch, tlsa/lzw-optimise has been created
at eca5a0cf19e5d9efab647c6a6d537c4827553ea1 (commit)
- Log -----------------------------------------------------------------
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=eca5a0cf19e5d9efab647c6a6d537c4827553ea1
commit eca5a0cf19e5d9efab647c6a6d537c4827553ea1
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
WIP: lzw: Direct output into frame data, avoiding stack.
diff --git a/src/libnsgif.c b/src/libnsgif.c
index cdd5b6b..fb2577c 100644
--- a/src/libnsgif.c
+++ b/src/libnsgif.c
@@ -641,8 +641,8 @@ static gif_result gif__recover_previous_frame(const
gif_animation *gif)
return GIF_OK;
}
-static inline gif_result
-gif__decode(gif_animation *gif,
+static gif_result
+gif__decode_complex(gif_animation *gif,
unsigned int frame,
unsigned int width,
unsigned int height,
@@ -716,6 +716,85 @@ gif__decode(gif_animation *gif,
return ret;
}
+static gif_result
+gif__decode_simple(gif_animation *gif,
+ unsigned int frame,
+ unsigned int height,
+ unsigned int offset_y,
+ uint8_t minimum_code_size,
+ unsigned int *restrict frame_data,
+ unsigned int *restrict colour_table)
+{
+ unsigned int transparency_index;
+ uint32_t pixels = gif->width * height;
+ uint32_t written = 0;
+ gif_result ret = GIF_OK;
+ lzw_result res;
+
+ /* Initialise the LZW decoding */
+ res = lzw_decode_init(gif->lzw_ctx, gif->gif_data,
+ gif->buffer_size, gif->buffer_position,
+ minimum_code_size);
+ if (res != LZW_OK) {
+ return gif_error_from_lzw(res);
+ }
+
+ transparency_index = gif->frames[frame].transparency ?
+ gif->frames[frame].transparency_index :
+ GIF_NO_TRANSPARENCY;
+
+ frame_data += (offset_y * gif->width);
+
+ while (pixels > 0) {
+ res = lzw_decode_map_continuous(gif->lzw_ctx,
+ transparency_index, colour_table,
+ frame_data, pixels, &written);
+ pixels -= written;
+ frame_data += written;
+ if (res != LZW_OK) {
+ /* Unexpected end of frame, try to recover */
+ if (res == LZW_OK_EOD) {
+ ret = GIF_OK;
+ } else {
+ ret = gif_error_from_lzw(res);
+ }
+ break;
+ }
+ }
+
+ if (pixels == 0) {
+ ret = GIF_OK;
+ }
+
+ return ret;
+}
+
+static inline gif_result
+gif__decode(gif_animation *gif,
+ unsigned int frame,
+ unsigned int width,
+ unsigned int height,
+ unsigned int offset_x,
+ unsigned int offset_y,
+ unsigned int interlace,
+ uint8_t minimum_code_size,
+ unsigned int *restrict frame_data,
+ unsigned int *restrict colour_table)
+{
+ gif_result ret;
+
+ if (interlace == false && width == gif->width && offset_x == 0) {
+ ret = gif__decode_simple(gif, frame, height, offset_y,
+ minimum_code_size, frame_data, colour_table);
+ } else {
+ ret = gif__decode_complex(gif, frame, width, height,
+ offset_x, offset_y, interlace,
+ minimum_code_size, frame_data, colour_table);
+ }
+
+ return ret;
+}
+
/**
* decode a gif frame
*
diff --git a/src/lzw.c b/src/lzw.c
index 2f604e4..d555151 100644
--- a/src/lzw.c
+++ b/src/lzw.c
@@ -85,6 +85,9 @@ struct lzw_ctx {
uint32_t output_code; /**< Code that has been partially output. */
uint32_t output_left; /**< Number of values left for output_code. */
+ uint32_t transparency_index;
+ uint32_t *restrict colour_table;
+
/** Output value stack. */
uint8_t stack_base[LZW_DICTIONARY_ENTRY_MAX];
@@ -345,6 +348,54 @@ static inline uint32_t lzw__write_pixels(struct lzw_ctx
*ctx,
return count;
}
+
+/**
+ * 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.
+ * \return Number of pixel values written.
+ */
+static inline uint32_t lzw__write_pixels_map(struct lzw_ctx *ctx,
+ void *buffer,
+ uint32_t length,
+ uint32_t used,
+ uint32_t code,
+ uint32_t left)
+{
+ uint32_t *stack_pos = (uint32_t *)buffer + used;
+ struct lzw_table_entry * const table = ctx->table;
+ uint32_t space = length - used;
+ uint32_t count = left;
+
+ if (count > space) {
+ left = count - space;
+ count = space;
+ } else {
+ left = 0;
+ }
+
+ ctx->output_code = code;
+ ctx->output_left = left;
+
+ for (unsigned i = left; i != 0; i--) {
+ struct lzw_table_entry *entry = table + code;
+ code = entry->extends;
+ }
+
+ stack_pos += count;
+ for (unsigned i = count; i != 0; i--) {
+ struct lzw_table_entry *entry = table + code;
+ --stack_pos;
+ if (entry->value != ctx->transparency_index) {
+ *stack_pos = ctx->colour_table[entry->value];
+ }
+ code = entry->extends;
+ }
+
+ return count;
+}
+
/**
* Fill the LZW stack with decompressed data
*
@@ -452,3 +503,32 @@ lzw_result lzw_decode_continuous(struct lzw_ctx *ctx,
return LZW_OK;
}
+
+/* Exported function, documented in lzw.h */
+lzw_result lzw_decode_map_continuous(struct lzw_ctx *ctx,
+ uint32_t transparency_index,
+ uint32_t *restrict colour_table,
+ uint32_t *restrict data,
+ uint32_t length,
+ uint32_t *restrict used)
+{
+ *used = 0;
+
+ ctx->transparency_index = transparency_index;
+ ctx->colour_table = colour_table;
+
+ if (ctx->output_left != 0) {
+ *used += lzw__write_pixels_map(ctx, data, length, *used,
+ ctx->output_code, ctx->output_left);
+ }
+
+ while (*used != sizeof(ctx->stack_base)) {
+ lzw_result res = lzw__decode(ctx, data, length,
+ lzw__write_pixels_map, used);
+ if (res != LZW_OK) {
+ return res;
+ }
+ }
+
+ return LZW_OK;
+}
diff --git a/src/lzw.h b/src/lzw.h
index ec7709a..9dbcac0 100644
--- a/src/lzw.h
+++ b/src/lzw.h
@@ -106,4 +106,22 @@ lzw_result lzw_decode_continuous(struct lzw_ctx *ctx,
const uint8_t ** const data,
uint32_t *used);
+/**
+ * Read LZW codes, mapping output to colours.
+ *
+ * Ensure anything on the stack is used before calling this, as anything
+ * on the stack before this call will be trampled.
+ *
+ * \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_map_continuous(struct lzw_ctx *ctx,
+ uint32_t transparency_index,
+ uint32_t *restrict colour_table,
+ uint32_t *restrict data,
+ uint32_t length,
+ uint32_t *restrict used);
+
#endif
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=b3ebed6297bb797c1af45b33b448514bf05c46e5
commit b3ebed6297bb797c1af45b33b448514bf05c46e5
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
gif: Handle any uncompressed output before exiting due to error.
diff --git a/src/libnsgif.c b/src/libnsgif.c
index 60209de..cdd5b6b 100644
--- a/src/libnsgif.c
+++ b/src/libnsgif.c
@@ -687,8 +687,6 @@ gif__decode(gif_animation *gif,
const uint8_t *uncompressed;
unsigned row_available;
if (available == 0) {
- res = lzw_decode(gif->lzw_ctx,
- &uncompressed, &available);
if (res != LZW_OK) {
/* Unexpected end of frame, try to
recover */
if (res == LZW_OK_EOD) {
@@ -698,6 +696,8 @@ gif__decode(gif_animation *gif,
}
break;
}
+ res = lzw_decode(gif->lzw_ctx,
+ &uncompressed, &available);
}
row_available = x < available ? x : available;
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=18afa8d0048c86216643ab2e883503ab4c413f38
commit 18afa8d0048c86216643ab2e883503ab4c413f38
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
lzw: Add function for decoding multiple LZW codes at a time.
diff --git a/src/lzw.c b/src/lzw.c
index 8c8911a..2f604e4 100644
--- a/src/lzw.c
+++ b/src/lzw.c
@@ -426,3 +426,29 @@ lzw_result lzw_decode(struct lzw_ctx *ctx,
return lzw__decode(ctx, ctx->stack_base, sizeof(ctx->stack_base),
lzw__write_pixels, used);
}
+
+/* Exported function, documented in lzw.h */
+lzw_result lzw_decode_continuous(struct lzw_ctx *ctx,
+ const uint8_t ** const data,
+ uint32_t *used)
+{
+ *used = 0;
+ *data = ctx->stack_base;
+
+ if (ctx->output_left != 0) {
+ *used += lzw__write_pixels(ctx,
+ ctx->stack_base, sizeof(ctx->stack_base), *used,
+ ctx->output_code, ctx->output_left);
+ }
+
+ while (*used != sizeof(ctx->stack_base)) {
+ lzw_result res = lzw__decode(ctx,
+ ctx->stack_base, sizeof(ctx->stack_base),
+ lzw__write_pixels, used);
+ if (res != LZW_OK) {
+ return res;
+ }
+ }
+
+ return LZW_OK;
+}
diff --git a/src/lzw.h b/src/lzw.h
index 4b6bfab..ec7709a 100644
--- a/src/lzw.h
+++ b/src/lzw.h
@@ -91,4 +91,19 @@ lzw_result lzw_decode(struct lzw_ctx *ctx,
const uint8_t ** const data,
uint32_t *used);
+/**
+ * Read input codes until end of input or output buffer is full.
+ *
+ * Ensure anything on the stack is used before calling this, as anything
+ * on the stack before this call will be trampled.
+ *
+ * \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_continuous(struct lzw_ctx *ctx,
+ const uint8_t ** const data,
+ uint32_t *used);
+
#endif
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=c8f094505a7d53997ef8f8b2d05fc114eee9315b
commit c8f094505a7d53997ef8f8b2d05fc114eee9315b
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
f
diff --git a/src/lzw.h b/src/lzw.h
index 2e82869..4b6bfab 100644
--- a/src/lzw.h
+++ b/src/lzw.h
@@ -77,15 +77,14 @@ lzw_result lzw_decode_init(
uint8_t minimum_code_size);
/**
- * Fill the LZW stack with decompressed data
+ * Read a single LZW code into the output buffer.
*
* Ensure anything on the stack is used before calling this, as anything
* on the stack 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,
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=3f760807f71ffef44a6ac36d0eb0c09c65ad90ba
commit 3f760807f71ffef44a6ac36d0eb0c09c65ad90ba
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
lzw: Return output pointer from decode rather than init.
diff --git a/src/libnsgif.c b/src/libnsgif.c
index 050a961..60209de 100644
--- a/src/libnsgif.c
+++ b/src/libnsgif.c
@@ -654,8 +654,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;
@@ -663,7 +661,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);
}
@@ -672,7 +670,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;
@@ -687,9 +684,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) {
@@ -699,7 +698,6 @@ gif__decode(gif_animation *gif,
}
break;
}
- stack_pos = stack_base;
}
row_available = x < available ? x : available;
@@ -707,7 +705,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 d3e0dcf..8c8911a 100644
--- a/src/lzw.c
+++ b/src/lzw.c
@@ -82,6 +82,9 @@ struct lzw_ctx {
uint32_t table_size; /**< Next position in table to fill. */
+ uint32_t output_code; /**< Code that has been partially output. */
+ uint32_t output_left; /**< Number of values left for output_code. */
+
/** Output value stack. */
uint8_t stack_base[LZW_DICTIONARY_ENTRY_MAX];
@@ -241,8 +244,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;
@@ -264,6 +266,8 @@ lzw_result lzw_decode_init(
ctx->clear_code = (1 << minimum_code_size) + 0;
ctx->eoi_code = (1 << minimum_code_size) + 1;
+ ctx->output_left = 0;
+
/* Initialise the standard table entries */
for (uint32_t i = 0; i < ctx->clear_code; ++i) {
table[i].first = i;
@@ -274,7 +278,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;
}
@@ -306,11 +309,31 @@ static inline void lzw__table_add_entry(
* \return Number of pixel values written.
*/
static inline uint32_t lzw__write_pixels(struct lzw_ctx *ctx,
- uint32_t code)
+ void *buffer,
+ uint32_t length,
+ uint32_t used,
+ uint32_t code,
+ uint32_t left)
{
- uint8_t *stack_pos = ctx->stack_base;
+ uint8_t *stack_pos = (uint8_t *)buffer + used;
struct lzw_table_entry * const table = ctx->table;
- uint32_t count = table[code].count;
+ uint32_t space = length - used;
+ uint32_t count = left;
+
+ if (count > space) {
+ left = count - space;
+ count = space;
+ } else {
+ left = 0;
+ }
+
+ ctx->output_code = code;
+ ctx->output_left = left;
+
+ for (unsigned i = left; i != 0; i--) {
+ struct lzw_table_entry *entry = table + code;
+ code = entry->extends;
+ }
stack_pos += count;
for (unsigned i = count; i != 0; i--) {
@@ -322,9 +345,28 @@ static inline uint32_t lzw__write_pixels(struct lzw_ctx
*ctx,
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 on the stack is used before calling this, as anything
+ * on the stack 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.
+ * \return LZW_OK on success, or appropriate error code otherwise.
+ */
+static inline lzw_result lzw__decode(struct lzw_ctx *ctx,
+ void *buffer,
+ uint32_t length,
+ uint32_t (*write_pixels)(struct lzw_ctx *ctx,
+ void *buffer,
+ uint32_t length,
+ uint32_t used,
+ uint32_t code,
+ uint32_t left),
+ uint32_t *used)
{
lzw_result res;
uint32_t code;
@@ -362,7 +404,8 @@ lzw_result lzw_decode(struct lzw_ctx *ctx,
}
}
- *written += lzw__write_pixels(ctx, code);
+ *used += write_pixels(ctx, buffer, length, *used, code,
+ ctx->table[code].count);
}
/* Store details of this code as "previous code" to the context. */
@@ -372,3 +415,14 @@ 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 ** const data,
+ uint32_t *used)
+{
+ *used = 0;
+ *data = ctx->stack_base;
+ return lzw__decode(ctx, ctx->stack_base, sizeof(ctx->stack_base),
+ lzw__write_pixels, used);
+}
diff --git a/src/lzw.h b/src/lzw.h
index a4a58fc..2e82869 100644
--- a/src/lzw.h
+++ b/src/lzw.h
@@ -74,8 +74,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);
/**
* Fill the LZW stack with decompressed data
@@ -89,8 +88,8 @@ lzw_result lzw_decode_init(
* lzw_decode_init() call.
* \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 ** const data,
+ uint32_t *used);
#endif
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=ad9ddb59c4f0607821e52919a5ffdd09a1090a4e
commit ad9ddb59c4f0607821e52919a5ffdd09a1090a4e
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
gif: Frame decoding: Rearrange for readability.
diff --git a/src/libnsgif.c b/src/libnsgif.c
index 2db34df..050a961 100644
--- a/src/libnsgif.c
+++ b/src/libnsgif.c
@@ -656,7 +656,7 @@ gif__decode(gif_animation *gif,
unsigned int transparency_index;
const uint8_t *stack_base;
const uint8_t *stack_pos;
- uint32_t written = 0;
+ uint32_t available = 0;
gif_result ret = GIF_OK;
lzw_result res;
@@ -687,23 +687,9 @@ gif__decode(gif_animation *gif,
x = width;
while (x > 0) {
- if (written > 0) {
- unsigned burst_bytes = written;
- if (burst_bytes > x) {
- burst_bytes = x;
- }
- x -= burst_bytes;
- written -= burst_bytes;
- while (burst_bytes-- > 0) {
- register unsigned int colour;
- colour = *stack_pos++;
- if (colour != transparency_index) {
- *frame_scanline =
colour_table[colour];
- }
- frame_scanline++;
- }
- } else {
- res = lzw_decode(gif->lzw_ctx, &written);
+ unsigned row_available;
+ if (available == 0) {
+ res = lzw_decode(gif->lzw_ctx, &available);
if (res != LZW_OK) {
/* Unexpected end of frame, try to
recover */
if (res == LZW_OK_EOD) {
@@ -715,6 +701,18 @@ gif__decode(gif_animation *gif,
}
stack_pos = stack_base;
}
+
+ row_available = x < available ? x : available;
+ x -= row_available;
+ available -= row_available;
+ while (row_available-- > 0) {
+ register unsigned int colour;
+ colour = *stack_pos++;
+ if (colour != transparency_index) {
+ *frame_scanline = colour_table[colour];
+ }
+ frame_scanline++;
+ }
}
}
return ret;
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=19bbdfd0e2cea3d133d3de1d275496060d069376
commit 19bbdfd0e2cea3d133d3de1d275496060d069376
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
gif: Frame decoding: Simplify transparency check.
diff --git a/src/libnsgif.c b/src/libnsgif.c
index 91dbb42..2db34df 100644
--- a/src/libnsgif.c
+++ b/src/libnsgif.c
@@ -42,6 +42,9 @@
/** Transparent colour */
#define GIF_TRANSPARENT_COLOUR 0x00
+/** No transparency */
+#define GIF_NO_TRANSPARENCY (0xFFFFFFFFu)
+
/* GIF Flags */
#define GIF_FRAME_COMBINE 1
#define GIF_FRAME_CLEAR 2
@@ -650,6 +653,7 @@ gif__decode(gif_animation *gif,
unsigned int *restrict frame_data,
unsigned int *restrict colour_table)
{
+ unsigned int transparency_index;
const uint8_t *stack_base;
const uint8_t *stack_pos;
uint32_t written = 0;
@@ -664,6 +668,10 @@ gif__decode(gif_animation *gif,
return gif_error_from_lzw(res);
}
+ transparency_index = gif->frames[frame].transparency ?
+ gif->frames[frame].transparency_index :
+ GIF_NO_TRANSPARENCY;
+
stack_pos = stack_base;
for (unsigned int y = 0; y < height; y++) {
unsigned int x;
@@ -687,11 +695,9 @@ gif__decode(gif_animation *gif,
x -= burst_bytes;
written -= burst_bytes;
while (burst_bytes-- > 0) {
- register unsigned char colour;
+ register unsigned int colour;
colour = *stack_pos++;
- if (((gif->frames[frame].transparency)
&&
- (colour !=
gif->frames[frame].transparency_index)) ||
-
(!gif->frames[frame].transparency)) {
+ if (colour != transparency_index) {
*frame_scanline =
colour_table[colour];
}
frame_scanline++;
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=a37a58757033a143ca6055ddf57111f5bdc6afec
commit a37a58757033a143ca6055ddf57111f5bdc6afec
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
lzw: Remove written member from context.
Not needed now that clear codes are handled normally.
diff --git a/src/lzw.c b/src/lzw.c
index d7e7a04..d3e0dcf 100644
--- a/src/lzw.c
+++ b/src/lzw.c
@@ -83,7 +83,6 @@ struct lzw_ctx {
uint32_t table_size; /**< Next position in table to fill. */
/** Output value stack. */
- uint32_t written;
uint8_t stack_base[LZW_DICTIONARY_ENTRY_MAX];
/** LZW decode table. Generated during decode. */
@@ -302,13 +301,14 @@ 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] code LZW code to output values for.
+ * \return Number of pixel values written.
*/
-static inline void lzw__write_pixels(struct lzw_ctx *ctx,
+static inline uint32_t lzw__write_pixels(struct lzw_ctx *ctx,
uint32_t code)
{
- uint8_t *stack_pos = ctx->stack_base + ctx->written;
+ uint8_t *stack_pos = ctx->stack_base;
struct lzw_table_entry * const table = ctx->table;
uint32_t count = table[code].count;
@@ -319,8 +319,7 @@ static inline void lzw__write_pixels(struct lzw_ctx *ctx,
code = entry->extends;
}
- ctx->written += count;
- return;
+ return count;
}
/* Exported function, documented in lzw.h */
@@ -330,8 +329,6 @@ 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) {
@@ -365,7 +362,7 @@ lzw_result lzw_decode(struct lzw_ctx *ctx,
}
}
- lzw__write_pixels(ctx, code);
+ *written += lzw__write_pixels(ctx, code);
}
/* Store details of this code as "previous code" to the context. */
@@ -373,7 +370,5 @@ lzw_result lzw_decode(struct lzw_ctx *ctx,
ctx->prev_code_count = ctx->table[code].count;
ctx->prev_code = code;
- *written = ctx->written;
-
return LZW_OK;
}
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=7aa7e7cbf5815d833bac688990e9e4d48226a83b
commit 7aa7e7cbf5815d833bac688990e9e4d48226a83b
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
lzw: Adapt main code handling to handle clear codes too.
diff --git a/src/lzw.c b/src/lzw.c
index 3db65c3..d7e7a04 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_DICTIONARY_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_DICTIONARY_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;
}
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=92850849f8cefe78c6abad56623f7ee2941fc340
commit 92850849f8cefe78c6abad56623f7ee2941fc340
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
lzw: Output values in picture order.
diff --git a/src/libnsgif.c b/src/libnsgif.c
index 6b73e2f..91dbb42 100644
--- a/src/libnsgif.c
+++ b/src/libnsgif.c
@@ -652,17 +652,19 @@ gif__decode(gif_animation *gif,
{
const uint8_t *stack_base;
const uint8_t *stack_pos;
+ uint32_t written = 0;
gif_result ret = GIF_OK;
lzw_result res;
/* 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, &stack_pos);
+ minimum_code_size, &stack_base);
if (res != LZW_OK) {
return gif_error_from_lzw(res);
}
+ stack_pos = stack_base;
for (unsigned int y = 0; y < height; y++) {
unsigned int x;
unsigned int decode_y;
@@ -675,21 +677,18 @@ gif__decode(gif_animation *gif,
}
frame_scanline = frame_data + offset_x + (decode_y *
gif->width);
- /* Rather than decoding pixel by pixel, we try to burst
- * out streams of data to remove the need for end-of
- * data checks every pixel.
- */
x = width;
while (x > 0) {
- unsigned int burst_bytes = (stack_pos - stack_base);
- if (burst_bytes > 0) {
+ if (written > 0) {
+ unsigned burst_bytes = written;
if (burst_bytes > x) {
burst_bytes = x;
}
x -= burst_bytes;
+ written -= burst_bytes;
while (burst_bytes-- > 0) {
register unsigned char colour;
- colour = *--stack_pos;
+ colour = *stack_pos++;
if (((gif->frames[frame].transparency)
&&
(colour !=
gif->frames[frame].transparency_index)) ||
(!gif->frames[frame].transparency)) {
@@ -698,7 +697,7 @@ gif__decode(gif_animation *gif,
frame_scanline++;
}
} else {
- res = lzw_decode(gif->lzw_ctx, &stack_pos);
+ res = lzw_decode(gif->lzw_ctx, &written);
if (res != LZW_OK) {
/* Unexpected end of frame, try to
recover */
if (res == LZW_OK_EOD) {
@@ -708,10 +707,10 @@ gif__decode(gif_animation *gif,
}
break;
}
+ stack_pos = stack_base;
}
}
}
-
return ret;
}
diff --git a/src/lzw.c b/src/lzw.c
index d9b4571..3db65c3 100644
--- a/src/lzw.c
+++ b/src/lzw.c
@@ -83,6 +83,7 @@ struct lzw_ctx {
uint32_t table_size; /**< Next position in table to fill. */
/** Output value stack. */
+ uint32_t written;
uint8_t stack_base[LZW_DICTIONARY_ENTRY_MAX];
/** LZW decode table. Generated during decode. */
@@ -223,15 +224,12 @@ static inline lzw_result lzw__read_code(
* Clear LZW code table.
*
* \param[in] ctx LZW reading context, updated.
- * \param[out] stack_pos_out Returns current stack position.
* \return LZW_OK or error code.
*/
static lzw_result lzw__clear_codes(
- struct lzw_ctx *ctx,
- const uint8_t ** const stack_pos_out)
+ struct lzw_ctx *ctx)
{
uint32_t code;
- uint8_t *stack_pos;
/* Reset table building context */
ctx->code_size = ctx->initial_code_size;
@@ -258,10 +256,8 @@ static lzw_result lzw__clear_codes(
ctx->prev_code_count = 1;
/* Reset the stack, and add first non-clear code added as first item. */
- stack_pos = ctx->stack_base;
- *stack_pos++ = code;
+ ctx->stack_base[ctx->written++] = code;
- *stack_pos_out = stack_pos;
return LZW_OK;
}
@@ -273,8 +269,7 @@ lzw_result lzw_decode_init(
uint32_t compressed_data_len,
uint32_t compressed_data_pos,
uint8_t minimum_code_size,
- const uint8_t ** const stack_base_out,
- const uint8_t ** const stack_pos_out)
+ const uint8_t ** const stack_base_out)
{
struct lzw_table_entry *table = ctx->table;
@@ -303,8 +298,10 @@ lzw_result lzw_decode_init(
table[i].count = 1;
}
+ ctx->written = 0;
+
*stack_base_out = ctx->stack_base;
- return lzw__clear_codes(ctx, stack_pos_out);
+ return lzw__clear_codes(ctx);
}
/**
@@ -332,32 +329,28 @@ static inline void lzw__table_add_entry(
*
* \param[in] ctx LZW reading context, updated.
* \param[in] code LZW code to output values for.
- * \param[out] stack_pos_out Returns current stack position.
- * There are `stack_pos_out - ctx->stack_base`
- * current stack entries.
*/
static inline void lzw__write_pixels(struct lzw_ctx *ctx,
- uint32_t code,
- const uint8_t ** const stack_pos_out)
+ uint32_t code)
{
- uint8_t *stack_pos = ctx->stack_base;
- uint32_t clear_code = ctx->clear_code;
+ uint8_t *stack_pos = ctx->stack_base + ctx->written;
struct lzw_table_entry * const table = ctx->table;
+ uint32_t count = table[code].count;
- while (code > clear_code) {
+ stack_pos += count;
+ for (unsigned i = count; i != 0; i--) {
struct lzw_table_entry *entry = table + code;
- *stack_pos++ = entry->value;
+ *--stack_pos = entry->value;
code = entry->extends;
}
- *stack_pos++ = table[code].value;
- *stack_pos_out = stack_pos;
+ ctx->written += count;
return;
}
/* Exported function, documented in lzw.h */
lzw_result lzw_decode(struct lzw_ctx *ctx,
- const uint8_t ** const stack_pos_out)
+ uint32_t *written)
{
lzw_result res;
uint32_t code;
@@ -371,7 +364,12 @@ lzw_result lzw_decode(struct lzw_ctx *ctx,
/* Handle the new code */
if (code == ctx->clear_code) {
/* Got Clear code */
- return lzw__clear_codes(ctx, stack_pos_out);
+ res = lzw__clear_codes(ctx);
+ if (res == LZW_OK) {
+ *written = ctx->written;
+ ctx->written = 0;
+ }
+ return res;
} else if (code == ctx->eoi_code) {
/* Got End of Information code */
@@ -400,6 +398,10 @@ 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, stack_pos_out);
+ lzw__write_pixels(ctx, code);
+
+ *written = ctx->written;
+ ctx->written = 0;
+
return LZW_OK;
}
diff --git a/src/lzw.h b/src/lzw.h
index 888526e..a4a58fc 100644
--- a/src/lzw.h
+++ b/src/lzw.h
@@ -67,9 +67,6 @@ void lzw_context_destroy(
* of a size byte at sub-block start.
* \param[in] minimum_code_size The LZW Minimum Code Size.
* \param[out] stack_base_out Returns base of decompressed data stack.
- * \param[out] stack_pos_out Returns current stack position.
- * There are `stack_pos_out - stack_base_out`
- * current stack entries.
* \return LZW_OK on success, or appropriate error code otherwise.
*/
lzw_result lzw_decode_init(
@@ -78,8 +75,7 @@ lzw_result lzw_decode_init(
uint32_t compressed_data_len,
uint32_t compressed_data_pos,
uint8_t minimum_code_size,
- const uint8_t ** const stack_base_out,
- const uint8_t ** const stack_pos_out);
+ const uint8_t ** const stack_base_out);
/**
* Fill the LZW stack with decompressed data
@@ -87,19 +83,14 @@ lzw_result lzw_decode_init(
* Ensure anything on the stack is used before calling this, as anything
* on the stack before this call will be trampled.
*
- * Caller does not own `stack_pos_out`.
- *
- * \param[in] ctx LZW reading context, updated.
- * \param[out] stack_pos_out Returns current stack position.
- * Use with `stack_base_out` value from previous
- * lzw_decode_init() call.
- * There are `stack_pos_out - stack_base_out`
- * current stack entries.
+ * \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.
* \return LZW_OK on success, or appropriate error code otherwise.
*/
lzw_result lzw_decode(
struct lzw_ctx *ctx,
- const uint8_t ** const stack_pos_out);
-
+ uint32_t *written);
#endif
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=80d152f7e3a67b65302a467ad1c7dd5c03ff3b29
commit 80d152f7e3a67b65302a467ad1c7dd5c03ff3b29
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
lzw: Store code's value count in table.
diff --git a/src/lzw.c b/src/lzw.c
index 6371513..d9b4571 100644
--- a/src/lzw.c
+++ b/src/lzw.c
@@ -58,6 +58,7 @@ struct lzw_read_ctx {
struct lzw_table_entry {
uint8_t value; /**< Last value for record ending at entry. */
uint8_t first; /**< First value in entry's entire record. */
+ uint16_t count; /**< Count of values in this entry's record. */
uint16_t extends; /**< Offset in table to previous entry. */
};
@@ -69,6 +70,7 @@ struct lzw_ctx {
uint32_t prev_code; /**< Code read from input previously. */
uint32_t prev_code_first; /**< First value of previous code. */
+ uint32_t prev_code_count; /**< Total values for previous code. */
uint32_t initial_code_size; /**< Starting LZW code size. */
@@ -253,6 +255,7 @@ static lzw_result lzw__clear_codes(
/* 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. */
stack_pos = ctx->stack_base;
@@ -297,6 +300,7 @@ lzw_result lzw_decode_init(
for (uint32_t i = 0; i < ctx->clear_code; ++i) {
table[i].first = i;
table[i].value = i;
+ table[i].count = 1;
}
*stack_base_out = ctx->stack_base;
@@ -317,6 +321,7 @@ static inline void lzw__table_add_entry(
entry->value = code;
entry->first = ctx->prev_code_first;
+ entry->count = ctx->prev_code_count + 1;
entry->extends = ctx->prev_code;
ctx->table_size++;
@@ -392,6 +397,7 @@ lzw_result lzw_decode(struct lzw_ctx *ctx,
/* Store details of this code as "previous code" to the context. */
ctx->prev_code_first = ctx->table[code].first;
+ ctx->prev_code_count = ctx->table[code].count;
ctx->prev_code = code;
lzw__write_pixels(ctx, code, stack_pos_out);
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=0ecaf6688dfcfb9a36824df9b13fa75ce02e554d
commit 0ecaf6688dfcfb9a36824df9b13fa75ce02e554d
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
gif: Split out gif frame data decode.
diff --git a/src/libnsgif.c b/src/libnsgif.c
index 7c40eeb..6b73e2f 100644
--- a/src/libnsgif.c
+++ b/src/libnsgif.c
@@ -638,6 +638,83 @@ static gif_result gif__recover_previous_frame(const
gif_animation *gif)
return GIF_OK;
}
+static inline gif_result
+gif__decode(gif_animation *gif,
+ unsigned int frame,
+ unsigned int width,
+ unsigned int height,
+ unsigned int offset_x,
+ unsigned int offset_y,
+ unsigned int interlace,
+ uint8_t minimum_code_size,
+ unsigned int *restrict frame_data,
+ unsigned int *restrict colour_table)
+{
+ const uint8_t *stack_base;
+ const uint8_t *stack_pos;
+ gif_result ret = GIF_OK;
+ lzw_result res;
+
+ /* 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, &stack_pos);
+ if (res != LZW_OK) {
+ return gif_error_from_lzw(res);
+ }
+
+ for (unsigned int y = 0; y < height; y++) {
+ unsigned int x;
+ unsigned int decode_y;
+ unsigned int *frame_scanline;
+
+ if (interlace) {
+ decode_y = gif_interlaced_line(height, y) + offset_y;
+ } else {
+ decode_y = y + offset_y;
+ }
+ frame_scanline = frame_data + offset_x + (decode_y *
gif->width);
+
+ /* Rather than decoding pixel by pixel, we try to burst
+ * out streams of data to remove the need for end-of
+ * data checks every pixel.
+ */
+ x = width;
+ while (x > 0) {
+ unsigned int burst_bytes = (stack_pos - stack_base);
+ if (burst_bytes > 0) {
+ if (burst_bytes > x) {
+ burst_bytes = x;
+ }
+ x -= burst_bytes;
+ while (burst_bytes-- > 0) {
+ register unsigned char colour;
+ colour = *--stack_pos;
+ if (((gif->frames[frame].transparency)
&&
+ (colour !=
gif->frames[frame].transparency_index)) ||
+
(!gif->frames[frame].transparency)) {
+ *frame_scanline =
colour_table[colour];
+ }
+ frame_scanline++;
+ }
+ } else {
+ res = lzw_decode(gif->lzw_ctx, &stack_pos);
+ if (res != LZW_OK) {
+ /* Unexpected end of frame, try to
recover */
+ if (res == LZW_OK_EOD) {
+ ret = GIF_OK;
+ } else {
+ ret = gif_error_from_lzw(res);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
/**
* decode a gif frame
*
@@ -658,11 +735,8 @@ gif_internal_decode_frame(gif_animation *gif,
unsigned int flags, colour_table_size, interlace;
unsigned int *colour_table;
unsigned int *frame_data = 0; // Set to 0 for no warnings
- unsigned int *frame_scanline;
unsigned int save_buffer_position;
unsigned int return_value = 0;
- unsigned int x, y, decode_y, burst_bytes;
- register unsigned char colour;
/* Ensure this frame is supposed to be decoded */
if (gif->frames[frame].display == false) {
@@ -810,10 +884,6 @@ gif_internal_decode_frame(gif_animation *gif,
/* If we are clearing the image we just clear, if not decode */
if (!clear_image) {
- lzw_result res;
- const uint8_t *stack_base;
- const uint8_t *stack_pos;
-
/* Ensure we have enough data for a 1-byte LZW code size +
* 1-byte gif trailer
*/
@@ -877,62 +947,15 @@ gif_internal_decode_frame(gif_animation *gif,
gif->decoded_frame = frame;
gif->buffer_position = (gif_data - gif->gif_data) + 1;
- /* Initialise the LZW decoding */
- res = lzw_decode_init(gif->lzw_ctx, gif->gif_data,
- gif->buffer_size, gif->buffer_position,
- gif_data[0], &stack_base, &stack_pos);
- if (res != LZW_OK) {
- return gif_error_from_lzw(res);
- }
-
- /* Decompress the data */
- for (y = 0; y < height; y++) {
- if (interlace) {
- decode_y = gif_interlaced_line(height, y) +
offset_y;
- } else {
- decode_y = y + offset_y;
- }
- frame_scanline = frame_data + offset_x + (decode_y *
gif->width);
-
- /* Rather than decoding pixel by pixel, we try to burst
- * out streams of data to remove the need for end-of
- * data checks every pixel.
- */
- x = width;
- while (x > 0) {
- burst_bytes = (stack_pos - stack_base);
- if (burst_bytes > 0) {
- if (burst_bytes > x) {
- burst_bytes = x;
- }
- x -= burst_bytes;
- while (burst_bytes-- > 0) {
- colour = *--stack_pos;
- if
(((gif->frames[frame].transparency) &&
- (colour !=
gif->frames[frame].transparency_index)) ||
-
(!gif->frames[frame].transparency)) {
- *frame_scanline =
colour_table[colour];
- }
- frame_scanline++;
- }
- } else {
- res = lzw_decode(gif->lzw_ctx,
&stack_pos);
- if (res != LZW_OK) {
- /* Unexpected end of frame,
try to recover */
- if (res == LZW_OK_EOD) {
- return_value = GIF_OK;
- } else {
- return_value =
gif_error_from_lzw(res);
- }
- goto gif_decode_frame_exit;
- }
- }
- }
- }
+ return_value = gif__decode(gif, frame, width, height,
+ offset_x, offset_y, interlace, gif_data[0],
+ frame_data, colour_table);
} else {
/* Clear our frame */
if (gif->frames[frame].disposal_method == GIF_FRAME_CLEAR) {
+ unsigned int y;
for (y = 0; y < height; y++) {
+ unsigned int *frame_scanline;
frame_scanline = frame_data + offset_x +
((offset_y + y) * gif->width);
if (gif->frames[frame].transparency) {
memset(frame_scanline,
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=680babcd5768289ae72434c5d89c351a505a2136
commit 680babcd5768289ae72434c5d89c351a505a2136
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
lzw: Rename a bunch of structures, functions and variables.
new_code -> code
last_value -> value
first_value -> first
previous_entry -> extends
current_entry -> table_size
previous_code -> prev_code
previous_code_first -> prev_code_first
current_code_size -> code_size
current_code_size_max -> code_max
lzw__next_code -> lzw_read_code
diff --git a/src/lzw.c b/src/lzw.c
index 61093bb..6371513 100644
--- a/src/lzw.c
+++ b/src/lzw.c
@@ -21,7 +21,7 @@
* Decoder for GIF LZW data.
*/
-/** Maximum number of dictionary entries. */
+/** Maximum number of table entries. */
#define LZW_DICTIONARY_ENTRY_MAX (1u << LZW_CODE_MAX)
/**
@@ -46,45 +46,45 @@ struct lzw_read_ctx {
};
/**
- * LZW dictionary entry.
+ * LZW table entry.
*
- * Records in the dictionary are composed of 1 or more entries.
- * Entries point to previous entries which can be followed to compose
+ * Records in the table are composed of 1 or more entries.
+ * Entries refer to the entry they extend which can be followed to compose
* the complete record. To compose the record in reverse order, take
- * the `last_value` from each entry, and move to the previous entry.
- * If the previous_entry's index is < the current clear_code, then it
+ * the `value` from each entry, and move to the entry it extends.
+ * If the extended entries index is < the current clear_code, then it
* is the last entry in the record.
*/
-struct lzw_dictionary_entry {
- uint8_t last_value; /**< Last value for record ending at entry. */
- uint8_t first_value; /**< First value for entry's record. */
- uint16_t previous_entry; /**< Offset in dictionary to previous entry. */
+struct lzw_table_entry {
+ uint8_t value; /**< Last value for record ending at entry. */
+ uint8_t first; /**< First value in entry's entire record. */
+ uint16_t extends; /**< Offset in table to previous entry. */
};
/**
* LZW decompression context.
*/
struct lzw_ctx {
- /** Input reading context */
- struct lzw_read_ctx input;
+ struct lzw_read_ctx input; /**< Input reading context */
- uint32_t previous_code; /**< Code read from input previously. */
- uint32_t previous_code_first; /**< First value of previous code. */
+ uint32_t prev_code; /**< Code read from input previously. */
+ uint32_t prev_code_first; /**< First value of previous code. */
- uint32_t initial_code_size; /**< Starting LZW code size. */
- uint32_t current_code_size; /**< Current LZW code size. */
- uint32_t current_code_size_max; /**< Max code value for current size. */
+ uint32_t initial_code_size; /**< Starting LZW code size. */
+
+ uint32_t code_size; /**< Current LZW code size. */
+ uint32_t code_max; /**< Max code value for current code size. */
uint32_t clear_code; /**< Special Clear code value */
uint32_t eoi_code; /**< Special End of Information code value */
- uint32_t current_entry; /**< Next position in table to fill. */
+ uint32_t table_size; /**< Next position in table to fill. */
/** Output value stack. */
uint8_t stack_base[LZW_DICTIONARY_ENTRY_MAX];
- /** LZW decode dictionary. Generated during decode. */
- struct lzw_dictionary_entry table[LZW_DICTIONARY_ENTRY_MAX];
+ /** LZW decode table. Generated during decode. */
+ struct lzw_table_entry table[LZW_DICTIONARY_ENTRY_MAX];
};
@@ -155,7 +155,7 @@ static lzw_result lzw__block_advance(struct lzw_read_ctx
*ctx)
* \param[out] code_out Returns an LZW code on success.
* \return LZW_OK or LZW_OK_EOD on success, appropriate error otherwise.
*/
-static inline lzw_result lzw__next_code(
+static inline lzw_result lzw__read_code(
struct lzw_read_ctx *ctx,
uint8_t code_size,
uint32_t *code_out)
@@ -218,7 +218,7 @@ static inline lzw_result lzw__next_code(
/**
- * Clear LZW code dictionary.
+ * Clear LZW code table.
*
* \param[in] ctx LZW reading context, updated.
* \param[out] stack_pos_out Returns current stack position.
@@ -231,28 +231,28 @@ static lzw_result lzw__clear_codes(
uint32_t code;
uint8_t *stack_pos;
- /* Reset dictionary building context */
- ctx->current_code_size = ctx->initial_code_size;
- ctx->current_code_size_max = (1 << ctx->initial_code_size) - 1;
- ctx->current_entry = ctx->eoi_code + 1;
+ /* 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__next_code(&ctx->input,
- ctx->current_code_size, &code);
+ 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 dictionary. */
+ /* 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->previous_code = code;
- ctx->previous_code_first = code;
+ ctx->prev_code = code;
+ ctx->prev_code_first = code;
/* Reset the stack, and add first non-clear code added as first item. */
stack_pos = ctx->stack_base;
@@ -273,7 +273,7 @@ lzw_result lzw_decode_init(
const uint8_t ** const stack_base_out,
const uint8_t ** const stack_pos_out)
{
- struct lzw_dictionary_entry *table = ctx->table;
+ struct lzw_table_entry *table = ctx->table;
if (minimum_code_size >= LZW_CODE_MAX) {
return LZW_BAD_ICODE;
@@ -287,16 +287,16 @@ lzw_result lzw_decode_init(
ctx->input.sb_bit = 0;
ctx->input.sb_bit_count = 0;
- /* Initialise the dictionary building context */
+ /* Initialise the table building context */
ctx->initial_code_size = minimum_code_size + 1;
ctx->clear_code = (1 << minimum_code_size) + 0;
ctx->eoi_code = (1 << minimum_code_size) + 1;
- /* Initialise the standard dictionary entries */
+ /* Initialise the standard table entries */
for (uint32_t i = 0; i < ctx->clear_code; ++i) {
- table[i].first_value = i;
- table[i].last_value = i;
+ table[i].first = i;
+ table[i].value = i;
}
*stack_base_out = ctx->stack_base;
@@ -304,22 +304,22 @@ lzw_result lzw_decode_init(
}
/**
- * Create new dictionary entry.
+ * Create new table entry.
*
* \param[in] ctx LZW reading context, updated.
- * \param[in] code Last value code for new dictionary entry.
+ * \param[in] code Last value code for new table entry.
*/
-static inline void lzw__dictionary_add_entry(
+static inline void lzw__table_add_entry(
struct lzw_ctx *ctx,
uint32_t code)
{
- struct lzw_dictionary_entry *entry = &ctx->table[ctx->current_entry];
+ struct lzw_table_entry *entry = &ctx->table[ctx->table_size];
- entry->last_value = code;
- entry->first_value = ctx->previous_code_first;
- entry->previous_entry = ctx->previous_code;
+ entry->value = code;
+ entry->first = ctx->prev_code_first;
+ entry->extends = ctx->prev_code;
- ctx->current_entry++;
+ ctx->table_size++;
}
/**
@@ -337,14 +337,14 @@ static inline void lzw__write_pixels(struct lzw_ctx *ctx,
{
uint8_t *stack_pos = ctx->stack_base;
uint32_t clear_code = ctx->clear_code;
- struct lzw_dictionary_entry * const table = ctx->table;
+ struct lzw_table_entry * const table = ctx->table;
while (code > clear_code) {
- struct lzw_dictionary_entry *entry = table + code;
- *stack_pos++ = entry->last_value;
- code = entry->previous_entry;
+ struct lzw_table_entry *entry = table + code;
+ *stack_pos++ = entry->value;
+ code = entry->extends;
}
- *stack_pos++ = table[code].last_value;
+ *stack_pos++ = table[code].value;
*stack_pos_out = stack_pos;
return;
@@ -355,47 +355,45 @@ lzw_result lzw_decode(struct lzw_ctx *ctx,
const uint8_t ** const stack_pos_out)
{
lzw_result res;
- uint32_t code_new;
- uint32_t current_entry = ctx->current_entry;
+ uint32_t code;
/* Get a new code from the input */
- res = lzw__next_code(&ctx->input, ctx->current_code_size, &code_new);
+ res = lzw__read_code(&ctx->input, ctx->code_size, &code);
if (res != LZW_OK) {
return res;
}
/* Handle the new code */
- if (code_new == ctx->clear_code) {
+ if (code == ctx->clear_code) {
/* Got Clear code */
return lzw__clear_codes(ctx, stack_pos_out);
- } else if (code_new == ctx->eoi_code) {
+ } else if (code == ctx->eoi_code) {
/* Got End of Information code */
return LZW_EOI_CODE;
- } else if (code_new > current_entry) {
+ } else if (code > ctx->table_size) {
/* Code is invalid */
return LZW_BAD_CODE;
}
- if (current_entry < LZW_DICTIONARY_ENTRY_MAX) {
- lzw__dictionary_add_entry(ctx, (code_new < current_entry) ?
- ctx->table[code_new].first_value :
- ctx->previous_code_first);
+ if (ctx->table_size < LZW_DICTIONARY_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 (current_entry == ctx->current_code_size_max &&
- ctx->current_code_size < LZW_CODE_MAX) {
- ctx->current_code_size++;
- ctx->current_code_size_max =
- (1 << ctx->current_code_size) - 1;
+ if (size == ctx->code_max && ctx->code_size < LZW_CODE_MAX) {
+ ctx->code_size++;
+ ctx->code_max = (1 << ctx->code_size) - 1;
}
}
/* Store details of this code as "previous code" to the context. */
- ctx->previous_code_first = ctx->table[code_new].first_value;
- ctx->previous_code = code_new;
+ ctx->prev_code_first = ctx->table[code].first;
+ ctx->prev_code = code;
- lzw__write_pixels(ctx, code_new, stack_pos_out);
+ lzw__write_pixels(ctx, code, stack_pos_out);
return LZW_OK;
}
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=01faec4a877bba33a7fe1ad8db8d91288548c1a0
commit 01faec4a877bba33a7fe1ad8db8d91288548c1a0
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
lzw: Split out output writing.
diff --git a/src/lzw.c b/src/lzw.c
index 8f2d5f2..61093bb 100644
--- a/src/lzw.c
+++ b/src/lzw.c
@@ -322,16 +322,41 @@ static inline void lzw__dictionary_add_entry(
ctx->current_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[out] stack_pos_out Returns current stack position.
+ * There are `stack_pos_out - ctx->stack_base`
+ * current stack entries.
+ */
+static inline void lzw__write_pixels(struct lzw_ctx *ctx,
+ uint32_t code,
+ const uint8_t ** const stack_pos_out)
+{
+ uint8_t *stack_pos = ctx->stack_base;
+ uint32_t clear_code = ctx->clear_code;
+ struct lzw_dictionary_entry * const table = ctx->table;
+
+ while (code > clear_code) {
+ struct lzw_dictionary_entry *entry = table + code;
+ *stack_pos++ = entry->last_value;
+ code = entry->previous_entry;
+ }
+ *stack_pos++ = table[code].last_value;
+
+ *stack_pos_out = stack_pos;
+ return;
+}
+
/* Exported function, documented in lzw.h */
lzw_result lzw_decode(struct lzw_ctx *ctx,
const uint8_t ** const stack_pos_out)
{
lzw_result res;
uint32_t code_new;
- uint8_t *stack_pos = ctx->stack_base;
- uint32_t clear_code = ctx->clear_code;
uint32_t current_entry = ctx->current_entry;
- struct lzw_dictionary_entry * const table = ctx->table;
/* Get a new code from the input */
res = lzw__next_code(&ctx->input, ctx->current_code_size, &code_new);
@@ -340,7 +365,7 @@ lzw_result lzw_decode(struct lzw_ctx *ctx,
}
/* Handle the new code */
- if (code_new == clear_code) {
+ if (code_new == ctx->clear_code) {
/* Got Clear code */
return lzw__clear_codes(ctx, stack_pos_out);
@@ -355,7 +380,7 @@ lzw_result lzw_decode(struct lzw_ctx *ctx,
if (current_entry < LZW_DICTIONARY_ENTRY_MAX) {
lzw__dictionary_add_entry(ctx, (code_new < current_entry) ?
- table[code_new].first_value :
+ ctx->table[code_new].first_value :
ctx->previous_code_first);
/* Ensure code size is increased, if needed. */
@@ -368,17 +393,9 @@ lzw_result lzw_decode(struct lzw_ctx *ctx,
}
/* Store details of this code as "previous code" to the context. */
- ctx->previous_code_first = table[code_new].first_value;
+ ctx->previous_code_first = ctx->table[code_new].first_value;
ctx->previous_code = code_new;
- /* Put data for this code on output stack. */
- while (code_new > clear_code) {
- struct lzw_dictionary_entry *entry = table + code_new;
- *stack_pos++ = entry->last_value;
- code_new = entry->previous_entry;
- }
- *stack_pos++ = table[code_new].last_value;
-
- *stack_pos_out = stack_pos;
+ lzw__write_pixels(ctx, code_new, stack_pos_out);
return LZW_OK;
}
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=d59e5eb2ec7db3009c6a7054c84dcae9273038c5
commit d59e5eb2ec7db3009c6a7054c84dcae9273038c5
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
lzw: Rename minimum_code_size to match what it's called in spec.
diff --git a/src/lzw.c b/src/lzw.c
index 8b3e472..8f2d5f2 100644
--- a/src/lzw.c
+++ b/src/lzw.c
@@ -269,13 +269,13 @@ lzw_result lzw_decode_init(
const uint8_t *compressed_data,
uint32_t compressed_data_len,
uint32_t compressed_data_pos,
- uint8_t code_size,
+ uint8_t minimum_code_size,
const uint8_t ** const stack_base_out,
const uint8_t ** const stack_pos_out)
{
struct lzw_dictionary_entry *table = ctx->table;
- if (code_size >= LZW_CODE_MAX) {
+ if (minimum_code_size >= LZW_CODE_MAX) {
return LZW_BAD_ICODE;
}
@@ -288,10 +288,10 @@ lzw_result lzw_decode_init(
ctx->input.sb_bit_count = 0;
/* Initialise the dictionary building context */
- ctx->initial_code_size = code_size + 1;
+ ctx->initial_code_size = minimum_code_size + 1;
- ctx->clear_code = (1 << code_size) + 0;
- ctx->eoi_code = (1 << code_size) + 1;
+ ctx->clear_code = (1 << minimum_code_size) + 0;
+ ctx->eoi_code = (1 << minimum_code_size) + 1;
/* Initialise the standard dictionary entries */
for (uint32_t i = 0; i < ctx->clear_code; ++i) {
diff --git a/src/lzw.h b/src/lzw.h
index 385b425..888526e 100644
--- a/src/lzw.h
+++ b/src/lzw.h
@@ -65,7 +65,7 @@ void lzw_context_destroy(
* \param[in] compressed_data_len Byte length of compressed data.
* \param[in] compressed_data_pos Start position in data. Must be position
* of a size byte at sub-block start.
- * \param[in] code_size The initial LZW code size to use.
+ * \param[in] minimum_code_size The LZW Minimum Code Size.
* \param[out] stack_base_out Returns base of decompressed data stack.
* \param[out] stack_pos_out Returns current stack position.
* There are `stack_pos_out - stack_base_out`
@@ -77,7 +77,7 @@ lzw_result lzw_decode_init(
const uint8_t *compressed_data,
uint32_t compressed_data_len,
uint32_t compressed_data_pos,
- uint8_t code_size,
+ uint8_t minimum_code_size,
const uint8_t ** const stack_base_out,
const uint8_t ** const stack_pos_out);
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=e708ae66a41c5f5eccc043bcf02bd0dccb132403
commit e708ae66a41c5f5eccc043bcf02bd0dccb132403
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
lzw: Slight simplification of clear code handling.
diff --git a/src/lzw.c b/src/lzw.c
index 55bb4f8..8b3e472 100644
--- a/src/lzw.c
+++ b/src/lzw.c
@@ -232,9 +232,9 @@ static lzw_result lzw__clear_codes(
uint8_t *stack_pos;
/* Reset dictionary building context */
- ctx->current_code_size = ctx->initial_code_size + 1;
- ctx->current_code_size_max = (1 << ctx->current_code_size) - 1;
- ctx->current_entry = (1 << ctx->initial_code_size) + 2;
+ ctx->current_code_size = ctx->initial_code_size;
+ ctx->current_code_size_max = (1 << ctx->initial_code_size) - 1;
+ ctx->current_entry = ctx->eoi_code + 1;
/* There might be a sequence of clear codes, so process them all */
do {
@@ -288,7 +288,7 @@ lzw_result lzw_decode_init(
ctx->input.sb_bit_count = 0;
/* Initialise the dictionary building context */
- ctx->initial_code_size = code_size;
+ ctx->initial_code_size = code_size + 1;
ctx->clear_code = (1 << code_size) + 0;
ctx->eoi_code = (1 << code_size) + 1;
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=e6c790fc877a231653f92b70c75a456812b5be0d
commit e6c790fc877a231653f92b70c75a456812b5be0d
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
lzw: Avoid code size increment check when dictionary is full.
diff --git a/src/lzw.c b/src/lzw.c
index 1d145b4..55bb4f8 100644
--- a/src/lzw.c
+++ b/src/lzw.c
@@ -357,11 +357,10 @@ lzw_result lzw_decode(struct lzw_ctx *ctx,
lzw__dictionary_add_entry(ctx, (code_new < current_entry) ?
table[code_new].first_value :
ctx->previous_code_first);
- }
- /* Ensure code size is increased, if needed. */
- if (current_entry == ctx->current_code_size_max) {
- if (ctx->current_code_size < LZW_CODE_MAX) {
+ /* Ensure code size is increased, if needed. */
+ if (current_entry == ctx->current_code_size_max &&
+ ctx->current_code_size < LZW_CODE_MAX) {
ctx->current_code_size++;
ctx->current_code_size_max =
(1 << ctx->current_code_size) - 1;
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=0d7049e414806b8af7f835cae9321138d4042a73
commit 0d7049e414806b8af7f835cae9321138d4042a73
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
lzw: Split out dictionary augmentation.
diff --git a/src/lzw.c b/src/lzw.c
index a5097ab..1d145b4 100644
--- a/src/lzw.c
+++ b/src/lzw.c
@@ -303,6 +303,24 @@ lzw_result lzw_decode_init(
return lzw__clear_codes(ctx, stack_pos_out);
}
+/**
+ * Create new dictionary entry.
+ *
+ * \param[in] ctx LZW reading context, updated.
+ * \param[in] code Last value code for new dictionary entry.
+ */
+static inline void lzw__dictionary_add_entry(
+ struct lzw_ctx *ctx,
+ uint32_t code)
+{
+ struct lzw_dictionary_entry *entry = &ctx->table[ctx->current_entry];
+
+ entry->last_value = code;
+ entry->first_value = ctx->previous_code_first;
+ entry->previous_entry = ctx->previous_code;
+
+ ctx->current_entry++;
+}
/* Exported function, documented in lzw.h */
lzw_result lzw_decode(struct lzw_ctx *ctx,
@@ -310,7 +328,6 @@ lzw_result lzw_decode(struct lzw_ctx *ctx,
{
lzw_result res;
uint32_t code_new;
- uint8_t last_value;
uint8_t *stack_pos = ctx->stack_base;
uint32_t clear_code = ctx->clear_code;
uint32_t current_entry = ctx->current_entry;
@@ -334,22 +351,12 @@ lzw_result lzw_decode(struct lzw_ctx *ctx,
} else if (code_new > current_entry) {
/* Code is invalid */
return LZW_BAD_CODE;
-
- } else if (code_new < current_entry) {
- /* Code is in table */
- last_value = table[code_new].first_value;
- } else {
- /* Code not in table */
- last_value = ctx->previous_code_first;
}
- /* Add to the dictionary, only if there's space */
if (current_entry < LZW_DICTIONARY_ENTRY_MAX) {
- struct lzw_dictionary_entry *entry = table + current_entry;
- entry->last_value = last_value;
- entry->first_value = ctx->previous_code_first;
- entry->previous_entry = ctx->previous_code;
- ctx->current_entry++;
+ lzw__dictionary_add_entry(ctx, (code_new < current_entry) ?
+ table[code_new].first_value :
+ ctx->previous_code_first);
}
/* Ensure code size is increased, if needed. */
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=970cc6c57b6d245ef20988b777edda51b3325184
commit 970cc6c57b6d245ef20988b777edda51b3325184
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
lzw: Create #define for number of dictionary entry slots.
diff --git a/src/lzw.c b/src/lzw.c
index 16e1a72..a5097ab 100644
--- a/src/lzw.c
+++ b/src/lzw.c
@@ -21,6 +21,8 @@
* Decoder for GIF LZW data.
*/
+/** Maximum number of dictionary entries. */
+#define LZW_DICTIONARY_ENTRY_MAX (1u << LZW_CODE_MAX)
/**
* Context for reading LZW data.
@@ -79,10 +81,10 @@ struct lzw_ctx {
uint32_t current_entry; /**< Next position in table to fill. */
/** Output value stack. */
- uint8_t stack_base[1 << LZW_CODE_MAX];
+ uint8_t stack_base[LZW_DICTIONARY_ENTRY_MAX];
/** LZW decode dictionary. Generated during decode. */
- struct lzw_dictionary_entry table[1 << LZW_CODE_MAX];
+ struct lzw_dictionary_entry table[LZW_DICTIONARY_ENTRY_MAX];
};
@@ -342,7 +344,7 @@ lzw_result lzw_decode(struct lzw_ctx *ctx,
}
/* Add to the dictionary, only if there's space */
- if (current_entry < (1 << LZW_CODE_MAX)) {
+ if (current_entry < LZW_DICTIONARY_ENTRY_MAX) {
struct lzw_dictionary_entry *entry = table + current_entry;
entry->last_value = last_value;
entry->first_value = ctx->previous_code_first;
commitdiff
http://git.netsurf-browser.org/libnsgif.git/commit/?id=aa6d16b88dc74f66e7a4f2041886f57ce750237e
commit aa6d16b88dc74f66e7a4f2041886f57ce750237e
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>
lzw: Simplify new code handling.
The tiny overhead of an extra time through the output loop
is worth the simpler code.
diff --git a/src/lzw.c b/src/lzw.c
index 1f85496..16e1a72 100644
--- a/src/lzw.c
+++ b/src/lzw.c
@@ -4,6 +4,7 @@
* http://www.opensource.org/licenses/mit-license.php
*
* Copyright 2017 Michael Drake <[email protected]>
+ * Copyright 2021 Michael Drake <[email protected]>
*/
#include <assert.h>
@@ -307,7 +308,6 @@ lzw_result lzw_decode(struct lzw_ctx *ctx,
{
lzw_result res;
uint32_t code_new;
- uint32_t code_out;
uint8_t last_value;
uint8_t *stack_pos = ctx->stack_base;
uint32_t clear_code = ctx->clear_code;
@@ -335,12 +335,9 @@ lzw_result lzw_decode(struct lzw_ctx *ctx,
} else if (code_new < current_entry) {
/* Code is in table */
- code_out = code_new;
last_value = table[code_new].first_value;
} else {
/* Code not in table */
- *stack_pos++ = ctx->previous_code_first;
- code_out = ctx->previous_code;
last_value = ctx->previous_code_first;
}
@@ -366,15 +363,13 @@ lzw_result lzw_decode(struct lzw_ctx *ctx,
ctx->previous_code_first = table[code_new].first_value;
ctx->previous_code = code_new;
- /* Put rest of data for this code on output stack.
- * Note, in the case of "code not in table", the last entry of the
- * current code has already been placed on the stack above. */
- while (code_out > clear_code) {
- struct lzw_dictionary_entry *entry = table + code_out;
+ /* Put data for this code on output stack. */
+ while (code_new > clear_code) {
+ struct lzw_dictionary_entry *entry = table + code_new;
*stack_pos++ = entry->last_value;
- code_out = entry->previous_entry;
+ code_new = entry->previous_entry;
}
- *stack_pos++ = table[code_out].last_value;
+ *stack_pos++ = table[code_new].last_value;
*stack_pos_out = stack_pos;
return LZW_OK;
-----------------------------------------------------------------------
--
NetSurf GIF Decoder
_______________________________________________
netsurf-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]