update libnsgif
pick up a couple of patches
This commit is contained in:
parent
9f15567f2c
commit
e4453f8b18
@ -418,7 +418,7 @@ static gif_result gif_initialise_frame(gif_animation *gif)
|
||||
if (gif_bytes < 1) {
|
||||
return GIF_INSUFFICIENT_FRAME_DATA;
|
||||
}
|
||||
if (gif_data[0] > LZW_CODE_MAX) {
|
||||
if (gif_data[0] >= LZW_CODE_MAX) {
|
||||
return GIF_DATA_ERROR;
|
||||
}
|
||||
|
||||
@ -864,10 +864,10 @@ gif_internal_decode_frame(gif_animation *gif,
|
||||
}
|
||||
}
|
||||
|
||||
if (gif->frames[frame].disposal_method == GIF_FRAME_RESTORE) {
|
||||
/* Store the previous frame for later restoration */
|
||||
gif__record_previous_frame(gif);
|
||||
}
|
||||
if (gif->frames[frame].disposal_method == GIF_FRAME_RESTORE) {
|
||||
/* Store the previous frame for later restoration */
|
||||
gif__record_previous_frame(gif);
|
||||
}
|
||||
|
||||
gif->decoded_frame = frame;
|
||||
gif->buffer_position = (gif_data - gif->gif_data) + 1;
|
||||
|
@ -160,7 +160,6 @@ static inline lzw_result lzw__next_code(
|
||||
uint32_t code = 0;
|
||||
uint8_t current_bit = ctx->sb_bit & 0x7;
|
||||
uint8_t byte_advance = (current_bit + code_size) >> 3;
|
||||
uint32_t new_code;
|
||||
|
||||
assert(byte_advance <= 2);
|
||||
|
||||
@ -210,11 +209,7 @@ static inline lzw_result lzw__next_code(
|
||||
}
|
||||
}
|
||||
|
||||
new_code = (code >> current_bit) & ((1 << code_size) - 1);
|
||||
if (new_code > ((1 << LZW_CODE_MAX) - 1))
|
||||
return LZW_BAD_CODE;
|
||||
*code_out = new_code;
|
||||
|
||||
*code_out = (code >> current_bit) & ((1 << code_size) - 1);
|
||||
return LZW_OK;
|
||||
}
|
||||
|
||||
@ -235,7 +230,7 @@ static lzw_result lzw__clear_codes(
|
||||
|
||||
/* 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_code_size_max = (1 << ctx->current_code_size) - 1;
|
||||
ctx->current_entry = (1 << ctx->initial_code_size) + 2;
|
||||
|
||||
/* There might be a sequence of clear codes, so process them all */
|
||||
@ -277,6 +272,10 @@ lzw_result lzw_decode_init(
|
||||
{
|
||||
struct lzw_dictionary_entry *table = ctx->table;
|
||||
|
||||
if (code_size >= LZW_CODE_MAX) {
|
||||
return LZW_BAD_ICODE;
|
||||
}
|
||||
|
||||
/* Initialise the input reading context */
|
||||
ctx->input.data = compressed_data;
|
||||
ctx->input.data_len = compressed_data_len;
|
||||
|
@ -1,23 +0,0 @@
|
||||
--- lzw-orig.c 2021-03-29 09:16:40.730562757 +0100
|
||||
+++ lzw.c 2021-03-29 09:16:30.390679354 +0100
|
||||
@@ -160,6 +160,7 @@
|
||||
uint32_t code = 0;
|
||||
uint8_t current_bit = ctx->sb_bit & 0x7;
|
||||
uint8_t byte_advance = (current_bit + code_size) >> 3;
|
||||
+ uint32_t new_code;
|
||||
|
||||
assert(byte_advance <= 2);
|
||||
|
||||
@@ -209,7 +210,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
- *code_out = (code >> current_bit) & ((1 << code_size) - 1);
|
||||
+ new_code = (code >> current_bit) & ((1 << code_size) - 1);
|
||||
+ if (new_code > ((1 << LZW_CODE_MAX) - 1))
|
||||
+ return LZW_BAD_CODE;
|
||||
+ *code_out = new_code;
|
||||
+
|
||||
return LZW_OK;
|
||||
}
|
||||
|
258
libvips/foreign/libnsgif/test/decode_gif.c
Normal file
258
libvips/foreign/libnsgif/test/decode_gif.c
Normal file
@ -0,0 +1,258 @@
|
||||
/* under libvips, compile with:
|
||||
*
|
||||
* gcc -g -Wall decode_gif.c `pkg-config vips --cflags --libs`
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2008 Sean Fox <dyntryx@gmail.com>
|
||||
* Copyright 2008 James Bursa <james@netsurf-browser.org>
|
||||
*
|
||||
* This file is part of NetSurf's libnsgif, http://www.netsurf-browser.org/
|
||||
* Licenced under the MIT License,
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include "../libnsgif.h"
|
||||
|
||||
#define BYTES_PER_PIXEL 4
|
||||
#define MAX_IMAGE_BYTES (48 * 1024 * 1024)
|
||||
|
||||
|
||||
static void *bitmap_create(int width, int height)
|
||||
{
|
||||
/* ensure a stupidly large bitmap is not created */
|
||||
if (((long long)width * (long long)height) > (MAX_IMAGE_BYTES/BYTES_PER_PIXEL)) {
|
||||
return NULL;
|
||||
}
|
||||
return calloc(width * height, BYTES_PER_PIXEL);
|
||||
}
|
||||
|
||||
|
||||
static void bitmap_set_opaque(void *bitmap, bool opaque)
|
||||
{
|
||||
(void) opaque; /* unused */
|
||||
(void) bitmap; /* unused */
|
||||
assert(bitmap);
|
||||
}
|
||||
|
||||
|
||||
static bool bitmap_test_opaque(void *bitmap)
|
||||
{
|
||||
(void) bitmap; /* unused */
|
||||
assert(bitmap);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static unsigned char *bitmap_get_buffer(void *bitmap)
|
||||
{
|
||||
assert(bitmap);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
static void bitmap_destroy(void *bitmap)
|
||||
{
|
||||
assert(bitmap);
|
||||
free(bitmap);
|
||||
}
|
||||
|
||||
|
||||
static void bitmap_modified(void *bitmap)
|
||||
{
|
||||
(void) bitmap; /* unused */
|
||||
assert(bitmap);
|
||||
return;
|
||||
}
|
||||
|
||||
static unsigned char *load_file(const char *path, size_t *data_size)
|
||||
{
|
||||
FILE *fd;
|
||||
struct stat sb;
|
||||
unsigned char *buffer;
|
||||
size_t size;
|
||||
size_t n;
|
||||
|
||||
fd = fopen(path, "rb");
|
||||
if (!fd) {
|
||||
perror(path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (stat(path, &sb)) {
|
||||
perror(path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
size = sb.st_size;
|
||||
|
||||
buffer = malloc(size);
|
||||
if (!buffer) {
|
||||
fprintf(stderr, "Unable to allocate %lld bytes\n",
|
||||
(long long) size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
n = fread(buffer, 1, size, fd);
|
||||
if (n != size) {
|
||||
perror(path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
|
||||
*data_size = size;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
static void warning(const char *context, gif_result code)
|
||||
{
|
||||
fprintf(stderr, "%s failed: ", context);
|
||||
switch (code)
|
||||
{
|
||||
case GIF_INSUFFICIENT_FRAME_DATA:
|
||||
fprintf(stderr, "GIF_INSUFFICIENT_FRAME_DATA");
|
||||
break;
|
||||
case GIF_FRAME_DATA_ERROR:
|
||||
fprintf(stderr, "GIF_FRAME_DATA_ERROR");
|
||||
break;
|
||||
case GIF_INSUFFICIENT_DATA:
|
||||
fprintf(stderr, "GIF_INSUFFICIENT_DATA");
|
||||
break;
|
||||
case GIF_DATA_ERROR:
|
||||
fprintf(stderr, "GIF_DATA_ERROR");
|
||||
break;
|
||||
case GIF_INSUFFICIENT_MEMORY:
|
||||
fprintf(stderr, "GIF_INSUFFICIENT_MEMORY");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown code %i", code);
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
static void write_ppm(FILE* fh, const char *name, gif_animation *gif,
|
||||
bool no_write)
|
||||
{
|
||||
unsigned int i;
|
||||
gif_result code;
|
||||
|
||||
if (!no_write) {
|
||||
fprintf(fh, "P3\n");
|
||||
fprintf(fh, "# %s\n", name);
|
||||
fprintf(fh, "# width %u \n", gif->width);
|
||||
fprintf(fh, "# height %u \n", gif->height);
|
||||
fprintf(fh, "# frame_count %u \n", gif->frame_count);
|
||||
fprintf(fh, "# frame_count_partial %u \n", gif->frame_count_partial);
|
||||
fprintf(fh, "# loop_count %u \n", gif->loop_count);
|
||||
fprintf(fh, "%u %u 256\n", gif->width, gif->height * gif->frame_count);
|
||||
}
|
||||
|
||||
/* decode the frames */
|
||||
for (i = 0; i != gif->frame_count; i++) {
|
||||
unsigned int row, col;
|
||||
unsigned char *image;
|
||||
|
||||
code = gif_decode_frame(gif, i);
|
||||
if (code != GIF_OK)
|
||||
warning("gif_decode_frame", code);
|
||||
|
||||
if (!no_write) {
|
||||
fprintf(fh, "# frame %u:\n", i);
|
||||
image = (unsigned char *) gif->frame_image;
|
||||
for (row = 0; row != gif->height; row++) {
|
||||
for (col = 0; col != gif->width; col++) {
|
||||
size_t z = (row * gif->width + col) * 4;
|
||||
fprintf(fh, "%u %u %u ",
|
||||
(unsigned char) image[z],
|
||||
(unsigned char) image[z + 1],
|
||||
(unsigned char) image[z + 2]);
|
||||
}
|
||||
fprintf(fh, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
gif_bitmap_callback_vt bitmap_callbacks = {
|
||||
bitmap_create,
|
||||
bitmap_destroy,
|
||||
bitmap_get_buffer,
|
||||
bitmap_set_opaque,
|
||||
bitmap_test_opaque,
|
||||
bitmap_modified
|
||||
};
|
||||
gif_animation gif;
|
||||
size_t size;
|
||||
gif_result code;
|
||||
unsigned char *data;
|
||||
FILE *outf = stdout;
|
||||
bool no_write = false;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: %s image.gif [out]\n", argv[0]);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "If [out] is NOWRITE, the gif will be docoded "
|
||||
"but not output.\n");
|
||||
fprintf(stderr, "Otherwise [out] is an output filename.\n");
|
||||
fprintf(stderr, "When [out] is unset, output is to stdout.\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc > 2) {
|
||||
if (strcmp(argv[2], "NOWRITE") == 0) {
|
||||
no_write = true;
|
||||
} else {
|
||||
outf = fopen(argv[2], "w+");
|
||||
if (outf == NULL) {
|
||||
fprintf(stderr, "Unable to open %s for writing\n", argv[2]);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* create our gif animation */
|
||||
gif_create(&gif, &bitmap_callbacks);
|
||||
|
||||
/* load file into memory */
|
||||
data = load_file(argv[1], &size);
|
||||
|
||||
/* begin decoding */
|
||||
do {
|
||||
code = gif_initialise(&gif, size, data);
|
||||
if (code != GIF_OK && code != GIF_WORKING) {
|
||||
warning("gif_initialise", code);
|
||||
gif_finalise(&gif);
|
||||
free(data);
|
||||
return 1;
|
||||
}
|
||||
} while (code != GIF_OK);
|
||||
|
||||
write_ppm(outf, argv[1], &gif, no_write);
|
||||
|
||||
if (argc > 2 && !no_write) {
|
||||
fclose(outf);
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
gif_finalise(&gif);
|
||||
free(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user