move file stuff into subclass, add rewind
This commit is contained in:
parent
a454225ef7
commit
9fe013f72d
@ -93,10 +93,29 @@
|
|||||||
#define DISPOSE_PREVIOUS 3
|
#define DISPOSE_PREVIOUS 3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* TODO:
|
||||||
|
*
|
||||||
|
* - initial very quick scan to discover
|
||||||
|
* - number of pages in file
|
||||||
|
* - has_transparency;
|
||||||
|
* - has_colour;
|
||||||
|
* can we avoid decompression of every pixel?
|
||||||
|
*
|
||||||
|
* - 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.
|
||||||
|
*/
|
||||||
|
|
||||||
typedef struct _VipsForeignLoadGif {
|
typedef struct _VipsForeignLoadGif {
|
||||||
VipsForeignLoad parent_object;
|
VipsForeignLoad parent_object;
|
||||||
|
|
||||||
/* Load this page (frame number).
|
/* Load from this page (frame number).
|
||||||
*/
|
*/
|
||||||
int page;
|
int page;
|
||||||
|
|
||||||
@ -150,13 +169,16 @@ typedef struct _VipsForeignLoadGif {
|
|||||||
*/
|
*/
|
||||||
int dispose;
|
int dispose;
|
||||||
|
|
||||||
/* The FILE* we read from.
|
|
||||||
*/
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
} VipsForeignLoadGif;
|
} VipsForeignLoadGif;
|
||||||
|
|
||||||
typedef VipsForeignLoadClass VipsForeignLoadGifClass;
|
typedef struct _VipsForeignLoadGifClass {
|
||||||
|
VipsForeignLoadClass parent_class;
|
||||||
|
|
||||||
|
/* Reset the read position. Subclasses must implement this. Close goes
|
||||||
|
* into _dispose, open is not virtual.
|
||||||
|
*/
|
||||||
|
int (*rewind)( VipsForeignLoadGif *gif );
|
||||||
|
} VipsForeignLoadGifClass;
|
||||||
|
|
||||||
G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadGif, vips_foreign_load_gif,
|
G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadGif, vips_foreign_load_gif,
|
||||||
VIPS_TYPE_FOREIGN_LOAD );
|
VIPS_TYPE_FOREIGN_LOAD );
|
||||||
@ -268,74 +290,6 @@ vips_foreign_load_gif_close( VipsForeignLoadGif *gif )
|
|||||||
gif->file = NULL;
|
gif->file = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
VIPS_FREEF( fclose, gif->fp );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Our input function for file open. We can't use DGifOpenFileName(), since
|
|
||||||
* that just calls open() and won't work with unicode on win32. We can't use
|
|
||||||
* DGifOpenFileHandle() since that's an fd from open() and you can't pass those
|
|
||||||
* acoss DLL boundaries on Windows.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
vips_giflib_file_read( GifFileType *file, GifByteType *buffer, int n )
|
|
||||||
{
|
|
||||||
FILE *fp = (FILE *) file->UserData;
|
|
||||||
|
|
||||||
return( (int) fread( (void *) buffer, 1, n, fp ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
vips_foreign_load_gif_open( VipsForeignLoadGif *gif, const char *filename )
|
|
||||||
{
|
|
||||||
g_assert( !gif->file );
|
|
||||||
g_assert( !gif->fp );
|
|
||||||
|
|
||||||
if( !(gif->fp = vips__file_open_read( filename, NULL, FALSE )) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
#ifdef HAVE_GIFLIB_5
|
|
||||||
{
|
|
||||||
int error;
|
|
||||||
|
|
||||||
if( !(gif->file =
|
|
||||||
DGifOpen( gif->fp, vips_giflib_file_read, &error )) ) {
|
|
||||||
vips_foreign_load_gif_error_vips( gif, error );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if( !(gif->file = DGifOpen( gif->fp, vips_giflib_file_read )) ) {
|
|
||||||
vips_foreign_load_gif_error_vips( gif, GifLastError() );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
vips_foreign_load_gif_open_buffer( VipsForeignLoadGif *gif, InputFunc read_fn )
|
|
||||||
{
|
|
||||||
g_assert( !gif->file );
|
|
||||||
|
|
||||||
#ifdef HAVE_GIFLIB_5
|
|
||||||
{
|
|
||||||
int error;
|
|
||||||
|
|
||||||
if( !(gif->file = DGifOpen( gif, read_fn, &error )) ) {
|
|
||||||
vips_foreign_load_gif_error_vips( gif, error );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if( !(gif->file = DGifOpen( gif, read_fn )) ) {
|
|
||||||
vips_foreign_load_gif_error_vips( gif, GifLastError() );
|
|
||||||
return( -1 );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -946,6 +900,26 @@ vips_foreign_load_gif_pages( VipsForeignLoadGif *gif, VipsImage **out )
|
|||||||
return( 0 );
|
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_header( VipsForeignLoad *load )
|
||||||
|
{
|
||||||
|
VipsForeignLoadGifClass *class =
|
||||||
|
(VipsForeignLoadGifClass *) VIPS_OBJECT_GET_CLASS( load );
|
||||||
|
VipsForeignLoadGif *gif = (VipsForeignLoadGif *) load;
|
||||||
|
|
||||||
|
printf( "vips_foreign_load_gif_header:\n" );
|
||||||
|
|
||||||
|
if( class->rewind( gif ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_foreign_load_gif_load( VipsForeignLoad *load )
|
vips_foreign_load_gif_load( VipsForeignLoad *load )
|
||||||
{
|
{
|
||||||
@ -955,6 +929,9 @@ vips_foreign_load_gif_load( VipsForeignLoad *load )
|
|||||||
|
|
||||||
VipsImage *im;
|
VipsImage *im;
|
||||||
|
|
||||||
|
if( vips_foreign_load_gif_header( load ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
if( vips_foreign_load_gif_pages( gif, &t[0] ) )
|
if( vips_foreign_load_gif_pages( gif, &t[0] ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
im = t[0];
|
im = t[0];
|
||||||
@ -1052,6 +1029,10 @@ typedef struct _VipsForeignLoadGifFile {
|
|||||||
*/
|
*/
|
||||||
char *filename;
|
char *filename;
|
||||||
|
|
||||||
|
/* The FILE* we read from.
|
||||||
|
*/
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
} VipsForeignLoadGifFile;
|
} VipsForeignLoadGifFile;
|
||||||
|
|
||||||
typedef VipsForeignLoadGifClass VipsForeignLoadGifFileClass;
|
typedef VipsForeignLoadGifClass VipsForeignLoadGifFileClass;
|
||||||
@ -1059,20 +1040,70 @@ typedef VipsForeignLoadGifClass VipsForeignLoadGifFileClass;
|
|||||||
G_DEFINE_TYPE( VipsForeignLoadGifFile, vips_foreign_load_gif_file,
|
G_DEFINE_TYPE( VipsForeignLoadGifFile, vips_foreign_load_gif_file,
|
||||||
vips_foreign_load_gif_get_type() );
|
vips_foreign_load_gif_get_type() );
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_load_gif_file_dispose( GObject *gobject )
|
||||||
|
{
|
||||||
|
VipsForeignLoadGifFile *file = (VipsForeignLoadGifFile *) gobject;
|
||||||
|
|
||||||
|
VIPS_FREEF( fclose, file->fp );
|
||||||
|
|
||||||
|
G_OBJECT_CLASS( vips_foreign_load_gif_file_parent_class )->
|
||||||
|
dispose( gobject );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Our input function for file open. We can't use DGifOpenFileName(), since
|
||||||
|
* that just calls open() and won't work with unicode on win32. We can't use
|
||||||
|
* DGifOpenFileHandle() since that's an fd from open() and you can't pass those
|
||||||
|
* across DLL boundaries on Windows.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
vips_giflib_file_read( GifFileType *file, GifByteType *buffer, int n )
|
||||||
|
{
|
||||||
|
FILE *fp = (FILE *) file->UserData;
|
||||||
|
|
||||||
|
return( (int) fread( (void *) buffer, 1, n, fp ) );
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_foreign_load_gif_file_header( VipsForeignLoad *load )
|
vips_foreign_load_gif_file_header( VipsForeignLoad *load )
|
||||||
{
|
{
|
||||||
VipsForeignLoadGif *gif = (VipsForeignLoadGif *) load;
|
VipsForeignLoadGif *gif = (VipsForeignLoadGif *) load;
|
||||||
VipsForeignLoadGifFile *file = (VipsForeignLoadGifFile *) load;
|
VipsForeignLoadGifFile *file = (VipsForeignLoadGifFile *) load;
|
||||||
|
|
||||||
if( vips_foreign_load_gif_open( gif, file->filename ) )
|
g_assert( !gif->file );
|
||||||
|
g_assert( !file->fp );
|
||||||
|
|
||||||
|
if( !(file->fp = vips__file_open_read( file->filename, NULL, FALSE )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
|
#ifdef HAVE_GIFLIB_5
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if( !(gif->file =
|
||||||
|
DGifOpen( file->fp, vips_giflib_file_read, &error )) ) {
|
||||||
|
vips_foreign_load_gif_error_vips( gif, error );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if( !(gif->file = DGifOpen( file->fp, vips_giflib_file_read )) ) {
|
||||||
|
vips_foreign_load_gif_error_vips( gif, GifLastError() );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
VIPS_SETSTR( load->out->filename, file->filename );
|
VIPS_SETSTR( load->out->filename, file->filename );
|
||||||
|
|
||||||
return( vips_foreign_load_gif_load( load ) );
|
return( vips_foreign_load_gif_load( load ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_load_gif_file_rewind( VipsForeignLoadGif *gif )
|
||||||
|
{
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
static const char *vips_foreign_gif_suffs[] = {
|
static const char *vips_foreign_gif_suffs[] = {
|
||||||
".gif",
|
".gif",
|
||||||
NULL
|
NULL
|
||||||
@ -1086,7 +1117,9 @@ vips_foreign_load_gif_file_class_init(
|
|||||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||||
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
|
||||||
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
|
||||||
|
VipsForeignLoadGifClass *gif_class = (VipsForeignLoadGifClass *) class;
|
||||||
|
|
||||||
|
gobject_class->dispose = vips_foreign_load_gif_file_dispose;
|
||||||
gobject_class->set_property = vips_object_set_property;
|
gobject_class->set_property = vips_object_set_property;
|
||||||
gobject_class->get_property = vips_object_get_property;
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
@ -1098,6 +1131,8 @@ vips_foreign_load_gif_file_class_init(
|
|||||||
load_class->is_a = vips_foreign_load_gif_is_a;
|
load_class->is_a = vips_foreign_load_gif_is_a;
|
||||||
load_class->header = vips_foreign_load_gif_file_header;
|
load_class->header = vips_foreign_load_gif_file_header;
|
||||||
|
|
||||||
|
gif_class->rewind = vips_foreign_load_gif_file_rewind;
|
||||||
|
|
||||||
VIPS_ARG_STRING( class, "filename", 1,
|
VIPS_ARG_STRING( class, "filename", 1,
|
||||||
_( "Filename" ),
|
_( "Filename" ),
|
||||||
_( "Filename to load from" ),
|
_( "Filename to load from" ),
|
||||||
@ -1155,13 +1190,28 @@ vips_foreign_load_gif_buffer_header( VipsForeignLoad *load )
|
|||||||
VipsForeignLoadGif *gif = (VipsForeignLoadGif *) load;
|
VipsForeignLoadGif *gif = (VipsForeignLoadGif *) load;
|
||||||
VipsForeignLoadGifBuffer *buffer = (VipsForeignLoadGifBuffer *) load;
|
VipsForeignLoadGifBuffer *buffer = (VipsForeignLoadGifBuffer *) load;
|
||||||
|
|
||||||
|
g_assert( !gif->file );
|
||||||
|
|
||||||
/* Init the read point.
|
/* Init the read point.
|
||||||
*/
|
*/
|
||||||
buffer->p = buffer->buf->data;
|
buffer->p = buffer->buf->data;
|
||||||
buffer->bytes_to_go = buffer->buf->length;
|
buffer->bytes_to_go = buffer->buf->length;
|
||||||
|
|
||||||
if( vips_foreign_load_gif_open_buffer( gif, vips_giflib_buffer_read ) )
|
#ifdef HAVE_GIFLIB_5
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if( !(gif->file = DGifOpen( gif, vips_giflib_buffer_read, &error )) ) {
|
||||||
|
vips_foreign_load_gif_error_vips( gif, error );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if( !(gif->file = DGifOpen( gif, vips_giflib_buffer_read )) ) {
|
||||||
|
vips_foreign_load_gif_error_vips( gif, GifLastError() );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return( vips_foreign_load_gif_load( load ) );
|
return( vips_foreign_load_gif_load( load ) );
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user