almost loading
This commit is contained in:
parent
e12b44e790
commit
617d910379
@ -50,8 +50,8 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
#define VIPS_DEBUG
|
||||
*/
|
||||
#define VIPS_DEBUG
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
@ -93,19 +93,6 @@
|
||||
#define DISPOSE_PREVIOUS 3
|
||||
#endif
|
||||
|
||||
/* TODO:
|
||||
*
|
||||
* - once we know this, we can set the header of the output image
|
||||
*
|
||||
* - second slow scan driven by _generate to render pages as required, with a
|
||||
* single page held as a memory image
|
||||
*
|
||||
* Try the fast scan idea first -- can we get everything we need quickly?
|
||||
*
|
||||
* Need vmethods for open/close/rewind in base class, implement in file and
|
||||
* buffer.
|
||||
*/
|
||||
|
||||
#define VIPS_TYPE_FOREIGN_LOAD_GIF (vips_foreign_load_gif_get_type())
|
||||
#define VIPS_FOREIGN_LOAD_GIF( obj ) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST( (obj), \
|
||||
@ -157,6 +144,10 @@ typedef struct _VipsForeignLoadGif {
|
||||
*/
|
||||
char *comment;
|
||||
|
||||
/* The number of pages (frame) in the image.
|
||||
*/
|
||||
int n_pages;
|
||||
|
||||
/* A memory image the sized of one frame ... we accumulate to this as
|
||||
* we scan the image, and copy lines to the output on generate.
|
||||
*/
|
||||
@ -404,12 +395,28 @@ vips_foreign_load_gif_code_next( VipsForeignLoadGif *gif,
|
||||
static int
|
||||
vips_foreign_load_gif_scan_image_record( VipsForeignLoadGif *gif )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( gif );
|
||||
GifFileType *file = gif->file;
|
||||
ColorMapObject *map = file->Image.ColorMap ?
|
||||
file->Image.ColorMap : file->SColorMap;
|
||||
|
||||
GifByteType *extension;
|
||||
|
||||
/* Check that the frame looks sane. Perhaps giflib checks
|
||||
* this for us.
|
||||
*/
|
||||
if( file->Image.Left < 0 ||
|
||||
file->Image.Width < 1 ||
|
||||
file->Image.Width > 10000 ||
|
||||
file->Image.Left + file->Image.Width > file->SWidth ||
|
||||
file->Image.Top < 0 ||
|
||||
file->Image.Height < 1 ||
|
||||
file->Image.Height > 10000 ||
|
||||
file->Image.Top + file->Image.Height > file->SHeight ) {
|
||||
vips_error( class->nickname, "%s", _( "bad frame size" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* Test for a non-greyscale colourmap for this frame.
|
||||
*/
|
||||
if( !gif->has_colour &&
|
||||
@ -508,10 +515,13 @@ vips_foreign_load_gif_scan_extension( VipsForeignLoadGif *gif )
|
||||
switch( ext_code ) {
|
||||
case GRAPHICS_EXT_FUNC_CODE:
|
||||
if( extension[0] == 4 &&
|
||||
extension[1] & 0x1 )
|
||||
extension[1] & 0x1 ) {
|
||||
VIPS_DEBUG_MSG( "gifload: has transp.\n" );
|
||||
gif->has_transparency = TRUE;
|
||||
}
|
||||
|
||||
if( !gif->has_delay ) {
|
||||
VIPS_DEBUG_MSG( "gifload: has delay\n" );
|
||||
gif->has_delay = TRUE;
|
||||
gif->delay = extension[2] | (extension[3] << 8);
|
||||
}
|
||||
@ -548,29 +558,52 @@ vips_foreign_load_gif_scan_extension( VipsForeignLoadGif *gif )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Attempt to quickly scan a GIF and discover:
|
||||
* - number of frames (pages)
|
||||
* - mono or colour (check colourmap on each page)
|
||||
* - has transparency (check bit in ext block on every page)
|
||||
static int
|
||||
vips_foreign_load_gif_set_header( VipsForeignLoadGif *gif, VipsImage *image )
|
||||
{
|
||||
vips_image_init_fields( image,
|
||||
gif->file->SWidth, gif->file->SHeight * gif->n,
|
||||
(gif->has_colour ? 3 : 1) + (gif->has_transparency ? 1 : 0),
|
||||
VIPS_FORMAT_UCHAR, VIPS_CODING_NONE,
|
||||
gif->has_colour ?
|
||||
VIPS_INTERPRETATION_sRGB : VIPS_INTERPRETATION_B_W,
|
||||
1.0, 1.0 );
|
||||
vips_image_pipelinev( image, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
|
||||
if( gif->n_pages > 1 ) {
|
||||
vips_image_set_int( image,
|
||||
VIPS_META_PAGE_HEIGHT, gif->file->SHeight );
|
||||
vips_image_set_int( image, VIPS_META_N_PAGES, gif->n_pages );
|
||||
}
|
||||
vips_image_set_int( image, "gif-delay", gif->delay );
|
||||
vips_image_set_int( image, "gif-loop", gif->loop );
|
||||
if( gif->comment )
|
||||
vips_image_set_string( image, "gif-comment", gif->comment );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Attempt to quickly scan a GIF and discover what we need for our header. We
|
||||
* need to scan the whole file to get n_pages, transparency and colour.
|
||||
*/
|
||||
static int
|
||||
vips_foreign_load_gif_header( VipsForeignLoad *load )
|
||||
{
|
||||
VipsForeignLoadGifClass *class =
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( load );
|
||||
VipsForeignLoadGifClass *gif_class =
|
||||
(VipsForeignLoadGifClass *) VIPS_OBJECT_GET_CLASS( load );
|
||||
VipsForeignLoadGif *gif = (VipsForeignLoadGif *) load;
|
||||
|
||||
GifRecordType record;
|
||||
int n_pages;
|
||||
|
||||
printf( "vips_foreign_load_gif_header:\n" );
|
||||
|
||||
if( class->open( gif ) )
|
||||
if( gif_class->open( gif ) )
|
||||
return( -1 );
|
||||
|
||||
printf( "vips_foreign_load_gif_header: starting page scan\n" );
|
||||
|
||||
n_pages = 0;
|
||||
gif->n_pages = 0;
|
||||
|
||||
do {
|
||||
if( DGifGetRecordType( gif->file, &record ) == GIF_ERROR ) {
|
||||
@ -592,7 +625,7 @@ vips_foreign_load_gif_header( VipsForeignLoad *load )
|
||||
if( vips_foreign_load_gif_scan_image_record( gif ) )
|
||||
return( -1 );
|
||||
|
||||
n_pages += 1;
|
||||
gif->n_pages += 1;
|
||||
|
||||
break;
|
||||
|
||||
@ -622,40 +655,23 @@ vips_foreign_load_gif_header( VipsForeignLoad *load )
|
||||
}
|
||||
} while( !gif->eof );
|
||||
|
||||
printf( "vips_foreign_load_gif_header: found %d pages\n", n_pages );
|
||||
printf( "vips_foreign_load_gif_header: found %d pages\n",
|
||||
gif->n_pages );
|
||||
|
||||
/* 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 );
|
||||
vips_image_pipelinev( gif->frame, VIPS_DEMAND_STYLE_ANY, NULL );
|
||||
if( vips_image_write_prepare( gif->frame ) )
|
||||
return( -1 );
|
||||
if( gif->n == -1 )
|
||||
gif->n = gif->n_pages - gif->page;
|
||||
|
||||
/* The real output image is long, and made on demand in _generate.
|
||||
*/
|
||||
vips_image_init_fields( load->out,
|
||||
gif->file->SWidth, gif->file->SHeight * n_pages,
|
||||
(gif->has_colour ? 3 : 1) + (gif->has_transparency ? 1 : 0),
|
||||
VIPS_FORMAT_UCHAR, VIPS_CODING_NONE,
|
||||
gif->has_colour ?
|
||||
VIPS_INTERPRETATION_sRGB : VIPS_INTERPRETATION_B_W,
|
||||
1.0, 1.0 );
|
||||
vips_image_pipelinev( load->out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
|
||||
if( n_pages > 1 ) {
|
||||
vips_image_set_int( load->out,
|
||||
VIPS_META_PAGE_HEIGHT, gif->file->SHeight );
|
||||
vips_image_set_int( load->out, VIPS_META_N_PAGES, n_pages );
|
||||
if( gif->page < 0 ||
|
||||
gif->n <= 0 ||
|
||||
gif->page + gif->n > gif->n_pages ) {
|
||||
vips_error( class->nickname, "%s", _( "bad page number" ) );
|
||||
return( -1 );
|
||||
}
|
||||
vips_image_set_int( load->out, "gif-delay", gif->delay );
|
||||
vips_image_set_int( load->out, "gif-loop", gif->loop );
|
||||
if( gif->comment )
|
||||
vips_image_set_string( load->out, "gif-comment", gif->comment );
|
||||
|
||||
/* And set the output vips header from what we've learned.
|
||||
*/
|
||||
if( vips_foreign_load_gif_set_header( gif, load->out ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -710,39 +726,9 @@ vips_foreign_load_gif_render_line( VipsForeignLoadGif *gif,
|
||||
* depending on the current dispose mode.
|
||||
*/
|
||||
static int
|
||||
vips_foreign_load_gif_render( VipsForeignLoadGif *gif,
|
||||
VipsImage *previous, VipsImage *out )
|
||||
vips_foreign_load_gif_render( VipsForeignLoadGif *gif )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( gif );
|
||||
GifFileType *file = gif->file;
|
||||
ColorMapObject *map = file->Image.ColorMap ?
|
||||
file->Image.ColorMap : file->SColorMap;
|
||||
|
||||
/* Check that the frame lies within our image.
|
||||
*/
|
||||
if( file->Image.Left < 0 ||
|
||||
file->Image.Left + file->Image.Width > out->Xsize ||
|
||||
file->Image.Top < 0 ||
|
||||
file->Image.Top + file->Image.Height > out->Ysize ) {
|
||||
vips_error( class->nickname,
|
||||
"%s", _( "frame is outside image area" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* Check if we have a non-greyscale colourmap for this frame.
|
||||
*/
|
||||
if( !gif->has_colour &&
|
||||
map ) {
|
||||
int i;
|
||||
|
||||
for( i = 0; i < map->ColorCount; i++ )
|
||||
if( map->Colors[i].Red != map->Colors[i].Green ||
|
||||
map->Colors[i].Green != map->Colors[i].Blue ) {
|
||||
VIPS_DEBUG_MSG( "gifload: not mono\n" );
|
||||
gif->has_colour = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( file->Image.Interlace ) {
|
||||
int i;
|
||||
@ -758,7 +744,7 @@ vips_foreign_load_gif_render( VipsForeignLoadGif *gif,
|
||||
for( y = InterlacedOffset[i];
|
||||
y < file->Image.Height;
|
||||
y += InterlacedJumps[i] ) {
|
||||
VipsPel *q = VIPS_IMAGE_ADDR( out,
|
||||
VipsPel *q = VIPS_IMAGE_ADDR( gif->frame,
|
||||
file->Image.Left, file->Image.Top + y );
|
||||
|
||||
if( DGifGetLine( gif->file, gif->line,
|
||||
@ -781,7 +767,7 @@ vips_foreign_load_gif_render( VipsForeignLoadGif *gif,
|
||||
file->Image.Left, file->Image.Top );
|
||||
|
||||
for( y = 0; y < file->Image.Height; y++ ) {
|
||||
VipsPel *q = VIPS_IMAGE_ADDR( out,
|
||||
VipsPel *q = VIPS_IMAGE_ADDR( gif->frame,
|
||||
file->Image.Left, file->Image.Top + y );
|
||||
|
||||
if( DGifGetLine( gif->file, gif->line,
|
||||
@ -836,19 +822,15 @@ vips_foreign_load_gif_extension( VipsForeignLoadGif *gif )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* 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. @previous is the
|
||||
* previous frame, if any.
|
||||
/* Read the next page from the file into @frame.
|
||||
*/
|
||||
static int
|
||||
vips_foreign_load_gif_page( VipsForeignLoadGif *gif,
|
||||
VipsImage *previous, VipsImage *out )
|
||||
vips_foreign_load_gif_next_page( VipsForeignLoadGif *gif )
|
||||
{
|
||||
GifRecordType record;
|
||||
int n_pages;
|
||||
|
||||
n_pages = 0;
|
||||
gboolean have_read_frame;
|
||||
|
||||
have_read_frame = FALSE;
|
||||
do {
|
||||
if( DGifGetRecordType( gif->file, &record ) == GIF_ERROR ) {
|
||||
vips_foreign_load_gif_error( gif );
|
||||
@ -864,13 +846,10 @@ vips_foreign_load_gif_page( VipsForeignLoadGif *gif,
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( vips_foreign_load_gif_render( gif, previous, out ) )
|
||||
if( vips_foreign_load_gif_render( gif ) )
|
||||
return( -1 );
|
||||
|
||||
n_pages += 1;
|
||||
|
||||
VIPS_DEBUG_MSG( "gifload: page %d\n",
|
||||
gif->current_page + n_pages );
|
||||
have_read_frame = TRUE;
|
||||
|
||||
break;
|
||||
|
||||
@ -895,198 +874,40 @@ vips_foreign_load_gif_page( VipsForeignLoadGif *gif,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} while( n_pages < 1 &&
|
||||
} while( !have_read_frame &&
|
||||
!gif->eof );
|
||||
|
||||
gif->current_page += n_pages;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static VipsImage *
|
||||
vips_foreign_load_gif_new_page( VipsForeignLoadGif *gif )
|
||||
{
|
||||
VipsImage *out;
|
||||
|
||||
out = vips_image_new_memory();
|
||||
|
||||
vips_image_init_fields( out,
|
||||
gif->file->SWidth, gif->file->SHeight, 4, VIPS_FORMAT_UCHAR,
|
||||
VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, 1.0, 1.0 );
|
||||
|
||||
/* We will have the whole GIF frame in memory, so we can render any
|
||||
* area.
|
||||
*/
|
||||
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_ANY, NULL );
|
||||
|
||||
/* Turn out into a memory image which we then render the GIF frames
|
||||
* into.
|
||||
*/
|
||||
if( vips_image_write_prepare( out ) ) {
|
||||
g_object_unref( out );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/* Some GIFs may not clear the background, so we must start
|
||||
* transparent.
|
||||
*/
|
||||
memset( VIPS_IMAGE_ADDR( out, 0, 0 ),
|
||||
0,
|
||||
VIPS_IMAGE_SIZEOF_IMAGE( out ) );
|
||||
|
||||
return( out );
|
||||
}
|
||||
|
||||
static void *
|
||||
unref_object( void *data, void *a, void *b )
|
||||
{
|
||||
g_object_unref( G_OBJECT( data ) );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
static void
|
||||
unref_array( GSList *list )
|
||||
{
|
||||
/* g_slist_free_full() was added in 2.28 and we have to work with
|
||||
* 2.6 :(
|
||||
*/
|
||||
vips_slist_map2( list, unref_object, NULL, NULL );
|
||||
g_slist_free( list );
|
||||
}
|
||||
|
||||
/* We render each frame to a separate memory image held in a linked
|
||||
* list, then assemble to out. We don't know the number of frames in advance,
|
||||
* so we can't just allocate a large area.
|
||||
*/
|
||||
static int
|
||||
vips_foreign_load_gif_pages( VipsForeignLoadGif *gif, VipsImage **out )
|
||||
vips_foreign_load_gif_generate( VipsRegion *or,
|
||||
void *seq, void *a, void *b, gboolean *stop )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( gif );
|
||||
VipsRect *r = &or->valid;
|
||||
VipsForeignLoadGif *gif = (VipsForeignLoadGif *) a;
|
||||
|
||||
GSList *frames;
|
||||
VipsImage *frame;
|
||||
VipsImage *previous;
|
||||
VipsImage **t;
|
||||
int n_frames;
|
||||
int i;
|
||||
|
||||
frames = NULL;
|
||||
previous = NULL;
|
||||
|
||||
/* Accumulate any start stuff up to the first frame we need.
|
||||
/* The page for this generate, and the line number in page.
|
||||
*/
|
||||
if( !(frame = vips_foreign_load_gif_new_page( gif )) )
|
||||
return( -1 );
|
||||
do {
|
||||
if( vips_foreign_load_gif_page( gif, NULL, frame ) ) {
|
||||
g_object_unref( frame );
|
||||
int page = r->top / gif->file->SHeight + gif->page;
|
||||
int line = r->top % gif->file->SHeight;
|
||||
|
||||
#ifdef DEBUG_VERBOSE
|
||||
printf( "vips_foreign_load_gif_generate: line %d\n", r->top );
|
||||
#endif /*DEBUG_VERBOSE*/
|
||||
|
||||
g_assert( r->height == 1 );
|
||||
|
||||
while( gif->current_page < page ) {
|
||||
if( vips_foreign_load_gif_next_page( gif ) )
|
||||
return( -1 );
|
||||
}
|
||||
} while( !gif->eof &&
|
||||
gif->current_page <= gif->page );
|
||||
|
||||
if( gif->eof ) {
|
||||
vips_error( class->nickname,
|
||||
"%s", _( "too few frames in GIF file" ) );
|
||||
g_object_unref( frame );
|
||||
return( -1 );
|
||||
gif->current_page += 1;
|
||||
}
|
||||
|
||||
frames = g_slist_append( frames, frame );
|
||||
previous = frame;
|
||||
|
||||
while( gif->n == -1 ||
|
||||
gif->current_page < gif->page + gif->n ) {
|
||||
/* We might need a frame for this read to render to.
|
||||
*/
|
||||
if( !(frame = vips_foreign_load_gif_new_page( gif )) ) {
|
||||
unref_array( frames );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( gif->dispose == DISPOSE_BACKGROUND )
|
||||
/* BACKGROUND means the bg shows through, ie. (in web
|
||||
* 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 ),
|
||||
VIPS_IMAGE_ADDR( previous, 0, 0 ),
|
||||
VIPS_IMAGE_SIZEOF_IMAGE( frame ) );
|
||||
|
||||
if( vips_foreign_load_gif_page( gif, previous, frame ) ) {
|
||||
g_object_unref( frame );
|
||||
unref_array( frames );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( gif->eof ) {
|
||||
/* Nope, didn't need the new frame.
|
||||
*/
|
||||
g_object_unref( frame );
|
||||
break;
|
||||
}
|
||||
else {
|
||||
frames = g_slist_append( frames, frame );
|
||||
|
||||
/* These two dispose modes set new background frames.
|
||||
*/
|
||||
if( gif->dispose == DISPOSAL_UNSPECIFIED ||
|
||||
gif->dispose == DISPOSE_DO_NOT )
|
||||
previous = frame;
|
||||
}
|
||||
}
|
||||
|
||||
n_frames = g_slist_length( frames );
|
||||
|
||||
if( gif->eof &&
|
||||
gif->n != -1 &&
|
||||
n_frames < gif->n ) {
|
||||
unref_array( frames );
|
||||
vips_error( class->nickname,
|
||||
"%s", _( "too few frames in GIF file" ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* We've rendered to a set of memory images ... we can shut down the GIF
|
||||
* reader now.
|
||||
*/
|
||||
vips_foreign_load_gif_close( gif );
|
||||
|
||||
if( !(t = VIPS_ARRAY( gif, n_frames, VipsImage * )) ) {
|
||||
unref_array( frames );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
for( i = 0; i < n_frames; i++ )
|
||||
t[i] = (VipsImage *) g_slist_nth_data( frames, i );
|
||||
|
||||
if( vips_arrayjoin( t, out, n_frames,
|
||||
"across", 1,
|
||||
NULL ) ) {
|
||||
unref_array( frames );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
unref_array( frames );
|
||||
|
||||
if( n_frames > 1 ) {
|
||||
vips_image_set_int( *out, VIPS_META_PAGE_HEIGHT, t[0]->Ysize );
|
||||
|
||||
/* n-pages is supposed to be the number of pages in the file,
|
||||
* but we'd need to scan the entire image to find that :( so
|
||||
* just set it to the number of pages we've read so far.
|
||||
*/
|
||||
vips_image_set_int( *out, VIPS_META_N_PAGES,
|
||||
gif->current_page );
|
||||
}
|
||||
vips_image_set_int( *out, "gif-delay", gif->delay );
|
||||
vips_image_set_int( *out, "gif-loop", gif->loop );
|
||||
if( gif->comment )
|
||||
vips_image_set_string( *out, "gif-comment", gif->comment );
|
||||
memcpy( VIPS_REGION_ADDR( or, 0, r->top ),
|
||||
VIPS_IMAGE_ADDR( gif->frame, 0, line ),
|
||||
VIPS_IMAGE_SIZEOF_LINE( gif->frame ) );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -1100,53 +921,35 @@ vips_foreign_load_gif_load( VipsForeignLoad *load )
|
||||
VipsImage **t = (VipsImage **)
|
||||
vips_object_local_array( VIPS_OBJECT( load ), 4 );
|
||||
|
||||
VipsImage *im;
|
||||
printf( "vips_foreign_load_gif_load:\n" );
|
||||
|
||||
/* Rewind.
|
||||
*/
|
||||
if( class->open( gif ) )
|
||||
return( -1 );
|
||||
|
||||
printf( "vips_foreign_load_gif_load:\n" );
|
||||
|
||||
if( vips_foreign_load_gif_pages( gif, &t[0] ) )
|
||||
return( -1 );
|
||||
im = t[0];
|
||||
|
||||
/* Depending on what we found, transform and write to load->real.
|
||||
/* Make the memory image we accumulate pixels in. We always accumulate
|
||||
* to RGBA, then trim down to whatever the output image needs on
|
||||
* _generate.
|
||||
*/
|
||||
if( gif->has_colour &&
|
||||
gif->has_transparency ) {
|
||||
/* Nothing to do.
|
||||
*/
|
||||
}
|
||||
else if( gif->has_colour ) {
|
||||
/* RGB.
|
||||
*/
|
||||
if( vips_extract_band( im, &t[1], 0,
|
||||
"n", 3,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
im = t[1];
|
||||
}
|
||||
else if( gif->has_transparency ) {
|
||||
/* GA. Take BA so we have neighboring channels.
|
||||
*/
|
||||
if( vips_extract_band( im, &t[1], 2,
|
||||
"n", 2,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
im = t[1];
|
||||
im->Type = VIPS_INTERPRETATION_B_W;
|
||||
}
|
||||
else {
|
||||
/* G.
|
||||
*/
|
||||
if( vips_extract_band( im, &t[1], 0, NULL ) )
|
||||
return( -1 );
|
||||
im = t[1];
|
||||
im->Type = VIPS_INTERPRETATION_B_W;
|
||||
}
|
||||
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 );
|
||||
vips_image_pipelinev( gif->frame, VIPS_DEMAND_STYLE_ANY, NULL );
|
||||
if( vips_image_write_prepare( gif->frame ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_write( im, load->out ) )
|
||||
/* Make the output pipeline.
|
||||
*/
|
||||
t[0] = vips_image_new();
|
||||
if( vips_foreign_load_gif_set_header( gif, t[0] ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_generate( t[0],
|
||||
NULL, vips_foreign_load_gif_generate, NULL, gif, NULL ) ||
|
||||
vips_sequential( t[0], &t[1], NULL ) ||
|
||||
vips_image_write( t[1], load->real ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
@ -1174,13 +977,14 @@ vips_foreign_load_gif_open( VipsForeignLoadGif *gif )
|
||||
#endif
|
||||
|
||||
gif->eof = FALSE;
|
||||
gif->current_page = 0;
|
||||
|
||||
/* Allocate a line buffer now that we have the GIF width.
|
||||
*/
|
||||
if( !gif->line )
|
||||
if( !(gif->line = VIPS_ARRAY( gif,
|
||||
gif->file->SWidth, GifPixelType )) )
|
||||
return( -1 );
|
||||
VIPS_FREE( gif->line )
|
||||
if( !(gif->line = VIPS_ARRAY( gif,
|
||||
gif->file->SWidth, GifPixelType )) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user