parent
27621733f2
commit
6a4b249445
@ -38,6 +38,7 @@
|
|||||||
- vips_affine() and vips_similarity() have a "background" parameter
|
- vips_affine() and vips_similarity() have a "background" parameter
|
||||||
- fix nasty jaggies on the edges of affine output, thanks chregu
|
- fix nasty jaggies on the edges of affine output, thanks chregu
|
||||||
- add gif-delay, gif-comment and gif-loop metadata
|
- add gif-delay, gif-comment and gif-loop metadata
|
||||||
|
- add dispose handling to gifload
|
||||||
|
|
||||||
29/8/17 started 8.5.9
|
29/8/17 started 8.5.9
|
||||||
- make --fail stop jpeg read on any libjpeg warning, thanks @mceachen
|
- make --fail stop jpeg read on any libjpeg warning, thanks @mceachen
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
* - colormap can be missing thanks Kleis
|
* - colormap can be missing thanks Kleis
|
||||||
* 21/11/17
|
* 21/11/17
|
||||||
* - add "gif-delay", "gif-loop", "gif-comment" metadata
|
* - add "gif-delay", "gif-loop", "gif-comment" metadata
|
||||||
|
* - add dispose handling
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -134,6 +135,10 @@ typedef struct _VipsForeignLoadGif {
|
|||||||
*/
|
*/
|
||||||
char *comment;
|
char *comment;
|
||||||
|
|
||||||
|
/* The current dispose method.
|
||||||
|
*/
|
||||||
|
int dispose;
|
||||||
|
|
||||||
/* The FILE* we read from.
|
/* The FILE* we read from.
|
||||||
*/
|
*/
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
@ -404,7 +409,14 @@ vips_foreign_load_gif_render_line( VipsForeignLoadGif *gif,
|
|||||||
q[2] = v;
|
q[2] = v;
|
||||||
q[3] = 255;
|
q[3] = 255;
|
||||||
}
|
}
|
||||||
|
else if( gif->dispose == DISPOSE_DO_NOT ) {
|
||||||
|
/* Transparent pixels let the previous frame show
|
||||||
|
* through, ie., do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
|
/* All other modes are just transparent.
|
||||||
|
*/
|
||||||
q[0] = 0;
|
q[0] = 0;
|
||||||
q[1] = 0;
|
q[1] = 0;
|
||||||
q[2] = 0;
|
q[2] = 0;
|
||||||
@ -415,12 +427,12 @@ vips_foreign_load_gif_render_line( VipsForeignLoadGif *gif,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Render the current gif frame into an RGBA buffer. GIFs
|
/* Render the current gif frame into an RGBA buffer. GIFs can accumulate,
|
||||||
* accumulate, so don't clear the buffer first, we need to paint a
|
* depending on the current dispose mode.
|
||||||
* series of frames on top of each other.
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
vips_foreign_load_gif_render( VipsForeignLoadGif *gif, VipsImage *out )
|
vips_foreign_load_gif_render( VipsForeignLoadGif *gif,
|
||||||
|
VipsImage *previous, VipsImage *out )
|
||||||
{
|
{
|
||||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( gif );
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( gif );
|
||||||
GifFileType *file = gif->file;
|
GifFileType *file = gif->file;
|
||||||
@ -544,10 +556,16 @@ vips_foreign_load_gif_graphics_ext( VipsForeignLoadGif *gif,
|
|||||||
if( extension[1] & 0x1 ) {
|
if( extension[1] & 0x1 ) {
|
||||||
gif->transparency = extension[4];
|
gif->transparency = extension[4];
|
||||||
gif->has_transparency = TRUE;
|
gif->has_transparency = TRUE;
|
||||||
VIPS_DEBUG_MSG( "gifload: "
|
VIPS_DEBUG_MSG( "gifload: transparency %d\n",
|
||||||
"seen transparency %d\n", gif->transparency );
|
gif->transparency );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set the current dispose mode. This is read during frame load
|
||||||
|
* to set the meaning of background and transparent pixels.
|
||||||
|
*/
|
||||||
|
gif->dispose = (extension[1] >> 2) & 0x7;
|
||||||
|
VIPS_DEBUG_MSG( "gifload: dispose %d\n", gif->dispose );
|
||||||
|
|
||||||
if( !gif->has_delay ) {
|
if( !gif->has_delay ) {
|
||||||
gif->has_delay = TRUE;
|
gif->has_delay = TRUE;
|
||||||
gif->delay = extension[2] | (extension[3] << 8);
|
gif->delay = extension[2] | (extension[3] << 8);
|
||||||
@ -662,10 +680,12 @@ vips_foreign_load_gif_extension( VipsForeignLoadGif *gif )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Write the next page, if there is one, to @page. Set EOF if we hit the end of
|
/* Write the next page, if there is one, to @page. Set EOF if we hit the end of
|
||||||
* the file. @page must be a memory image of the right size.
|
* the file. @page must be a memory image of the right size. @previous is the
|
||||||
|
* previous frame, if any.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
vips_foreign_load_gif_page( VipsForeignLoadGif *gif, VipsImage *out )
|
vips_foreign_load_gif_page( VipsForeignLoadGif *gif,
|
||||||
|
VipsImage *previous, VipsImage *out )
|
||||||
{
|
{
|
||||||
GifRecordType record;
|
GifRecordType record;
|
||||||
int n_pages;
|
int n_pages;
|
||||||
@ -687,7 +707,7 @@ vips_foreign_load_gif_page( VipsForeignLoadGif *gif, VipsImage *out )
|
|||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( vips_foreign_load_gif_render( gif, out ) )
|
if( vips_foreign_load_gif_render( gif, previous, out ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
n_pages += 1;
|
n_pages += 1;
|
||||||
@ -795,7 +815,7 @@ vips_foreign_load_gif_pages( VipsForeignLoadGif *gif, VipsImage **out )
|
|||||||
if( !(frame = vips_foreign_load_gif_new_page( gif )) )
|
if( !(frame = vips_foreign_load_gif_new_page( gif )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
do {
|
do {
|
||||||
if( vips_foreign_load_gif_page( gif, frame ) ) {
|
if( vips_foreign_load_gif_page( gif, NULL, frame ) ) {
|
||||||
g_object_unref( frame );
|
g_object_unref( frame );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
@ -821,14 +841,19 @@ vips_foreign_load_gif_pages( VipsForeignLoadGif *gif, VipsImage **out )
|
|||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* And init with the previous frame, if any.
|
if( gif->dispose == DISPOSE_BACKGROUND )
|
||||||
*/
|
/* BACKGROUND means the bg shows through, ie. (in web
|
||||||
if( previous )
|
* terms) everything is transparent.
|
||||||
|
*/
|
||||||
|
memset( VIPS_IMAGE_ADDR( frame, 0, 0 ),
|
||||||
|
0,
|
||||||
|
VIPS_IMAGE_SIZEOF_IMAGE( frame ) );
|
||||||
|
else
|
||||||
memcpy( VIPS_IMAGE_ADDR( frame, 0, 0 ),
|
memcpy( VIPS_IMAGE_ADDR( frame, 0, 0 ),
|
||||||
VIPS_IMAGE_ADDR( previous, 0, 0 ),
|
VIPS_IMAGE_ADDR( previous, 0, 0 ),
|
||||||
VIPS_IMAGE_SIZEOF_IMAGE( frame ) );
|
VIPS_IMAGE_SIZEOF_IMAGE( frame ) );
|
||||||
|
|
||||||
if( vips_foreign_load_gif_page( gif, frame ) ) {
|
if( vips_foreign_load_gif_page( gif, previous, frame ) ) {
|
||||||
g_object_unref( frame );
|
g_object_unref( frame );
|
||||||
unref_array( frames );
|
unref_array( frames );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
@ -842,7 +867,12 @@ vips_foreign_load_gif_pages( VipsForeignLoadGif *gif, VipsImage **out )
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
frames = g_slist_append( frames, frame );
|
frames = g_slist_append( frames, frame );
|
||||||
previous = frame;
|
|
||||||
|
/* These two dispose modes set new background frames.
|
||||||
|
*/
|
||||||
|
if( gif->dispose == DISPOSAL_UNSPECIFIED ||
|
||||||
|
gif->dispose == DISPOSE_DO_NOT )
|
||||||
|
previous = frame;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -985,6 +1015,7 @@ vips_foreign_load_gif_init( VipsForeignLoadGif *gif )
|
|||||||
gif->delay = 4;
|
gif->delay = 4;
|
||||||
gif->loop = 0;
|
gif->loop = 0;
|
||||||
gif->comment = NULL;
|
gif->comment = NULL;
|
||||||
|
gif->dispose = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _VipsForeignLoadGifFile {
|
typedef struct _VipsForeignLoadGifFile {
|
||||||
|
Loading…
Reference in New Issue
Block a user