Update to latest libnsgif (#2747)
* libnsgif: Update to latest upstream. * nsgifload: Update for new pixel format API. LibNSGIF now lets the client select a pixel colour component order. We use NSGIF_BITMAP_FMT_R8G8B8A8, which is the same format LibNSGIF always decoded to. * nsgifload: Remove loop_count from VERBOSE output. This was internal state for a nsgif_frame_prepare() managed animation, but VIPS doesn't use nsgif_frame_prepare(). The loop_count member has been removed from the public structure.
This commit is contained in:
parent
89bd46d1c4
commit
0f30690360
@ -22,14 +22,17 @@ Using
|
||||
LibNSGIF allows the client to allocate the bitmap into which the GIF is
|
||||
decoded. The client can have an arbitrary bitmap structure, that is simply
|
||||
a void pointer to LibNSGIF. The client must provide a callback table for
|
||||
interacting with bitmaps. This table must include as a minimum functions to
|
||||
create and destroy bitmaps, and a function to get a pointer to the bitmap's
|
||||
pixel data buffer.
|
||||
interacting with bitmaps, and the required client bitmap pixel format.
|
||||
The bitmap table must include as a minimum functions to create and destroy
|
||||
bitmaps, and a function to get a pointer to the bitmap's pixel data buffer.
|
||||
|
||||
LibNSGIF always decodes to a 32bpp, 8 bits per channel bitmap pixel format,
|
||||
however it allows the client to control the colour component ordering.
|
||||
|
||||
To load a GIF, first create an nsgif object with `nsgif_create()`.
|
||||
|
||||
```c
|
||||
err = nsgif_create(&bitmap_callbacks, &gif);
|
||||
err = nsgif_create(&bitmap_callbacks, NSGIF_BITMAP_FMT_R8G8B8A8, &gif);
|
||||
if (err != NSGIF_OK) {
|
||||
fprintf(stderr, "%s\n", nsgif_strerror(err));
|
||||
// Handle error
|
||||
|
@ -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 8 Mar 2022.
|
||||
Last updated 4 Apr 2022.
|
||||
|
||||
# To do
|
||||
|
||||
|
@ -20,6 +20,16 @@
|
||||
/** Maximum colour table size */
|
||||
#define NSGIF_MAX_COLOURS 256
|
||||
|
||||
/** Default minimum allowable frame delay in cs. */
|
||||
#define NSGIF_FRAME_DELAY_MIN 2
|
||||
|
||||
/**
|
||||
* Default frame delay to apply.
|
||||
*
|
||||
* Used when a frame delay lower than the minimum is requested.
|
||||
*/
|
||||
#define NSGIF_FRAME_DELAY_DEFAULT 10
|
||||
|
||||
/** GIF frame data */
|
||||
typedef struct nsgif_frame {
|
||||
struct nsgif_frame_info info;
|
||||
@ -40,6 +50,14 @@ typedef struct nsgif_frame {
|
||||
uint32_t flags;
|
||||
} nsgif_frame;
|
||||
|
||||
/** Pixel format: colour component order. */
|
||||
struct nsgif_colour_layout {
|
||||
uint8_t r; /**< Byte offset within pixel to red component. */
|
||||
uint8_t g; /**< Byte offset within pixel to green component. */
|
||||
uint8_t b; /**< Byte offset within pixel to blue component. */
|
||||
uint8_t a; /**< Byte offset within pixel to alpha component. */
|
||||
};
|
||||
|
||||
/** GIF animation data */
|
||||
struct nsgif {
|
||||
struct nsgif_info info;
|
||||
@ -57,9 +75,15 @@ struct nsgif {
|
||||
/** currently decoded image; stored as bitmap from bitmap_create callback */
|
||||
nsgif_bitmap_t *frame_image;
|
||||
|
||||
/** Minimum allowable frame delay. */
|
||||
uint16_t delay_min;
|
||||
|
||||
/** Frame delay to apply when delay is less than \ref delay_min. */
|
||||
uint16_t delay_default;
|
||||
|
||||
/** number of animation loops so far */
|
||||
int loop_count;
|
||||
|
||||
/** number of frames partially decoded */
|
||||
uint32_t frame_count_partial;
|
||||
|
||||
@ -83,6 +107,8 @@ struct nsgif {
|
||||
bool global_colours;
|
||||
/** current colour table */
|
||||
uint32_t *colour_table;
|
||||
/** Client's colour component order. */
|
||||
struct nsgif_colour_layout colour_layout;
|
||||
/** global colour table */
|
||||
uint32_t global_colour_table[NSGIF_MAX_COLOURS];
|
||||
/** local colour table */
|
||||
@ -580,30 +606,6 @@ static inline nsgif_error nsgif__decode(
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to assign a pixel representation from a gif background colour array.
|
||||
*
|
||||
* \param[in] bg The background colour to read from.
|
||||
* \param[out] px The pixel colour to write.
|
||||
*/
|
||||
static inline void nsgif__gif_bg_to_px(
|
||||
const uint8_t bg[4], uint32_t *px)
|
||||
{
|
||||
*px = *(uint32_t *)bg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to assign a gif background colour array from a pixel representation.
|
||||
*
|
||||
* \param[in] px The pixel colour to read from.
|
||||
* \param[out] bg The background colour to write.
|
||||
*/
|
||||
static inline void nsgif__gif_px_to_bg(
|
||||
const uint32_t *px, uint8_t bg[4])
|
||||
{
|
||||
*(uint32_t *)bg = *px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore a GIF to the background colour.
|
||||
*
|
||||
@ -646,9 +648,7 @@ static void nsgif__restore_bg(
|
||||
uint32_t *scanline = bitmap + offset_x +
|
||||
(offset_y + y) * gif->info.width;
|
||||
for (uint32_t x = 0; x < width; x++) {
|
||||
nsgif__gif_bg_to_px(
|
||||
gif->info.background,
|
||||
&scanline[x]);
|
||||
scanline[x] = gif->info.background;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1042,6 +1042,7 @@ static nsgif_error nsgif__parse_image_descriptor(
|
||||
static nsgif_error nsgif__colour_table_extract(
|
||||
struct nsgif *gif,
|
||||
uint32_t colour_table[NSGIF_MAX_COLOURS],
|
||||
const struct nsgif_colour_layout *layout,
|
||||
size_t colour_table_entries,
|
||||
const uint8_t **pos,
|
||||
bool decode)
|
||||
@ -1060,16 +1061,16 @@ static nsgif_error nsgif__colour_table_extract(
|
||||
while (count--) {
|
||||
/* Gif colour map contents are r,g,b.
|
||||
*
|
||||
* We want to pack them bytewise into the
|
||||
* colour table, such that the red component
|
||||
* is in byte 0 and the alpha component is in
|
||||
* byte 3.
|
||||
* We want to pack them bytewise into the colour table,
|
||||
* according to the client colour layout.
|
||||
*/
|
||||
|
||||
*entry++ = *data++; /* r */
|
||||
*entry++ = *data++; /* g */
|
||||
*entry++ = *data++; /* b */
|
||||
*entry++ = 0xff; /* a */
|
||||
entry[layout->r] = *data++;
|
||||
entry[layout->g] = *data++;
|
||||
entry[layout->b] = *data++;
|
||||
entry[layout->a] = 0xff;
|
||||
|
||||
entry += sizeof(uint32_t);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1104,7 +1105,8 @@ static nsgif_error nsgif__parse_colour_table(
|
||||
return NSGIF_OK;
|
||||
}
|
||||
|
||||
ret = nsgif__colour_table_extract(gif, gif->local_colour_table,
|
||||
ret = nsgif__colour_table_extract(gif,
|
||||
gif->local_colour_table, &gif->colour_layout,
|
||||
2 << (frame->flags & NSGIF_COLOUR_TABLE_SIZE_MASK),
|
||||
pos, decode);
|
||||
if (ret != NSGIF_OK) {
|
||||
@ -1343,8 +1345,90 @@ void nsgif_destroy(nsgif_t *gif)
|
||||
free(gif);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the host is little endian.
|
||||
*
|
||||
* Checks whether least significant bit is in the first byte of a `uint16_t`.
|
||||
*
|
||||
* \return true if host is little endian.
|
||||
*/
|
||||
static inline bool nsgif__host_is_little_endian(void)
|
||||
{
|
||||
const uint16_t test = 1;
|
||||
|
||||
return ((const uint8_t *) &test)[0];
|
||||
}
|
||||
|
||||
static struct nsgif_colour_layout nsgif__bitmap_fmt_to_colour_layout(
|
||||
nsgif_bitmap_fmt_t bitmap_fmt)
|
||||
{
|
||||
bool le = nsgif__host_is_little_endian();
|
||||
|
||||
/* Map endian-dependant formats to byte-wise format for the host. */
|
||||
switch (bitmap_fmt) {
|
||||
case NSGIF_BITMAP_FMT_RGBA8888:
|
||||
bitmap_fmt = (le) ? NSGIF_BITMAP_FMT_A8B8G8R8
|
||||
: NSGIF_BITMAP_FMT_R8G8B8A8;
|
||||
break;
|
||||
case NSGIF_BITMAP_FMT_BGRA8888:
|
||||
bitmap_fmt = (le) ? NSGIF_BITMAP_FMT_A8R8G8B8
|
||||
: NSGIF_BITMAP_FMT_B8G8R8A8;
|
||||
break;
|
||||
case NSGIF_BITMAP_FMT_ARGB8888:
|
||||
bitmap_fmt = (le) ? NSGIF_BITMAP_FMT_B8G8R8A8
|
||||
: NSGIF_BITMAP_FMT_A8R8G8B8;
|
||||
break;
|
||||
case NSGIF_BITMAP_FMT_ABGR8888:
|
||||
bitmap_fmt = (le) ? NSGIF_BITMAP_FMT_R8G8B8A8
|
||||
: NSGIF_BITMAP_FMT_A8B8G8R8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set up colour component order for bitmap format. */
|
||||
switch (bitmap_fmt) {
|
||||
default:
|
||||
/* Fall through. */
|
||||
case NSGIF_BITMAP_FMT_R8G8B8A8:
|
||||
return (struct nsgif_colour_layout) {
|
||||
.r = 0,
|
||||
.g = 1,
|
||||
.b = 2,
|
||||
.a = 3,
|
||||
};
|
||||
|
||||
case NSGIF_BITMAP_FMT_B8G8R8A8:
|
||||
return (struct nsgif_colour_layout) {
|
||||
.b = 0,
|
||||
.g = 1,
|
||||
.r = 2,
|
||||
.a = 3,
|
||||
};
|
||||
|
||||
case NSGIF_BITMAP_FMT_A8R8G8B8:
|
||||
return (struct nsgif_colour_layout) {
|
||||
.a = 0,
|
||||
.r = 1,
|
||||
.g = 2,
|
||||
.b = 3,
|
||||
};
|
||||
|
||||
case NSGIF_BITMAP_FMT_A8B8G8R8:
|
||||
return (struct nsgif_colour_layout) {
|
||||
.a = 0,
|
||||
.b = 1,
|
||||
.g = 2,
|
||||
.r = 3,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/* exported function documented in nsgif.h */
|
||||
nsgif_error nsgif_create(const nsgif_bitmap_cb_vt *bitmap_vt, nsgif_t **gif_out)
|
||||
nsgif_error nsgif_create(
|
||||
const nsgif_bitmap_cb_vt *bitmap_vt,
|
||||
nsgif_bitmap_fmt_t bitmap_fmt,
|
||||
nsgif_t **gif_out)
|
||||
{
|
||||
nsgif_t *gif;
|
||||
|
||||
@ -1357,13 +1441,25 @@ nsgif_error nsgif_create(const nsgif_bitmap_cb_vt *bitmap_vt, nsgif_t **gif_out)
|
||||
gif->decoded_frame = NSGIF_FRAME_INVALID;
|
||||
gif->prev_index = NSGIF_FRAME_INVALID;
|
||||
|
||||
gif->delay_min = 2;
|
||||
gif->delay_default = 10;
|
||||
gif->delay_min = NSGIF_FRAME_DELAY_MIN;
|
||||
gif->delay_default = NSGIF_FRAME_DELAY_DEFAULT;
|
||||
|
||||
gif->colour_layout = nsgif__bitmap_fmt_to_colour_layout(bitmap_fmt);
|
||||
|
||||
*gif_out = gif;
|
||||
return NSGIF_OK;
|
||||
}
|
||||
|
||||
/* exported function documented in nsgif.h */
|
||||
void nsgif_set_frame_delay_behaviour(
|
||||
nsgif_t *gif,
|
||||
uint16_t delay_min,
|
||||
uint16_t delay_default)
|
||||
{
|
||||
gif->delay_min = delay_min;
|
||||
gif->delay_default = delay_default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read GIF header.
|
||||
*
|
||||
@ -1535,6 +1631,7 @@ nsgif_error nsgif_data_scan(
|
||||
if (gif->global_colours) {
|
||||
ret = nsgif__colour_table_extract(gif,
|
||||
gif->global_colour_table,
|
||||
&gif->colour_layout,
|
||||
gif->colour_table_size,
|
||||
&nsgif_data, true);
|
||||
if (ret != NSGIF_OK) {
|
||||
@ -1544,27 +1641,30 @@ nsgif_error nsgif_data_scan(
|
||||
gif->buf_pos = (nsgif_data - gif->buf);
|
||||
} else {
|
||||
/* Create a default colour table with the first two
|
||||
* colours as black and white
|
||||
*/
|
||||
uint32_t *entry = gif->global_colour_table;
|
||||
* colours as black and white. */
|
||||
uint8_t *entry = (uint8_t *)gif->global_colour_table;
|
||||
|
||||
entry[0] = 0x00000000;
|
||||
/* Force Alpha channel to opaque */
|
||||
((uint8_t *) entry)[3] = 0xff;
|
||||
/* Black */
|
||||
entry[gif->colour_layout.r] = 0x00;
|
||||
entry[gif->colour_layout.g] = 0x00;
|
||||
entry[gif->colour_layout.b] = 0x00;
|
||||
entry[gif->colour_layout.a] = 0xFF;
|
||||
|
||||
entry[1] = 0xffffffff;
|
||||
entry += sizeof(uint32_t);
|
||||
|
||||
/* White */
|
||||
entry[gif->colour_layout.r] = 0xFF;
|
||||
entry[gif->colour_layout.g] = 0xFF;
|
||||
entry[gif->colour_layout.b] = 0xFF;
|
||||
entry[gif->colour_layout.a] = 0xFF;
|
||||
}
|
||||
|
||||
if (gif->global_colours &&
|
||||
gif->bg_index < gif->colour_table_size) {
|
||||
size_t bg_idx = gif->bg_index;
|
||||
nsgif__gif_px_to_bg(
|
||||
&gif->global_colour_table[bg_idx],
|
||||
gif->info.background);
|
||||
gif->info.background = gif->global_colour_table[bg_idx];
|
||||
} else {
|
||||
nsgif__gif_px_to_bg(
|
||||
&gif->global_colour_table[0],
|
||||
gif->info.background);
|
||||
gif->info.background = gif->global_colour_table[0];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1663,7 +1763,7 @@ static inline bool nsgif__animation_complete(int count, int max)
|
||||
nsgif_error nsgif_reset(
|
||||
nsgif_t *gif)
|
||||
{
|
||||
gif->info.loop_count = 0;
|
||||
gif->loop_count = 0;
|
||||
gif->frame = NSGIF_FRAME_INVALID;
|
||||
|
||||
return NSGIF_OK;
|
||||
@ -1691,7 +1791,7 @@ nsgif_error nsgif_frame_prepare(
|
||||
}
|
||||
|
||||
if (nsgif__animation_complete(
|
||||
gif->info.loop_count,
|
||||
gif->loop_count,
|
||||
gif->info.loop_max)) {
|
||||
return NSGIF_ERR_ANIMATION_END;
|
||||
}
|
||||
@ -1702,7 +1802,7 @@ nsgif_error nsgif_frame_prepare(
|
||||
}
|
||||
|
||||
if (gif->frame != NSGIF_FRAME_INVALID && frame < gif->frame) {
|
||||
gif->info.loop_count++;
|
||||
gif->loop_count++;
|
||||
}
|
||||
|
||||
if (gif->info.frame_count == 1) {
|
||||
@ -1717,7 +1817,7 @@ nsgif_error nsgif_frame_prepare(
|
||||
|
||||
if (frame_next < frame) {
|
||||
if (nsgif__animation_complete(
|
||||
gif->info.loop_count + 1,
|
||||
gif->loop_count + 1,
|
||||
gif->info.loop_max)) {
|
||||
delay = NSGIF_INFINITE;
|
||||
}
|
||||
|
@ -98,15 +98,70 @@ typedef enum {
|
||||
NSGIF_ERR_ANIMATION_END,
|
||||
} nsgif_error;
|
||||
|
||||
/**
|
||||
* NSGIF \ref nsgif_bitmap_t pixel format.
|
||||
*
|
||||
* All pixel formats are 32 bits per pixel (bpp). The different formats
|
||||
* allow control over the ordering of the colour channels. All colour
|
||||
* channels are 8 bits wide.
|
||||
*
|
||||
* Note that the GIF file format only supports an on/off mask, so the
|
||||
* alpha (A) component (opacity) will always have a value of `0` (fully
|
||||
* transparent) or `255` (fully opaque).
|
||||
*/
|
||||
typedef enum nsgif_bitmap_fmt {
|
||||
/** Bite-wise RGBA: Byte order: 0xRR, 0xGG, 0xBB, 0xAA. */
|
||||
NSGIF_BITMAP_FMT_R8G8B8A8,
|
||||
|
||||
/** Bite-wise BGRA: Byte order: 0xBB, 0xGG, 0xRR, 0xAA. */
|
||||
NSGIF_BITMAP_FMT_B8G8R8A8,
|
||||
|
||||
/** Bite-wise ARGB: Byte order: 0xAA, 0xRR, 0xGG, 0xBB. */
|
||||
NSGIF_BITMAP_FMT_A8R8G8B8,
|
||||
|
||||
/** Bite-wise ABGR: Byte order: 0xAA, 0xBB, 0xGG, 0xRR. */
|
||||
NSGIF_BITMAP_FMT_A8B8G8R8,
|
||||
|
||||
/**
|
||||
* 32-bit RGBA (0xRRGGBBAA).
|
||||
*
|
||||
* * On little endian host, same as \ref NSGIF_BITMAP_FMT_A8B8G8R8.
|
||||
* * On big endian host, same as \ref NSGIF_BITMAP_FMT_R8G8B8A8.
|
||||
*/
|
||||
NSGIF_BITMAP_FMT_RGBA8888,
|
||||
|
||||
/**
|
||||
* 32-bit BGRA (0xBBGGRRAA).
|
||||
*
|
||||
* * On little endian host, same as \ref NSGIF_BITMAP_FMT_A8R8G8B8.
|
||||
* * On big endian host, same as \ref NSGIF_BITMAP_FMT_B8G8R8A8.
|
||||
*/
|
||||
NSGIF_BITMAP_FMT_BGRA8888,
|
||||
|
||||
/**
|
||||
* 32-bit ARGB (0xAARRGGBB).
|
||||
*
|
||||
* * On little endian host, same as \ref NSGIF_BITMAP_FMT_B8G8R8A8.
|
||||
* * On big endian host, same as \ref NSGIF_BITMAP_FMT_A8R8G8B8.
|
||||
*/
|
||||
NSGIF_BITMAP_FMT_ARGB8888,
|
||||
|
||||
/**
|
||||
* 32-bit BGRA (0xAABBGGRR).
|
||||
*
|
||||
* * On little endian host, same as \ref NSGIF_BITMAP_FMT_R8G8B8A8.
|
||||
* * On big endian host, same as \ref NSGIF_BITMAP_FMT_A8B8G8R8.
|
||||
*/
|
||||
NSGIF_BITMAP_FMT_ABGR8888,
|
||||
} nsgif_bitmap_fmt_t;
|
||||
|
||||
/**
|
||||
* Client bitmap type.
|
||||
*
|
||||
* These are client-created and destroyed, via the \ref bitmap callbacks,
|
||||
* but they are owned by a \ref nsgif_t.
|
||||
*
|
||||
* The pixel buffer is is 32bpp, treated as individual bytes in the component
|
||||
* order RR GG BB AA. For example, a 1x1 image with a single orange pixel would
|
||||
* be encoded as the following sequence of bytes: 0xff, 0x88, 0x00, 0x00.
|
||||
* See \ref nsgif_bitmap_fmt for pixel format information.
|
||||
*/
|
||||
typedef void nsgif_bitmap_t;
|
||||
|
||||
@ -176,13 +231,15 @@ const char *nsgif_strerror(nsgif_error err);
|
||||
/**
|
||||
* Create the NSGIF object.
|
||||
*
|
||||
* \param[in] bitmap_vt Bitmap operation functions v-table.
|
||||
* \param[out] gif_out Return \ref nsgif_t object on success.
|
||||
* \param[in] bitmap_vt Bitmap operation functions v-table.
|
||||
* \param[in] bitmap_fmt Bitmap pixel format specification.
|
||||
* \param[out] gif_out Return \ref nsgif_t object on success.
|
||||
*
|
||||
* \return NSGIF_OK on success, or appropriate error otherwise.
|
||||
*/
|
||||
nsgif_error nsgif_create(
|
||||
const nsgif_bitmap_cb_vt *bitmap_vt,
|
||||
nsgif_bitmap_fmt_t bitmap_fmt,
|
||||
nsgif_t **gif_out);
|
||||
|
||||
/**
|
||||
@ -286,10 +343,8 @@ typedef struct nsgif_info {
|
||||
uint32_t frame_count;
|
||||
/** number of times to play animation (zero means loop forever) */
|
||||
int loop_max;
|
||||
/** number of animation loops so far */
|
||||
int loop_count;
|
||||
/** background colour in same pixel format as \ref nsgif_bitmap_t. */
|
||||
uint8_t background[4];
|
||||
uint32_t background;
|
||||
} nsgif_info_t;
|
||||
|
||||
/**
|
||||
@ -353,4 +408,35 @@ const nsgif_frame_info_t *nsgif_get_frame_info(
|
||||
const nsgif_t *gif,
|
||||
uint32_t frame);
|
||||
|
||||
/**
|
||||
* Configure handling of small frame delays.
|
||||
*
|
||||
* Historically people created GIFs with a tiny frame delay, however the slow
|
||||
* hardware of the time meant they actually played much slower. As computers
|
||||
* sped up, to prevent animations playing faster than intended, decoders came
|
||||
* to ignore overly small frame delays.
|
||||
*
|
||||
* By default a \ref nsgif_frame_prepare() managed animation will override
|
||||
* frame delays of less than 2 centiseconds with a default frame delay of
|
||||
* 10 centiseconds. This matches the behaviour of web browsers and other
|
||||
* renderers.
|
||||
*
|
||||
* Both the minimum and the default values can be overridden for a given GIF
|
||||
* by the client. To get frame delays exactly as specified by the GIF file, set
|
||||
* \ref delay_min to zero.
|
||||
*
|
||||
* Note that this does not affect the frame delay in the frame info
|
||||
* (\ref nsgif_frame_info_t) structure, which will always contain values
|
||||
* specified by the GIF.
|
||||
*
|
||||
* \param[in] gif The \ref nsgif_t object to configure.
|
||||
* \param[in] delay_min The minimum frame delay in centiseconds.
|
||||
* \param[in] delay_default The delay to use if a frame delay is less than
|
||||
* \ref delay_min.
|
||||
*/
|
||||
void nsgif_set_frame_delay_behaviour(
|
||||
nsgif_t *gif,
|
||||
uint16_t delay_min,
|
||||
uint16_t delay_default);
|
||||
|
||||
#endif
|
||||
|
@ -135,15 +135,17 @@ static void warning(const char *context, nsgif_error err)
|
||||
|
||||
static void print_gif_info(const nsgif_info_t *info)
|
||||
{
|
||||
const uint8_t *bg = (uint8_t *) &info->background;
|
||||
|
||||
fprintf(stdout, "gif:\n");
|
||||
fprintf(stdout, " width: %"PRIu32"\n", info->width);
|
||||
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, " background:\n");
|
||||
fprintf(stdout, " red: 0x%"PRIx8"\n", info->background[0]);
|
||||
fprintf(stdout, " green: 0x%"PRIx8"\n", info->background[1]);
|
||||
fprintf(stdout, " blue: 0x%"PRIx8"\n", info->background[2]);
|
||||
fprintf(stdout, " red: 0x%"PRIx8"\n", bg[0]);
|
||||
fprintf(stdout, " green: 0x%"PRIx8"\n", bg[1]);
|
||||
fprintf(stdout, " blue: 0x%"PRIx8"\n", bg[2]);
|
||||
fprintf(stdout, " frames:\n");
|
||||
}
|
||||
|
||||
@ -272,7 +274,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* create our gif animation */
|
||||
err = nsgif_create(&bitmap_callbacks, &gif);
|
||||
err = nsgif_create(&bitmap_callbacks, NSGIF_BITMAP_FMT_R8G8B8A8, &gif);
|
||||
if (err != NSGIF_OK) {
|
||||
warning("nsgif_create", err);
|
||||
return EXIT_FAILURE;
|
||||
|
@ -216,18 +216,15 @@ static void
|
||||
print_animation( nsgif_t *anim, const nsgif_info_t *info )
|
||||
{
|
||||
int i;
|
||||
const uint8_t *bg = (uint8_t *) &info->background;
|
||||
|
||||
printf( "animation:\n" );
|
||||
printf( " width = %d\n", info->width );
|
||||
printf( " height = %d\n", info->height );
|
||||
printf( " frame_count = %d\n", info->frame_count );
|
||||
printf( " loop_max = %d\n", info->loop_max );
|
||||
printf( " loop_count = %d\n", info->loop_count );
|
||||
printf( " background = %d %d %d %d\n",
|
||||
info->background[0],
|
||||
info->background[1],
|
||||
info->background[2],
|
||||
info->background[3] );
|
||||
bg[0], bg[1], bg[2], bg[3] );
|
||||
|
||||
for( i = 0; i < info->frame_count; i++ ) {
|
||||
printf( "%d ", i );
|
||||
@ -242,6 +239,7 @@ vips_foreign_load_nsgif_set_header( VipsForeignLoadNsgif *gif,
|
||||
VipsImage *image )
|
||||
{
|
||||
double array[3];
|
||||
const uint8_t *bg;
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_foreign_load_nsgif_set_header:\n" );
|
||||
|
||||
@ -265,9 +263,11 @@ vips_foreign_load_nsgif_set_header( VipsForeignLoadNsgif *gif,
|
||||
vips_image_set_array_int( image, "delay",
|
||||
gif->delay, gif->info->frame_count );
|
||||
|
||||
array[0] = gif->info->background[0];
|
||||
array[1] = gif->info->background[1];
|
||||
array[2] = gif->info->background[2];
|
||||
|
||||
bg = (uint8_t *) &gif->info->background;
|
||||
array[0] = bg[0];
|
||||
array[1] = bg[1];
|
||||
array[2] = bg[2];
|
||||
|
||||
vips_image_set_array_double( image, "background", array, 3 );
|
||||
|
||||
@ -557,6 +557,7 @@ vips_foreign_load_nsgif_init( VipsForeignLoadNsgif *gif )
|
||||
{
|
||||
nsgif_error result = nsgif_create(
|
||||
&vips_foreign_load_nsgif_bitmap_callbacks,
|
||||
NSGIF_BITMAP_FMT_R8G8B8A8,
|
||||
&gif->anim );
|
||||
if (result != NSGIF_OK) {
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( gif );
|
||||
|
Loading…
Reference in New Issue
Block a user