libnsgif: Update to latest upstream. (#2712)

This commit is contained in:
Michael Drake 2022-03-09 10:13:48 +00:00 committed by GitHub
parent 2fdab9ba70
commit 292ee9a47e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 10 deletions

View File

@ -49,10 +49,15 @@ Now you can load the GIF source data into the nsgif object with
This scans the source data and decodes information about each frame, however
it doesn't decode any of the bitmap data for the frames. The client may call
`nsgif_data_scan()` multiple times as source data is fetched. Once the
function has returned `NSGIF_OK` it has enough data to display at least one
frame. The early frames can be decoded before the later frames are scanned.
Frames have to be scanned before they can be decoded.
`nsgif_data_scan()` multiple times as source data is fetched. The early frames
can be decoded before the later frames are scanned. Frames have to be scanned
before they can be decoded.
This function will sometimes return an error. That is OK, and even expected.
It is fine to proceed to decoding any frames that are available after a scan.
Some errors indicate that there is a flaw in the source GIF data (not at all
uncommon, GIF is an ancient format that has had many broken encoders), or that
it has reached the end of the source data.
> **Note**: The client must not free the data until after calling
> `nsgif_destroy()`. You can move the data, e.g. if you realloc to a bigger

View File

@ -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 3 Mar 2022.
Last updated 8 Mar 2022.
# To do

View File

@ -770,6 +770,34 @@ static nsgif_error nsgif__parse_extension_graphic_control(
return NSGIF_OK;
}
/**
* Check an app ext identifier and authentication code for loop count extension.
*
* \param[in] data The data to decode.
* \param[in] len Byte length of data.
* \return true if extension is a loop count extension.
*/
static bool nsgif__app_ext_is_loop_count(
const uint8_t *data,
size_t len)
{
enum {
EXT_LOOP_COUNT_BLOCK_SIZE = 0x0b,
};
assert(len > 13);
(void)(len);
if (data[1] == EXT_LOOP_COUNT_BLOCK_SIZE) {
if (strncmp((const char *)data + 2, "NETSCAPE2.0", 11) == 0 ||
strncmp((const char *)data + 2, "ANIMEXTS1.0", 11) == 0) {
return true;
}
}
return false;
}
/**
* Parse the application extension
*
@ -796,10 +824,24 @@ static nsgif_error nsgif__parse_extension_application(
return NSGIF_ERR_END_OF_DATA;
}
if ((data[1] == 0x0b) &&
(strncmp((const char *)data + 2, "NETSCAPE2.0", 11) == 0) &&
(data[13] == 0x03) && (data[14] == 0x01)) {
gif->info.loop_max = data[15] | (data[16] << 8);
if (nsgif__app_ext_is_loop_count(data, len)) {
enum {
EXT_LOOP_COUNT_SUB_BLOCK_SIZE = 0x03,
EXT_LOOP_COUNT_SUB_BLOCK_ID = 0x01,
};
if ((data[13] == EXT_LOOP_COUNT_SUB_BLOCK_SIZE) &&
(data[14] == EXT_LOOP_COUNT_SUB_BLOCK_ID)) {
gif->info.loop_max = data[15] | (data[16] << 8);
/* The value in the source data means repeat N times
* after the first implied play. A value of zero has
* the special meaning of loop forever. (The only way
* to play the animation once is not to have this
* extension at all. */
if (gif->info.loop_max > 0) {
gif->info.loop_max++;
}
}
}
return NSGIF_OK;

View File

@ -284,7 +284,7 @@ typedef struct nsgif_info {
uint32_t height;
/** number of frames decoded */
uint32_t frame_count;
/** number of times to loop animation */
/** number of times to play animation (zero means loop forever) */
int loop_max;
/** number of animation loops so far */
int loop_count;