Update LibNSGIF to latest upstream (#2791)
* libnsgif: Update to latest upstream * nsgifload: Add palette info to debug output.
This commit is contained in:
parent
460a19b78e
commit
ceaa2d2096
@ -8,7 +8,7 @@ but within the libvips build system.
|
||||
Run `./update.sh` to update this copy of libnsgif from the upstream repo. It
|
||||
will also patch libnsgif.c to prevent it modifying the input.
|
||||
|
||||
Last updated 15 Apr 2022.
|
||||
Last updated 8 May 2022.
|
||||
|
||||
# To do
|
||||
|
||||
|
@ -17,9 +17,6 @@
|
||||
#include "lzw.h"
|
||||
#include "nsgif.h"
|
||||
|
||||
/** Maximum colour table size */
|
||||
#define NSGIF_MAX_COLOURS 256
|
||||
|
||||
/** Default minimum allowable frame delay in cs. */
|
||||
#define NSGIF_FRAME_DELAY_MIN 2
|
||||
|
||||
@ -35,7 +32,7 @@ typedef struct nsgif_frame {
|
||||
struct nsgif_frame_info info;
|
||||
|
||||
/** offset (in bytes) to the GIF frame data */
|
||||
uint32_t frame_pointer;
|
||||
uint32_t frame_offset;
|
||||
/** whether the frame has previously been decoded. */
|
||||
bool decoded;
|
||||
/** whether the frame is totally opaque */
|
||||
@ -46,6 +43,9 @@ typedef struct nsgif_frame {
|
||||
/** the index designating a transparent pixel */
|
||||
uint32_t transparency_index;
|
||||
|
||||
/** offset to frame colour table */
|
||||
uint32_t colour_table_offset;
|
||||
|
||||
/* Frame flags */
|
||||
uint32_t flags;
|
||||
} nsgif_frame;
|
||||
@ -72,8 +72,11 @@ struct nsgif {
|
||||
uint32_t frame;
|
||||
/** current frame decoded to bitmap */
|
||||
uint32_t decoded_frame;
|
||||
|
||||
/** currently decoded image; stored as bitmap from bitmap_create callback */
|
||||
nsgif_bitmap_t *frame_image;
|
||||
/** Row span of frame_image in pixels. */
|
||||
uint32_t rowspan;
|
||||
|
||||
/** Minimum allowable frame delay. */
|
||||
uint16_t delay_min;
|
||||
@ -100,11 +103,9 @@ struct nsgif {
|
||||
uint32_t bg_index;
|
||||
/** image aspect ratio (ignored) */
|
||||
uint32_t aspect_ratio;
|
||||
/** size of colour table (in entries) */
|
||||
/** size of global colour table (in entries) */
|
||||
uint32_t colour_table_size;
|
||||
|
||||
/** whether the GIF has a global colour table */
|
||||
bool global_colours;
|
||||
/** current colour table */
|
||||
uint32_t *colour_table;
|
||||
/** Client's colour component order. */
|
||||
@ -223,6 +224,11 @@ static inline uint32_t* nsgif__bitmap_get(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gif->rowspan = gif->info.width;
|
||||
if (gif->bitmap.get_rowspan) {
|
||||
gif->rowspan = gif->bitmap.get_rowspan(gif->frame_image);
|
||||
}
|
||||
|
||||
/* Get the frame data */
|
||||
assert(gif->bitmap.get_buffer);
|
||||
return (void *)gif->bitmap.get_buffer(gif->frame_image);
|
||||
@ -463,7 +469,7 @@ static nsgif_error nsgif__decode_complex(
|
||||
uint32_t *frame_scanline;
|
||||
|
||||
frame_scanline = frame_data + offset_x +
|
||||
(y + offset_y) * gif->info.width;
|
||||
(y + offset_y) * gif->rowspan;
|
||||
|
||||
x = width;
|
||||
while (x > 0) {
|
||||
@ -594,7 +600,9 @@ static inline nsgif_error nsgif__decode(
|
||||
uint32_t transparency_index = frame->transparency_index;
|
||||
uint32_t *restrict colour_table = gif->colour_table;
|
||||
|
||||
if (interlace == false && width == gif->info.width && offset_x == 0) {
|
||||
if (interlace == false && offset_x == 0 &&
|
||||
width == gif->info.width &&
|
||||
width == gif->rowspan) {
|
||||
ret = nsgif__decode_simple(gif, height, offset_y,
|
||||
data, transparency_index,
|
||||
frame_data, colour_table);
|
||||
@ -1031,6 +1039,38 @@ static nsgif_error nsgif__parse_image_descriptor(
|
||||
return NSGIF_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a GIF colour table into a LibNSGIF colour table buffer.
|
||||
*
|
||||
* \param[in] colour_table The colour table to populate.
|
||||
* \param[in] layout la.
|
||||
* \param[in] colour_table_entries The number of colour table entries.
|
||||
* \param[in] Data Raw colour table data.
|
||||
*/
|
||||
static void nsgif__colour_table_decode(
|
||||
uint32_t colour_table[NSGIF_MAX_COLOURS],
|
||||
const struct nsgif_colour_layout *layout,
|
||||
size_t colour_table_entries,
|
||||
const uint8_t *data)
|
||||
{
|
||||
uint8_t *entry = (uint8_t *)colour_table;
|
||||
|
||||
while (colour_table_entries--) {
|
||||
/* Gif colour map contents are r,g,b.
|
||||
*
|
||||
* We want to pack them bytewise into the colour table,
|
||||
* according to the client colour layout.
|
||||
*/
|
||||
|
||||
entry[layout->r] = *data++;
|
||||
entry[layout->g] = *data++;
|
||||
entry[layout->b] = *data++;
|
||||
entry[layout->a] = 0xff;
|
||||
|
||||
entry += sizeof(uint32_t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a GIF colour table into a LibNSGIF colour table buffer.
|
||||
*
|
||||
@ -1041,42 +1081,25 @@ static nsgif_error nsgif__parse_image_descriptor(
|
||||
* \param[in] decode Whether to decode the colour table.
|
||||
* \return NSGIF_OK on success, appropriate error otherwise.
|
||||
*/
|
||||
static nsgif_error nsgif__colour_table_extract(
|
||||
struct nsgif *gif,
|
||||
static inline nsgif_error nsgif__colour_table_extract(
|
||||
uint32_t colour_table[NSGIF_MAX_COLOURS],
|
||||
const struct nsgif_colour_layout *layout,
|
||||
size_t colour_table_entries,
|
||||
const uint8_t **pos,
|
||||
const uint8_t *data,
|
||||
size_t data_len,
|
||||
size_t *used,
|
||||
bool decode)
|
||||
{
|
||||
const uint8_t *data = *pos;
|
||||
size_t len = gif->buf + gif->buf_len - data;
|
||||
|
||||
if (len < colour_table_entries * 3) {
|
||||
if (data_len < colour_table_entries * 3) {
|
||||
return NSGIF_ERR_END_OF_DATA;
|
||||
}
|
||||
|
||||
if (decode) {
|
||||
int count = colour_table_entries;
|
||||
uint8_t *entry = (uint8_t *)colour_table;
|
||||
|
||||
while (count--) {
|
||||
/* Gif colour map contents are r,g,b.
|
||||
*
|
||||
* We want to pack them bytewise into the colour table,
|
||||
* according to the client colour layout.
|
||||
*/
|
||||
|
||||
entry[layout->r] = *data++;
|
||||
entry[layout->g] = *data++;
|
||||
entry[layout->b] = *data++;
|
||||
entry[layout->a] = 0xff;
|
||||
|
||||
entry += sizeof(uint32_t);
|
||||
}
|
||||
nsgif__colour_table_decode(colour_table, layout,
|
||||
colour_table_entries, data);
|
||||
}
|
||||
|
||||
*pos += colour_table_entries * 3;
|
||||
*used = colour_table_entries * 3;
|
||||
return NSGIF_OK;
|
||||
}
|
||||
|
||||
@ -1098,6 +1121,9 @@ static nsgif_error nsgif__parse_colour_table(
|
||||
bool decode)
|
||||
{
|
||||
nsgif_error ret;
|
||||
const uint8_t *data = *pos;
|
||||
size_t len = gif->buf + gif->buf_len - data;
|
||||
size_t used_bytes;
|
||||
|
||||
assert(gif != NULL);
|
||||
assert(frame != NULL);
|
||||
@ -1107,15 +1133,25 @@ static nsgif_error nsgif__parse_colour_table(
|
||||
return NSGIF_OK;
|
||||
}
|
||||
|
||||
ret = nsgif__colour_table_extract(gif,
|
||||
if (decode == false) {
|
||||
frame->colour_table_offset = *pos - gif->buf;
|
||||
}
|
||||
|
||||
ret = nsgif__colour_table_extract(
|
||||
gif->local_colour_table, &gif->colour_layout,
|
||||
2 << (frame->flags & NSGIF_COLOUR_TABLE_SIZE_MASK),
|
||||
pos, decode);
|
||||
data, len, &used_bytes, decode);
|
||||
if (ret != NSGIF_OK) {
|
||||
return ret;
|
||||
}
|
||||
*pos += used_bytes;
|
||||
|
||||
if (decode) {
|
||||
gif->colour_table = gif->local_colour_table;
|
||||
} else {
|
||||
frame->info.local_palette = true;
|
||||
}
|
||||
|
||||
gif->colour_table = gif->local_colour_table;
|
||||
return NSGIF_OK;
|
||||
}
|
||||
|
||||
@ -1223,7 +1259,8 @@ static struct nsgif_frame *nsgif__get_frame(
|
||||
frame = &gif->frames[frame_idx];
|
||||
|
||||
frame->transparency_index = NSGIF_NO_TRANSPARENCY;
|
||||
frame->frame_pointer = gif->buf_pos;
|
||||
frame->frame_offset = gif->buf_pos;
|
||||
frame->info.local_palette = false;
|
||||
frame->info.transparency = false;
|
||||
frame->redraw_required = false;
|
||||
frame->info.display = false;
|
||||
@ -1261,7 +1298,7 @@ static nsgif_error nsgif__process_frame(
|
||||
end = gif->buf + gif->buf_len;
|
||||
|
||||
if (decode) {
|
||||
pos = gif->buf + frame->frame_pointer;
|
||||
pos = gif->buf + frame->frame_offset;
|
||||
|
||||
/* Ensure this frame is supposed to be decoded */
|
||||
if (frame->info.display == false) {
|
||||
@ -1536,7 +1573,7 @@ static nsgif_error nsgif__parse_logical_screen_descriptor(
|
||||
|
||||
gif->info.width = data[0] | (data[1] << 8);
|
||||
gif->info.height = data[2] | (data[3] << 8);
|
||||
gif->global_colours = data[4] & NSGIF_COLOUR_TABLE_MASK;
|
||||
gif->info.global_palette = data[4] & NSGIF_COLOUR_TABLE_MASK;
|
||||
gif->colour_table_size = 2 << (data[4] & NSGIF_COLOUR_TABLE_SIZE_MASK);
|
||||
gif->bg_index = data[5];
|
||||
gif->aspect_ratio = data[6];
|
||||
@ -1630,16 +1667,20 @@ nsgif_error nsgif_data_scan(
|
||||
*/
|
||||
if (gif->global_colour_table[0] == NSGIF_PROCESS_COLOURS) {
|
||||
/* Check for a global colour map signified by bit 7 */
|
||||
if (gif->global_colours) {
|
||||
ret = nsgif__colour_table_extract(gif,
|
||||
if (gif->info.global_palette) {
|
||||
size_t remaining = gif->buf + gif->buf_len - nsgif_data;
|
||||
size_t used;
|
||||
|
||||
ret = nsgif__colour_table_extract(
|
||||
gif->global_colour_table,
|
||||
&gif->colour_layout,
|
||||
gif->colour_table_size,
|
||||
&nsgif_data, true);
|
||||
nsgif_data, remaining, &used, true);
|
||||
if (ret != NSGIF_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
nsgif_data += used;
|
||||
gif->buf_pos = (nsgif_data - gif->buf);
|
||||
} else {
|
||||
/* Create a default colour table with the first two
|
||||
@ -1659,9 +1700,11 @@ nsgif_error nsgif_data_scan(
|
||||
entry[gif->colour_layout.g] = 0xFF;
|
||||
entry[gif->colour_layout.b] = 0xFF;
|
||||
entry[gif->colour_layout.a] = 0xFF;
|
||||
|
||||
gif->colour_table_size = 2;
|
||||
}
|
||||
|
||||
if (gif->global_colours &&
|
||||
if (gif->info.global_palette &&
|
||||
gif->bg_index < gif->colour_table_size) {
|
||||
size_t bg_idx = gif->bg_index;
|
||||
gif->info.background = gif->global_colour_table[bg_idx];
|
||||
@ -1895,6 +1938,43 @@ const nsgif_frame_info_t *nsgif_get_frame_info(
|
||||
return &gif->frames[frame].info;
|
||||
}
|
||||
|
||||
/* exported function documented in nsgif.h */
|
||||
void nsgif_global_palette(
|
||||
const nsgif_t *gif,
|
||||
uint32_t table[NSGIF_MAX_COLOURS],
|
||||
size_t *entries)
|
||||
{
|
||||
size_t len = sizeof(*table) * NSGIF_MAX_COLOURS;
|
||||
|
||||
memcpy(table, gif->global_colour_table, len);
|
||||
*entries = gif->colour_table_size;
|
||||
}
|
||||
|
||||
/* exported function documented in nsgif.h */
|
||||
bool nsgif_local_palette(
|
||||
const nsgif_t *gif,
|
||||
uint32_t frame,
|
||||
uint32_t table[NSGIF_MAX_COLOURS],
|
||||
size_t *entries)
|
||||
{
|
||||
const nsgif_frame *f;
|
||||
|
||||
if (frame >= gif->frame_count_partial) {
|
||||
return false;
|
||||
}
|
||||
|
||||
f = &gif->frames[frame];
|
||||
if (f->info.local_palette == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*entries = 2 << (f->flags & NSGIF_COLOUR_TABLE_SIZE_MASK);
|
||||
nsgif__colour_table_decode(table, &gif->colour_layout,
|
||||
*entries, gif->buf + f->colour_table_offset);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* exported function documented in nsgif.h */
|
||||
const char *nsgif_strerror(nsgif_error err)
|
||||
{
|
||||
|
@ -23,6 +23,9 @@
|
||||
/** Representation of infinity. */
|
||||
#define NSGIF_INFINITE (UINT32_MAX)
|
||||
|
||||
/** Maximum colour table size */
|
||||
#define NSGIF_MAX_COLOURS 256
|
||||
|
||||
/**
|
||||
* Opaque type used by LibNSGIF to represent a GIF object in memory.
|
||||
*/
|
||||
@ -162,6 +165,11 @@ typedef enum nsgif_bitmap_fmt {
|
||||
* but they are owned by a \ref nsgif_t.
|
||||
*
|
||||
* See \ref nsgif_bitmap_fmt for pixel format information.
|
||||
*
|
||||
* The bitmap may have a row_span greater than the bitmap width, but the
|
||||
* difference between row span and width must be a whole number of pixels
|
||||
* (a multiple of four bytes). If row span is greater than width, the
|
||||
* \ref get_rowspan callback must be provided.
|
||||
*/
|
||||
typedef void nsgif_bitmap_t;
|
||||
|
||||
@ -186,7 +194,8 @@ typedef struct nsgif_bitmap_cb_vt {
|
||||
/**
|
||||
* Get pointer to pixel buffer in a bitmap.
|
||||
*
|
||||
* The pixel buffer must be `width * height * sizeof(uint32_t)`.
|
||||
* The pixel buffer must be `(width + N) * height * sizeof(uint32_t)`.
|
||||
* Where `N` is any number greater than or equal to 0.
|
||||
* Note that the returned pointer to uint8_t must be 4-byte aligned.
|
||||
*
|
||||
* \param[in] bitmap The bitmap.
|
||||
@ -218,6 +227,15 @@ typedef struct nsgif_bitmap_cb_vt {
|
||||
* \param[in] bitmap The bitmap.
|
||||
*/
|
||||
void (*modified)(nsgif_bitmap_t *bitmap);
|
||||
|
||||
/**
|
||||
* Get row span in pixels.
|
||||
*
|
||||
* If this callback is not provided, LibNSGIF will use the width.
|
||||
*
|
||||
* \param[in] bitmap The bitmap.
|
||||
*/
|
||||
uint32_t (*get_rowspan)(nsgif_bitmap_t *bitmap);
|
||||
} nsgif_bitmap_cb_vt;
|
||||
|
||||
/**
|
||||
@ -345,6 +363,8 @@ typedef struct nsgif_info {
|
||||
int loop_max;
|
||||
/** background colour in same pixel format as \ref nsgif_bitmap_t. */
|
||||
uint32_t background;
|
||||
/** whether the GIF has a global colour table */
|
||||
bool global_palette;
|
||||
} nsgif_info_t;
|
||||
|
||||
/**
|
||||
@ -377,6 +397,8 @@ typedef struct nsgif_frame_info {
|
||||
bool display;
|
||||
/** whether the frame may have transparency */
|
||||
bool transparency;
|
||||
/** whether the frame has a local colour table */
|
||||
bool local_palette;
|
||||
|
||||
/** Disposal method for previous frame; affects plotting */
|
||||
uint8_t disposal;
|
||||
@ -408,6 +430,43 @@ const nsgif_frame_info_t *nsgif_get_frame_info(
|
||||
const nsgif_t *gif,
|
||||
uint32_t frame);
|
||||
|
||||
/**
|
||||
* Get the global colour palette.
|
||||
*
|
||||
* If the GIF has no global colour table, this will return the default
|
||||
* colour palette.
|
||||
*
|
||||
* Colours in same pixel format as \ref nsgif_bitmap_t.
|
||||
*
|
||||
* \param[in] gif The \ref nsgif_t object.
|
||||
* \param[out] table Client buffer to hold the colour table.
|
||||
* \param[out] entries The number of used entries in the colour table.
|
||||
*/
|
||||
void nsgif_global_palette(
|
||||
const nsgif_t *gif,
|
||||
uint32_t table[NSGIF_MAX_COLOURS],
|
||||
size_t *entries);
|
||||
|
||||
/**
|
||||
* Get the local colour palette for a frame.
|
||||
*
|
||||
* Frames may have no local palette. In this case they use the global palette.
|
||||
* This function returns false if the frame has no local palette.
|
||||
*
|
||||
* Colours in same pixel format as \ref nsgif_bitmap_t.
|
||||
*
|
||||
* \param[in] gif The \ref nsgif_t object.
|
||||
* \param[in] frame The \ref frame to get the palette for.
|
||||
* \param[out] table Client buffer to hold the colour table.
|
||||
* \param[out] entries The number of used entries in the colour table.
|
||||
* \return true if a palette is returned, false otherwise.
|
||||
*/
|
||||
bool nsgif_local_palette(
|
||||
const nsgif_t *gif,
|
||||
uint32_t frame,
|
||||
uint32_t table[NSGIF_MAX_COLOURS],
|
||||
size_t *entries);
|
||||
|
||||
/**
|
||||
* Configure handling of small frame delays.
|
||||
*
|
||||
|
@ -27,6 +27,7 @@ static struct nsgif_options {
|
||||
const char *file;
|
||||
const char *ppm;
|
||||
uint64_t loops;
|
||||
bool palette;
|
||||
bool info;
|
||||
} nsgif_options;
|
||||
|
||||
@ -53,6 +54,13 @@ static const struct cli_table_entry cli_entries[] = {
|
||||
.d = "Loop through decoding all frames N times. "
|
||||
"The default is 1."
|
||||
},
|
||||
{
|
||||
.s = 'p',
|
||||
.l = "palette",
|
||||
.t = CLI_BOOL,
|
||||
.v.b = &nsgif_options.palette,
|
||||
.d = "Save palette images."
|
||||
},
|
||||
{
|
||||
.p = true,
|
||||
.l = "FILE",
|
||||
@ -142,6 +150,7 @@ static void print_gif_info(const nsgif_info_t *info)
|
||||
fprintf(stdout, " height: %"PRIu32"\n", info->height);
|
||||
fprintf(stdout, " max-loops: %"PRIu32"\n", info->loop_max);
|
||||
fprintf(stdout, " frame-count: %"PRIu32"\n", info->frame_count);
|
||||
fprintf(stdout, " global palette: %s\n", info->global_palette ? "yes" : "no");
|
||||
fprintf(stdout, " background:\n");
|
||||
fprintf(stdout, " red: 0x%"PRIx8"\n", bg[0]);
|
||||
fprintf(stdout, " green: 0x%"PRIx8"\n", bg[1]);
|
||||
@ -154,6 +163,7 @@ static void print_gif_frame_info(const nsgif_frame_info_t *info, uint32_t i)
|
||||
const char *disposal = nsgif_str_disposal(info->disposal);
|
||||
|
||||
fprintf(stdout, " - frame: %"PRIu32"\n", i);
|
||||
fprintf(stdout, " local palette: %s\n", info->local_palette ? "yes" : "no");
|
||||
fprintf(stdout, " disposal-method: %s\n", disposal);
|
||||
fprintf(stdout, " transparency: %s\n", info->transparency ? "yes" : "no");
|
||||
fprintf(stdout, " display: %s\n", info->display ? "yes" : "no");
|
||||
@ -165,7 +175,82 @@ static void print_gif_frame_info(const nsgif_frame_info_t *info, uint32_t i)
|
||||
fprintf(stdout, " h: %"PRIu32"\n", info->rect.y1 - info->rect.y0);
|
||||
}
|
||||
|
||||
static void decode(FILE* ppm, const char *name, nsgif_t *gif)
|
||||
static bool save_palette(
|
||||
const char *img_filename,
|
||||
const char *palette_filename,
|
||||
const uint32_t palette[NSGIF_MAX_COLOURS],
|
||||
size_t used_entries)
|
||||
{
|
||||
enum {
|
||||
SIZE = 32,
|
||||
COUNT = 16,
|
||||
};
|
||||
FILE *f;
|
||||
int size = COUNT * SIZE + 1;
|
||||
|
||||
f = fopen(palette_filename, "w+");
|
||||
if (f == NULL) {
|
||||
fprintf(stderr, "Unable to open %s for writing\n",
|
||||
palette_filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
fprintf(f, "P3\n");
|
||||
fprintf(f, "# %s: %s\n", img_filename, palette_filename);
|
||||
fprintf(f, "# Colour count: %zu\n", used_entries);
|
||||
fprintf(f, "%u %u 256\n", size, size);
|
||||
|
||||
for (int y = 0; y < size; y++) {
|
||||
for (int x = 0; x < size; x++) {
|
||||
if (x % SIZE == 0 || y % SIZE == 0) {
|
||||
fprintf(f, "0 0 0 ");
|
||||
} else {
|
||||
size_t offset = y / SIZE * COUNT + x / SIZE;
|
||||
uint8_t *entry = (uint8_t *)&palette[offset];
|
||||
|
||||
fprintf(f, "%u %u %u ",
|
||||
entry[0],
|
||||
entry[1],
|
||||
entry[2]);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool save_global_palette(const nsgif_t *gif)
|
||||
{
|
||||
uint32_t table[NSGIF_MAX_COLOURS];
|
||||
size_t entries;
|
||||
|
||||
nsgif_global_palette(gif, table, &entries);
|
||||
|
||||
return save_palette(nsgif_options.file, "global-palette.ppm",
|
||||
table, entries);
|
||||
}
|
||||
|
||||
static bool save_local_palette(const nsgif_t *gif, uint32_t frame)
|
||||
{
|
||||
static uint32_t table[NSGIF_MAX_COLOURS];
|
||||
char filename[64];
|
||||
size_t entries;
|
||||
|
||||
snprintf(filename, sizeof(filename), "local-palette-%"PRIu32".ppm",
|
||||
frame);
|
||||
|
||||
if (!nsgif_local_palette(gif, frame, table, &entries)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return save_palette(nsgif_options.file, filename, table, entries);
|
||||
}
|
||||
|
||||
static void decode(FILE* ppm, const char *name, nsgif_t *gif, bool first)
|
||||
{
|
||||
nsgif_error err;
|
||||
uint32_t frame_prev = 0;
|
||||
@ -173,7 +258,7 @@ static void decode(FILE* ppm, const char *name, nsgif_t *gif)
|
||||
|
||||
info = nsgif_get_info(gif);
|
||||
|
||||
if (ppm != NULL) {
|
||||
if (first && ppm != NULL) {
|
||||
fprintf(ppm, "P3\n");
|
||||
fprintf(ppm, "# %s\n", name);
|
||||
fprintf(ppm, "# width %u \n", info->width);
|
||||
@ -184,9 +269,12 @@ static void decode(FILE* ppm, const char *name, nsgif_t *gif)
|
||||
info->height * info->frame_count);
|
||||
}
|
||||
|
||||
if (nsgif_options.info == true) {
|
||||
if (first && nsgif_options.info) {
|
||||
print_gif_info(info);
|
||||
}
|
||||
if (first && nsgif_options.palette && info->global_palette) {
|
||||
save_global_palette(gif);
|
||||
}
|
||||
|
||||
/* decode the frames */
|
||||
while (true) {
|
||||
@ -210,7 +298,7 @@ static void decode(FILE* ppm, const char *name, nsgif_t *gif)
|
||||
}
|
||||
frame_prev = frame_new;
|
||||
|
||||
if (nsgif_options.info == true) {
|
||||
if (first && nsgif_options.info) {
|
||||
const nsgif_frame_info_t *f_info;
|
||||
|
||||
f_info = nsgif_get_frame_info(gif, frame_new);
|
||||
@ -218,6 +306,9 @@ static void decode(FILE* ppm, const char *name, nsgif_t *gif)
|
||||
print_gif_frame_info(f_info, frame_new);
|
||||
}
|
||||
}
|
||||
if (first && nsgif_options.palette) {
|
||||
save_local_palette(gif, frame_new);
|
||||
}
|
||||
|
||||
err = nsgif_frame_decode(gif, frame_new, &bitmap);
|
||||
if (err != NSGIF_OK) {
|
||||
@ -226,7 +317,7 @@ static void decode(FILE* ppm, const char *name, nsgif_t *gif)
|
||||
frame_new, nsgif_strerror(err));
|
||||
/* Continue decoding the rest of the frames. */
|
||||
|
||||
} else if (ppm != NULL) {
|
||||
} else if (first && ppm != NULL) {
|
||||
fprintf(ppm, "# frame %u:\n", frame_new);
|
||||
image = (const uint8_t *) bitmap;
|
||||
for (uint32_t y = 0; y != info->height; y++) {
|
||||
@ -299,7 +390,10 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
for (uint64_t i = 0; i < nsgif_options.loops; i++) {
|
||||
decode((i == 0) ? ppm : NULL, nsgif_options.file, gif);
|
||||
decode(ppm, nsgif_options.file, gif, i == 0);
|
||||
|
||||
/* We want to ignore any loop limit in the GIF. */
|
||||
nsgif_reset(gif);
|
||||
}
|
||||
|
||||
if (ppm != NULL) {
|
||||
|
@ -201,6 +201,7 @@ print_frame( const nsgif_frame_info_t *frame_info )
|
||||
|
||||
printf( "frame_info:\n" );
|
||||
printf( " display = %d\n", frame_info->display );
|
||||
printf( " local_palette = %d\n", frame_info->local_palette );
|
||||
printf( " transparency = %d\n", frame_info->transparency );
|
||||
printf( " disposal = %d (%s)\n",
|
||||
frame_info->disposal,
|
||||
@ -222,6 +223,7 @@ print_animation( nsgif_t *anim, const nsgif_info_t *info )
|
||||
printf( " width = %d\n", info->width );
|
||||
printf( " height = %d\n", info->height );
|
||||
printf( " frame_count = %d\n", info->frame_count );
|
||||
printf( " global_palette = %d\n", info->global_palette );
|
||||
printf( " loop_max = %d\n", info->loop_max );
|
||||
printf( " background = %d %d %d %d\n",
|
||||
bg[0], bg[1], bg[2], bg[3] );
|
||||
|
Loading…
Reference in New Issue
Block a user