make giflib load less fussy
it was refusing to load a few GIFs
This commit is contained in:
parent
a0086e49cd
commit
ae680a8d8c
@ -824,19 +824,18 @@ vips_foreign_load_gif_render( VipsForeignLoadGif *gif )
|
||||
|
||||
for( y = InterlacedOffset[i];
|
||||
y < file->Image.Height;
|
||||
y += InterlacedJumps[i] ) {
|
||||
VipsPel *q = VIPS_IMAGE_ADDR( gif->frame,
|
||||
file->Image.Left, file->Image.Top + y );
|
||||
|
||||
y += InterlacedJumps[i] )
|
||||
if( DGifGetLine( gif->file, gif->line,
|
||||
file->Image.Width ) == GIF_ERROR ) {
|
||||
vips_foreign_load_gif_error( gif );
|
||||
return( -1 );
|
||||
}
|
||||
VipsPel *q = VIPS_IMAGE_ADDR(
|
||||
gif->frame,
|
||||
file->Image.Left,
|
||||
file->Image.Top + y );
|
||||
|
||||
vips_foreign_load_gif_render_line( gif,
|
||||
file->Image.Width, q, gif->line );
|
||||
}
|
||||
vips_foreign_load_gif_render_line( gif,
|
||||
file->Image.Width, q,
|
||||
gif->line );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -847,19 +846,15 @@ vips_foreign_load_gif_render( VipsForeignLoadGif *gif )
|
||||
file->Image.Width, file->Image.Height,
|
||||
file->Image.Left, file->Image.Top );
|
||||
|
||||
for( y = 0; y < file->Image.Height; y++ ) {
|
||||
VipsPel *q = VIPS_IMAGE_ADDR( gif->frame,
|
||||
file->Image.Left, file->Image.Top + y );
|
||||
|
||||
for( y = 0; y < file->Image.Height; y++ )
|
||||
if( DGifGetLine( gif->file, gif->line,
|
||||
file->Image.Width ) == GIF_ERROR ) {
|
||||
vips_foreign_load_gif_error( gif );
|
||||
return( -1 );
|
||||
}
|
||||
file->Image.Width ) != GIF_ERROR ) {
|
||||
VipsPel *q = VIPS_IMAGE_ADDR( gif->frame,
|
||||
file->Image.Left, file->Image.Top + y );
|
||||
|
||||
vips_foreign_load_gif_render_line( gif,
|
||||
file->Image.Width, q, gif->line );
|
||||
}
|
||||
vips_foreign_load_gif_render_line( gif,
|
||||
file->Image.Width, q, gif->line );
|
||||
}
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
@ -915,10 +910,8 @@ vips_foreign_load_gif_next_page( VipsForeignLoadGif *gif )
|
||||
|
||||
have_read_frame = FALSE;
|
||||
do {
|
||||
if( DGifGetRecordType( gif->file, &record ) == GIF_ERROR ) {
|
||||
vips_foreign_load_gif_error( gif );
|
||||
return( -1 );
|
||||
}
|
||||
if( DGifGetRecordType( gif->file, &record ) == GIF_ERROR )
|
||||
continue;
|
||||
|
||||
switch( record ) {
|
||||
case IMAGE_DESC_RECORD_TYPE:
|
||||
|
@ -32,6 +32,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
#define VERBOSE
|
||||
*/
|
||||
#define VIPS_DEBUG
|
||||
|
||||
@ -52,11 +53,23 @@
|
||||
#include <vips/debug.h>
|
||||
|
||||
/* TODO:
|
||||
*
|
||||
* - look into frame / page match up ... what about optimised GIFs where
|
||||
* several frames make up each page?
|
||||
*
|
||||
* - early close
|
||||
* - detect greyscale images
|
||||
* - detect images with transparent pixels
|
||||
*
|
||||
* - libnsgif does not seem to support comment metadata
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* - hard to detect mono images -- local_colour_table in libnsgif is only set
|
||||
* when we decode a frame, so we can't tell just from init whether any
|
||||
* frames
|
||||
*
|
||||
* - don't bother detecting alpha -- if we can't detect RGB, alpha won't help
|
||||
* much
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_LIBNSGIF
|
||||
@ -98,14 +111,6 @@ typedef struct _VipsForeignLoadGif {
|
||||
unsigned char *data;
|
||||
size_t size;
|
||||
|
||||
/* Does this GIF have a non-greyscale colourmap?
|
||||
*/
|
||||
gboolean has_colour;
|
||||
|
||||
/* Does this GIF have any transparent pixels?
|
||||
*/
|
||||
gboolean has_transparency;
|
||||
|
||||
} VipsForeignLoadGif;
|
||||
|
||||
typedef VipsForeignLoadClass VipsForeignLoadGifClass;
|
||||
@ -268,6 +273,7 @@ static gif_bitmap_callback_vt vips_foreign_load_gif_bitmap_callbacks = {
|
||||
vips_foreign_load_gif_bitmap_modified
|
||||
};
|
||||
|
||||
#ifdef VERBOSE
|
||||
static void
|
||||
print_frame( gif_frame *frame )
|
||||
{
|
||||
@ -311,17 +317,15 @@ print_animation( gif_animation *anim )
|
||||
print_frame( &anim->frames[i] );
|
||||
}
|
||||
}
|
||||
#endif /*VERBOSE*/
|
||||
|
||||
static int
|
||||
vips_foreign_load_gif_set_header( VipsForeignLoadGif *gif, VipsImage *image )
|
||||
{
|
||||
vips_image_init_fields( image,
|
||||
gif->anim->width, gif->anim->height * gif->n,
|
||||
(gif->has_colour ? 3 : 1) + (gif->has_transparency ? 1 : 0),
|
||||
gif->anim->width, gif->anim->height * gif->n, 4,
|
||||
VIPS_FORMAT_UCHAR, VIPS_CODING_NONE,
|
||||
gif->has_colour ?
|
||||
VIPS_INTERPRETATION_sRGB : VIPS_INTERPRETATION_B_W,
|
||||
1.0, 1.0 );
|
||||
VIPS_INTERPRETATION_sRGB, 1.0, 1.0 );
|
||||
vips_image_pipelinev( image, VIPS_DEMAND_STYLE_FATSTRIP, NULL );
|
||||
|
||||
if( vips_object_argument_isset( VIPS_OBJECT( gif ), "n" ) )
|
||||
@ -365,11 +369,13 @@ vips_foreign_load_gif_header( VipsForeignLoad *load )
|
||||
|
||||
/* GIF_INSUFFICIENT_FRAME_DATA means we allow truncated GIFs.
|
||||
*
|
||||
* TODO use fail to bail out on truncvated GIFs.
|
||||
* TODO use fail to bail out on truncated GIFs.
|
||||
*/
|
||||
result = gif_initialise( gif->anim, gif->size, gif->data );
|
||||
VIPS_DEBUG_MSG( "gif_initialise() = %d\n", result );
|
||||
#ifdef VERBOSE
|
||||
print_animation( gif->anim );
|
||||
#endif /*VERBOSE*/
|
||||
if( result != GIF_OK &&
|
||||
result != GIF_WORKING &&
|
||||
result != GIF_INSUFFICIENT_FRAME_DATA ) {
|
||||
@ -381,23 +387,15 @@ vips_foreign_load_gif_header( VipsForeignLoad *load )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* TODO test for a non-greyscale colourmap.
|
||||
map = file->Image.ColorMap ? file->Image.ColorMap : file->SColorMap;
|
||||
if( !gif->has_colour &&
|
||||
map ) {
|
||||
int i;
|
||||
if( gif->n == -1 )
|
||||
gif->n = gif->anim->frame_count - gif->page;
|
||||
|
||||
for( i = 0; i < map->ColorCount; i++ )
|
||||
if( map->Colors[i].Red != map->Colors[i].Green ||
|
||||
map->Colors[i].Green != map->Colors[i].Blue ) {
|
||||
gif->has_colour = TRUE;
|
||||
break;
|
||||
}
|
||||
if( gif->page < 0 ||
|
||||
gif->n <= 0 ||
|
||||
gif->page + gif->n > gif->anim->frame_count ) {
|
||||
vips_error( class->nickname, "%s", _( "bad page number" ) );
|
||||
return( -1 );
|
||||
}
|
||||
*/
|
||||
|
||||
/* TODO test for transparency.
|
||||
*/
|
||||
|
||||
vips_foreign_load_gif_set_header( gif, load->out );
|
||||
|
||||
@ -413,8 +411,10 @@ vips_foreign_load_gif_generate( VipsRegion *or,
|
||||
|
||||
int y;
|
||||
|
||||
#ifdef VERBOSE
|
||||
VIPS_DEBUG_MSG( "vips_foreign_load_gif_generate: "
|
||||
"top = %d, height = %d\n", r->top, r->height );
|
||||
#endif /*VERBOSE*/
|
||||
|
||||
for( y = 0; y < r->height; y++ ) {
|
||||
/* The page for this output line, and the line number in page.
|
||||
@ -440,9 +440,13 @@ vips_foreign_load_gif_generate( VipsRegion *or,
|
||||
vips_foreign_load_gif_error( gif, result );
|
||||
return( -1 );
|
||||
}
|
||||
#ifdef VERBOSE
|
||||
print_animation( gif->anim );
|
||||
#endif /*VERBOSE*/
|
||||
}
|
||||
|
||||
/* TODO ... handle G, GA, RGB cases as well.
|
||||
*/
|
||||
p = gif->anim->frame_image +
|
||||
line * gif->anim->width * sizeof( int );
|
||||
q = VIPS_REGION_ADDR( or, 0, r->top + y );
|
||||
@ -461,27 +465,6 @@ vips_foreign_load_gif_load( VipsForeignLoad *load )
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_foreign_load_gif_load:\n" );
|
||||
|
||||
/* Make the memory image we accumulate pixels in. We always accumulate
|
||||
* to RGBA, then trim down to whatever the output image needs on
|
||||
* _generate.
|
||||
gif->frame = vips_image_new_memory();
|
||||
vips_image_init_fields( gif->frame,
|
||||
gif->file->SWidth, gif->file->SHeight, 4, VIPS_FORMAT_UCHAR,
|
||||
VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, 1.0, 1.0 );
|
||||
if( vips_image_write_prepare( gif->frame ) )
|
||||
return( -1 );
|
||||
*/
|
||||
|
||||
/* A copy of the previous state of the frame, in case we have to
|
||||
* process a DISPOSE_PREVIOUS.
|
||||
gif->previous = vips_image_new_memory();
|
||||
vips_image_init_fields( gif->previous,
|
||||
gif->file->SWidth, gif->file->SHeight, 4, VIPS_FORMAT_UCHAR,
|
||||
VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, 1.0, 1.0 );
|
||||
if( vips_image_write_prepare( gif->previous ) )
|
||||
return( -1 );
|
||||
*/
|
||||
|
||||
/* Make the output pipeline.
|
||||
*/
|
||||
t[0] = vips_image_new();
|
||||
@ -548,11 +531,6 @@ static void
|
||||
vips_foreign_load_gif_init( VipsForeignLoadGif *gif )
|
||||
{
|
||||
gif->n = 1;
|
||||
|
||||
/* TODO always read RGBA for now.
|
||||
*/
|
||||
gif->has_colour = TRUE;
|
||||
gif->has_transparency = TRUE;
|
||||
}
|
||||
|
||||
typedef struct _VipsForeignLoadGifFile {
|
||||
|
Loading…
Reference in New Issue
Block a user