revise webpload for improved loader pattern

This commit is contained in:
John Cupitt 2019-12-24 13:49:53 +00:00
parent 5e35827a41
commit f2f2ab200d

View File

@ -58,6 +58,10 @@
typedef struct _VipsForeignLoadWebp { typedef struct _VipsForeignLoadWebp {
VipsForeignLoad parent_object; VipsForeignLoad parent_object;
/* Set by subclasses.
*/
VipsStreami *streami;
/* Load this page (frame number). /* Load this page (frame number).
*/ */
int page; int page;
@ -80,17 +84,67 @@ typedef VipsForeignLoadClass VipsForeignLoadWebpClass;
G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadWebp, vips_foreign_load_webp, G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadWebp, vips_foreign_load_webp,
VIPS_TYPE_FOREIGN_LOAD ); VIPS_TYPE_FOREIGN_LOAD );
static void
vips_foreign_load_webp_dispose( GObject *gobject )
{
VipsForeignLoadWebp *webp = (VipsForeignLoadWebp *) gobject;
VIPS_UNREF( webp->streami );
G_OBJECT_CLASS( vips_foreign_load_webp_parent_class )->
dispose( gobject );
}
static int
vips_foreign_load_webp_build( VipsObject *object )
{
VipsForeignLoadWebp *webp = (VipsForeignLoadWebp *) object;
/* BC for the old API.
*/
if( !vips_object_argument_isset( VIPS_OBJECT( webp ), "scale" ) &&
vips_object_argument_isset( VIPS_OBJECT( webp ), "shrink" ) &&
webp->shrink != 0 )
webp->scale = 1.0 / webp->shrink;
if( VIPS_OBJECT_CLASS( vips_foreign_load_webp_parent_class )->
build( object ) )
return( -1 );
return( 0 );
}
static VipsForeignFlags static VipsForeignFlags
vips_foreign_load_webp_get_flags( VipsForeignLoad *load ) vips_foreign_load_webp_get_flags( VipsForeignLoad *load )
{ {
return( 0 ); return( 0 );
} }
static int static VipsForeignFlags
vips_foreign_load_webp_build( VipsObject *object ) vips_foreign_load_webp_get_flags_filename( const char *filename )
{ {
if( VIPS_OBJECT_CLASS( vips_foreign_load_webp_parent_class )-> return( 0 );
build( object ) ) }
static int
vips_foreign_load_webp_header( VipsForeignLoad *load )
{
VipsForeignLoadWebp *webp = (VipsForeignLoadWebp *) load;
if( vips__webp_read_header_stream( webp->streami, load->out,
webp->page, webp->n, webp->scale ) )
return( -1 );
return( 0 );
}
static int
vips_foreign_load_webp_load( VipsForeignLoad *load )
{
VipsForeignLoadWebp *webp = (VipsForeignLoadWebp *) load;
if( vips__webp_read_stream( webp->streami, load->real,
webp->page, webp->n, webp->scale ) )
return( -1 ); return( -1 );
return( 0 ); return( 0 );
@ -101,8 +155,10 @@ vips_foreign_load_webp_class_init( VipsForeignLoadWebpClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class; VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class; VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->dispose = vips_foreign_load_webp_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;
@ -110,7 +166,15 @@ vips_foreign_load_webp_class_init( VipsForeignLoadWebpClass *class )
object_class->description = _( "load webp" ); object_class->description = _( "load webp" );
object_class->build = vips_foreign_load_webp_build; object_class->build = vips_foreign_load_webp_build;
/* is_a() is not that quick ... lower the priority.
*/
foreign_class->priority = -50;
load_class->get_flags_filename =
vips_foreign_load_webp_get_flags_filename;
load_class->get_flags = vips_foreign_load_webp_get_flags; load_class->get_flags = vips_foreign_load_webp_get_flags;
load_class->header = vips_foreign_load_webp_header;
load_class->load = vips_foreign_load_webp_load;
VIPS_ARG_INT( class, "page", 20, VIPS_ARG_INT( class, "page", 20,
_( "Page" ), _( "Page" ),
@ -166,26 +230,19 @@ G_DEFINE_TYPE( VipsForeignLoadWebpStream, vips_foreign_load_webp_stream,
vips_foreign_load_webp_get_type() ); vips_foreign_load_webp_get_type() );
static int static int
vips_foreign_load_webp_stream_header( VipsForeignLoad *load ) vips_foreign_load_webp_stream_build( VipsObject *object )
{ {
VipsForeignLoadWebp *webp = (VipsForeignLoadWebp *) load; VipsForeignLoadWebp *webp = (VipsForeignLoadWebp *) object;
VipsForeignLoadWebpStream *stream = (VipsForeignLoadWebpStream *) load; VipsForeignLoadWebpStream *stream =
(VipsForeignLoadWebpStream *) object;
if( vips__webp_read_header_stream( stream->streami, load->out, if( stream->streami ) {
webp->page, webp->n, webp->scale ) ) webp->streami = stream->streami;
return( -1 ); g_object_ref( webp->streami );
}
return( 0 ); if( VIPS_OBJECT_CLASS( vips_foreign_load_webp_stream_parent_class )->
} build( object ) )
static int
vips_foreign_load_webp_stream_load( VipsForeignLoad *load )
{
VipsForeignLoadWebp *webp = (VipsForeignLoadWebp *) load;
VipsForeignLoadWebpStream *stream = (VipsForeignLoadWebpStream *) load;
if( vips__webp_read_stream( stream->streami, load->real,
webp->page, webp->n, webp->scale ) )
return( -1 ); return( -1 );
return( 0 ); return( 0 );
@ -197,7 +254,6 @@ vips_foreign_load_webp_stream_class_init(
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class; VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class; VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->set_property = vips_object_set_property; gobject_class->set_property = vips_object_set_property;
@ -205,14 +261,9 @@ vips_foreign_load_webp_stream_class_init(
object_class->nickname = "webpload_stream"; object_class->nickname = "webpload_stream";
object_class->description = _( "load webp from stream" ); object_class->description = _( "load webp from stream" );
object_class->build = vips_foreign_load_webp_stream_build;
/* is_a() is not that quick ... lower the priority.
*/
foreign_class->priority = -50;
load_class->is_a_stream = vips__iswebp_stream; load_class->is_a_stream = vips__iswebp_stream;
load_class->header = vips_foreign_load_webp_stream_header;
load_class->load = vips_foreign_load_webp_stream_load;
VIPS_ARG_OBJECT( class, "streami", 1, VIPS_ARG_OBJECT( class, "streami", 1,
_( "Streami" ), _( "Streami" ),
@ -242,9 +293,21 @@ typedef VipsForeignLoadWebpClass VipsForeignLoadWebpFileClass;
G_DEFINE_TYPE( VipsForeignLoadWebpFile, vips_foreign_load_webp_file, G_DEFINE_TYPE( VipsForeignLoadWebpFile, vips_foreign_load_webp_file,
vips_foreign_load_webp_get_type() ); vips_foreign_load_webp_get_type() );
static VipsForeignFlags static int
vips_foreign_load_webp_file_get_flags_filename( const char *filename ) vips_foreign_load_webp_file_build( VipsObject *object )
{ {
VipsForeignLoadWebp *webp = (VipsForeignLoadWebp *) object;
VipsForeignLoadWebpFile *file = (VipsForeignLoadWebpFile *) object;
if( file->filename &&
!(webp->streami =
vips_streami_new_from_file( file->filename )) )
return( -1 );
if( VIPS_OBJECT_CLASS( vips_foreign_load_webp_file_parent_class )->
build( object ) )
return( -1 );
return( 0 ); return( 0 );
} }
@ -262,53 +325,6 @@ vips_foreign_load_webp_file_is_a( const char *filename )
return( result ); return( result );
} }
static int
vips_foreign_load_webp_file_header( VipsForeignLoad *load )
{
VipsForeignLoadWebp *webp = (VipsForeignLoadWebp *) load;
VipsForeignLoadWebpFile *file = (VipsForeignLoadWebpFile *) load;
VipsStreami *streami;
/* BC for the old API.
*/
if( !vips_object_argument_isset( VIPS_OBJECT( load ), "scale" ) &&
vips_object_argument_isset( VIPS_OBJECT( load ), "shrink" ) &&
webp->shrink != 0 )
webp->scale = 1.0 / webp->shrink;
if( !(streami = vips_streami_new_from_file( file->filename )) )
return( -1 );
if( vips__webp_read_header_stream( streami, load->out,
webp->page, webp->n, webp->scale ) ) {
VIPS_UNREF( streami );
return( -1 );
}
VIPS_UNREF( streami );
return( 0 );
}
static int
vips_foreign_load_webp_file_load( VipsForeignLoad *load )
{
VipsForeignLoadWebp *webp = (VipsForeignLoadWebp *) load;
VipsForeignLoadWebpFile *file = (VipsForeignLoadWebpFile *) load;
VipsStreami *streami;
if( !(streami = vips_streami_new_from_file( file->filename )) )
return( -1 );
if( vips__webp_read_stream( streami, load->real,
webp->page, webp->n, webp->scale ) ) {
VIPS_UNREF( streami );
return( -1 );
}
VIPS_UNREF( streami );
return( 0 );
}
const char *vips__webp_suffs[] = { ".webp", NULL }; const char *vips__webp_suffs[] = { ".webp", NULL };
static void static void
@ -324,14 +340,11 @@ vips_foreign_load_webp_file_class_init( VipsForeignLoadWebpFileClass *class )
object_class->nickname = "webpload"; object_class->nickname = "webpload";
object_class->description = _( "load webp from file" ); object_class->description = _( "load webp from file" );
object_class->build = vips_foreign_load_webp_file_build;
foreign_class->suffs = vips__webp_suffs; foreign_class->suffs = vips__webp_suffs;
load_class->get_flags_filename =
vips_foreign_load_webp_file_get_flags_filename;
load_class->is_a = vips_foreign_load_webp_file_is_a; load_class->is_a = vips_foreign_load_webp_file_is_a;
load_class->header = vips_foreign_load_webp_file_header;
load_class->load = vips_foreign_load_webp_file_load;
VIPS_ARG_STRING( class, "filename", 1, VIPS_ARG_STRING( class, "filename", 1,
_( "Filename" ), _( "Filename" ),
@ -351,7 +364,7 @@ typedef struct _VipsForeignLoadWebpBuffer {
/* Load from a buffer. /* Load from a buffer.
*/ */
VipsArea *buf; VipsBlob *blob;
} VipsForeignLoadWebpBuffer; } VipsForeignLoadWebpBuffer;
@ -360,6 +373,26 @@ typedef VipsForeignLoadWebpClass VipsForeignLoadWebpBufferClass;
G_DEFINE_TYPE( VipsForeignLoadWebpBuffer, vips_foreign_load_webp_buffer, G_DEFINE_TYPE( VipsForeignLoadWebpBuffer, vips_foreign_load_webp_buffer,
vips_foreign_load_webp_get_type() ); vips_foreign_load_webp_get_type() );
static int
vips_foreign_load_webp_buffer_build( VipsObject *object )
{
VipsForeignLoadWebp *webp = (VipsForeignLoadWebp *) object;
VipsForeignLoadWebpBuffer *buffer =
(VipsForeignLoadWebpBuffer *) object;
if( buffer->blob &&
!(webp->streami = vips_streami_new_from_memory(
VIPS_AREA( buffer->blob )->data,
VIPS_AREA( buffer->blob )->length )) )
return( -1 );
if( VIPS_OBJECT_CLASS( vips_foreign_load_webp_buffer_parent_class )->
build( object ) )
return( -1 );
return( 0 );
}
static gboolean static gboolean
vips_foreign_load_webp_buffer_is_a_buffer( const void *buf, size_t len ) vips_foreign_load_webp_buffer_is_a_buffer( const void *buf, size_t len )
{ {
@ -374,55 +407,12 @@ vips_foreign_load_webp_buffer_is_a_buffer( const void *buf, size_t len )
return( result ); return( result );
} }
static int
vips_foreign_load_webp_buffer_header( VipsForeignLoad *load )
{
VipsForeignLoadWebp *webp = (VipsForeignLoadWebp *) load;
VipsForeignLoadWebpBuffer *buffer = (VipsForeignLoadWebpBuffer *) load;
VipsStreami *streami;
if( !(streami = vips_streami_new_from_memory( buffer->buf->data,
buffer->buf->length )) )
return( FALSE );
if( vips__webp_read_header_stream( streami, load->out,
webp->page, webp->n, webp->scale ) ) {
VIPS_UNREF( streami );
return( -1 );
}
VIPS_UNREF( streami );
return( 0 );
}
static int
vips_foreign_load_webp_buffer_load( VipsForeignLoad *load )
{
VipsForeignLoadWebp *webp = (VipsForeignLoadWebp *) load;
VipsForeignLoadWebpBuffer *buffer = (VipsForeignLoadWebpBuffer *) load;
VipsStreami *streami;
if( !(streami = vips_streami_new_from_memory( buffer->buf->data,
buffer->buf->length )) )
return( FALSE );
if( vips__webp_read_stream( streami, load->real,
webp->page, webp->n, webp->scale ) ) {
VIPS_UNREF( streami );
return( -1 );
}
VIPS_UNREF( streami );
return( 0 );
}
static void static void
vips_foreign_load_webp_buffer_class_init( vips_foreign_load_webp_buffer_class_init(
VipsForeignLoadWebpBufferClass *class ) VipsForeignLoadWebpBufferClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class; VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class; VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
gobject_class->set_property = vips_object_set_property; gobject_class->set_property = vips_object_set_property;
@ -430,20 +420,15 @@ vips_foreign_load_webp_buffer_class_init(
object_class->nickname = "webpload_buffer"; object_class->nickname = "webpload_buffer";
object_class->description = _( "load webp from buffer" ); object_class->description = _( "load webp from buffer" );
object_class->build = vips_foreign_load_webp_buffer_build;
/* is_a() is not that quick ... lower the priority.
*/
foreign_class->priority = -50;
load_class->is_a_buffer = vips_foreign_load_webp_buffer_is_a_buffer; load_class->is_a_buffer = vips_foreign_load_webp_buffer_is_a_buffer;
load_class->header = vips_foreign_load_webp_buffer_header;
load_class->load = vips_foreign_load_webp_buffer_load;
VIPS_ARG_BOXED( class, "buffer", 1, VIPS_ARG_BOXED( class, "buffer", 1,
_( "Buffer" ), _( "Buffer" ),
_( "Buffer to load from" ), _( "Buffer to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT, VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignLoadWebpBuffer, buf ), G_STRUCT_OFFSET( VipsForeignLoadWebpBuffer, blob ),
VIPS_TYPE_BLOB ); VIPS_TYPE_BLOB );
} }