From b9db7249f45c7bf3de851e13f927d6dc155c4986 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sun, 27 Nov 2011 21:31:21 +0000 Subject: [PATCH] new-style CLI save working --- TODO | 12 +-- libvips/deprecated/dispatch_types.c | 4 + libvips/file/file.c | 145 +++++++++++++++++----------- libvips/file/vipsload.c | 32 ++---- libvips/include/vips/file.h | 6 +- libvips/iofuncs/generate.c | 2 +- libvips/iofuncs/image.c | 2 +- libvips/iofuncs/object.c | 50 +++++++--- 8 files changed, 150 insertions(+), 103 deletions(-) diff --git a/TODO b/TODO index 4e54a57c..602e9d0c 100644 --- a/TODO +++ b/TODO @@ -1,12 +1,6 @@ -- test ref counting in vips_object_set_argument_from_string() VipsFile stuff +- make compat wrappers for old im_jpeg2vips() and im_vips2jpeg() - add path for output images, see vips_object_get_argument_to_string() - - - - - - make compat wrappers for old im_jpeg2vips() and im_vips2jpeg() + make sure we are using the operation cache for jpegload move format/* to deprecated @@ -15,7 +9,7 @@ -- return missing just after read_xmp() in master? + diff --git a/libvips/deprecated/dispatch_types.c b/libvips/deprecated/dispatch_types.c index 1178d9d3..53f7a23f 100644 --- a/libvips/deprecated/dispatch_types.c +++ b/libvips/deprecated/dispatch_types.c @@ -876,6 +876,10 @@ input_interpolate_init( im_object *obj, char *str ) interpolate_class = vips_class_find( "VipsInterpolate", "interpolate" ); if( !(object = vips_object_new_from_string( interpolate_class, str )) ) return( -1 ); + if( vips_object_build( object ) ) { + g_object_unref( object ); + return( -1 ); + } *obj = object; return( 0 ); diff --git a/libvips/file/file.c b/libvips/file/file.c index 610c9d4b..ada5fb45 100644 --- a/libvips/file/file.c +++ b/libvips/file/file.c @@ -547,24 +547,34 @@ vips_file_load_build( VipsObject *object ) build( object ) ) return( -1 ); - /* Read header fields to init the return image. THINSTRIP since this is - * probably a disc file. We can't tell yet whether we will be opening - * to memory, sadly, so we can't suggest ANY. + /* Read the header into @out. */ if( class->header && class->header( load ) ) return( -1 ); - vips_demand_hint( load->out, VIPS_DEMAND_STYLE_THINSTRIP, NULL ); - /* Then 'start' creates the real image and 'gen' fetches pixels for - * 'out' from real on demand. + /* If there's no ->load() method then the header read has done + * everything. Otherwise, it's just set fields and we now must + * convert pixels on demand. */ - if( vips_image_generate( load->out, - vips_file_load_start_cb, - vips_file_load_generate_cb, - vips_stop_one, - load, NULL ) ) - return( -1 ); + if( class->load ) { + /* THINSTRIP since this is probably a disc file. + * We can't tell yet whether we will be opening + * to memory, sadly, so we can't suggest ANY. + */ + vips_demand_hint( load->out, + VIPS_DEMAND_STYLE_THINSTRIP, NULL ); + + /* Then 'start' creates the real image and 'gen' fetches + * pixels for @out from @real on demand. + */ + if( vips_image_generate( load->out, + vips_file_load_start_cb, + vips_file_load_generate_cb, + vips_stop_one, + load, NULL ) ) + return( -1 ); + } return( 0 ); } @@ -640,6 +650,69 @@ vips_file_save_print_class( VipsObjectClass *object_class, VipsBuf *buf ) VIPS_ENUM_NICK( VIPS_TYPE_SAVEABLE, class->saveable ) ); } +/* Can we write this filename with this file? + */ +static void * +vips_file_save_new_from_filename_sub( VipsFileSaveClass *save_class, + const char *filename ) +{ + VipsFileClass *class = VIPS_FILE_CLASS( save_class ); + + if( vips_filename_suffix_match( filename, class->suffs ) ) + return( save_class ); + + return( NULL ); +} + +/** + * vips_file_find_save: + * @filename: name to find a file for + * + * Searches for an operation you could use to save a file. + * + * See also: vips_file_write(). + * + * Returns: the name of an operation on success, %NULL on error + */ +const char * +vips_file_find_save( const char *filename ) +{ + VipsFileSaveClass *save_class; + + if( !(save_class = (VipsFileSaveClass *) vips_file_map( + "VipsFileSave", + (VipsSListMap2Fn) vips_file_save_new_from_filename_sub, + (void *) filename, NULL )) ) { + vips_error( "VipsFileSave", + _( "\"%s\" is not a supported image file." ), + filename ); + + return( NULL ); + } + + return( G_OBJECT_CLASS_NAME( save_class ) ); +} + +static VipsObject * +vips_file_save_new_from_string( const char *string ) +{ + const char *file_op; + GType type; + VipsFileSave *save; + + if( !(file_op = vips_file_find_save( string )) ) + return( NULL ); + type = g_type_from_name( file_op ); + g_assert( type ); + + save = VIPS_FILE_SAVE( g_object_new( type, NULL ) ); + g_object_set( save, + "filename", string, + NULL ); + + return( VIPS_OBJECT( save ) ); +} + /* Generate the saveable image. */ static int @@ -864,10 +937,11 @@ vips_file_save_class_init( VipsFileSaveClass *class ) gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; + object_class->build = vips_file_save_build; + object_class->print_class = vips_file_save_print_class; + object_class->new_from_string = vips_file_save_new_from_string; object_class->nickname = "filesave"; object_class->description = _( "file savers" ); - object_class->print_class = vips_file_save_print_class; - object_class->build = vips_file_save_build; VIPS_ARG_IMAGE( class, "in", 0, _( "Input" ), @@ -881,49 +955,6 @@ vips_file_save_init( VipsFileSave *object ) { } -/* Can we write this filename with this file? - */ -static void * -vips_file_save_new_from_filename_sub( VipsFileSaveClass *save_class, - const char *filename ) -{ - VipsFileClass *class = VIPS_FILE_CLASS( save_class ); - - if( vips_filename_suffix_match( filename, class->suffs ) ) - return( save_class ); - - return( NULL ); -} - -/** - * vips_file_find_save: - * @filename: name to find a file for - * - * Searches for an operation you could use to save a file. - * - * See also: vips_file_write(). - * - * Returns: the name of an operation on success, %NULL on error - */ -const char * -vips_file_find_save( const char *filename ) -{ - VipsFileSaveClass *save_class; - - if( !(save_class = (VipsFileSaveClass *) vips_file_map( - "VipsFileSave", - (VipsSListMap2Fn) vips_file_save_new_from_filename_sub, - (void *) filename, NULL )) ) { - vips_error( "VipsFileSave", - _( "\"%s\" is not a supported image file." ), - filename ); - - return( NULL ); - } - - return( G_OBJECT_CLASS_NAME( save_class ) ); -} - /** * vips_file_read: * @filename: file to load diff --git a/libvips/file/vipsload.c b/libvips/file/vipsload.c index 298a9094..65b3b0a5 100644 --- a/libvips/file/vipsload.c +++ b/libvips/file/vipsload.c @@ -49,16 +49,6 @@ typedef VipsFileLoadClass VipsFileLoadVipsClass; G_DEFINE_TYPE( VipsFileLoadVips, vips_file_load_vips, VIPS_TYPE_FILE_LOAD ); -static int -vips_file_load_vips_build( VipsObject *object ) -{ - if( VIPS_OBJECT_CLASS( vips_file_load_vips_parent_class )-> - build( object ) ) - return( -1 ); - - return( 0 ); -} - static gboolean vips_file_load_vips_is_a( const char *filename ) { @@ -86,20 +76,19 @@ static int vips_file_load_vips_header( VipsFileLoad *load ) { VipsFile *file = VIPS_FILE( load ); + VipsImage *out; + VipsImage *out2; - if( !(load->out = vips_image_new_from_file( file->filename )) ) + if( !(out2 = vips_image_new_from_file( file->filename )) ) return( -1 ); - return( 0 ); -} + /* Unref the @out that's there now. + */ + g_object_get( load, "out", &out, NULL ); + g_object_unref( out ); + g_object_unref( out ); -static int -vips_file_load_vips_load( VipsFileLoad *load ) -{ - VipsFile *file = VIPS_FILE( load ); - - if( !(load->real = vips_image_new_from_file( file->filename )) ) - return( -1 ); + g_object_set( load, "out", out2, NULL ); return( 0 ); } @@ -115,14 +104,13 @@ vips_file_load_vips_class_init( VipsFileLoadVipsClass *class ) object_class->nickname = "vipsload"; object_class->description = _( "load vips from file" ); - object_class->build = vips_file_load_vips_build; file_class->suffs = vips_suffs; load_class->is_a = vips_file_load_vips_is_a; load_class->get_flags = vips_file_load_vips_get_flags; load_class->header = vips_file_load_vips_header; - load_class->load = vips_file_load_vips_load; + load_class->load = NULL; } static void diff --git a/libvips/include/vips/file.h b/libvips/include/vips/file.h index c382bd48..3f6e962b 100644 --- a/libvips/include/vips/file.h +++ b/libvips/include/vips/file.h @@ -145,11 +145,13 @@ typedef struct _VipsFileLoadClass { */ int (*get_flags)( VipsFileLoad * ); - /* Read the header into @out. + /* Set the header fields in @out from @filename. If you can read the + * whole image as well with no performance cost (as with vipsload), + * leave ->load() NULL. */ int (*header)( VipsFileLoad * ); - /* Read the whole image into real. It gets copied to out later. + /* Read the whole image into @real. It gets copied to @out later. */ int (*load)( VipsFileLoad * ); diff --git a/libvips/iofuncs/generate.c b/libvips/iofuncs/generate.c index 08568665..a5ee7210 100644 --- a/libvips/iofuncs/generate.c +++ b/libvips/iofuncs/generate.c @@ -682,7 +682,7 @@ vips_image_generate( VipsImage *image, */ vips_error( "VipsImage", _( "unable to output to a %s image" ), - VIPS_ENUM_NICK( VIPS_TYPE_DEMAND_STYLE, + VIPS_ENUM_NICK( VIPS_TYPE_IMAGE_TYPE, image->dtype ) ); return( -1 ); } diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index 7cfdaec6..d24d979d 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -1796,7 +1796,7 @@ vips_image_write_line( VipsImage *image, int ypos, PEL *linebuffer ) default: vips_error( "VipsImage", _( "unable to output to a %s image" ), - VIPS_ENUM_STRING( VIPS_TYPE_DEMAND_STYLE, + VIPS_ENUM_STRING( VIPS_TYPE_IMAGE_TYPE, image->dtype ) ); return( -1 ); } diff --git a/libvips/iofuncs/object.c b/libvips/iofuncs/object.c index a9d62e54..fcfe2a91 100644 --- a/libvips/iofuncs/object.c +++ b/libvips/iofuncs/object.c @@ -1236,28 +1236,33 @@ vips_object_set_argument_from_string( VipsObject *object, VipsObject *new_object; VipsImage *out; - /* Use VipsFile to build images, then pull 'out' from it and - * set that to set the value. + /* Use VipsFile to build images, then pull @out from it and + * use that to set the value. */ if( !(new_object = vips_object_new_from_string( oclass, value )) ) return( -1 ); + if( vips_object_build( new_object ) ) { + g_object_unref( new_object ); + return( -1 ); + } + g_object_get( new_object, "out", &out, NULL ); - /* Getting 'out' will have upped it's count and we want to + /* Getting @out will have upped it's count and we want to * hold the only ref to it. */ g_object_unref( out ); - /* 'out' holds a ref to new_object, we can drop ours. + /* @out holds a ref to new_object, we can drop ours. */ g_object_unref( new_object ); g_value_init( &gvalue, VIPS_TYPE_IMAGE ); g_value_set_object( &gvalue, out ); - /* Setting gvalue will have upped out's count again, + /* Setting gvalue will have upped @out's count again, * go back to 1 so that gvalue has the only ref. */ g_object_unref( out ); @@ -1270,6 +1275,11 @@ vips_object_set_argument_from_string( VipsObject *object, vips_object_new_from_string( oclass, value )) ) return( -1 ); + if( vips_object_build( new_object ) ) { + g_object_unref( new_object ); + return( -1 ); + } + g_value_init( &gvalue, G_TYPE_OBJECT ); g_value_set_object( &gvalue, new_object ); @@ -1407,7 +1417,30 @@ vips_object_get_argument_to_string( VipsObject *object, g_assert( argument_class->flags & VIPS_ARGUMENT_OUTPUT ); - if( g_type_is_a( otype, VIPS_TYPE_OBJECT ) && + if( g_type_is_a( otype, VIPS_TYPE_IMAGE ) && + (oclass = g_type_class_ref( VIPS_TYPE_FILE_SAVE )) ) { + VipsObject *new_object; + VipsImage *in; + + /* Use VipsFile to make a saver, set 'in' on that and run + * build to make it write. + */ + if( !(new_object = + vips_object_new_from_string( oclass, arg )) ) + return( -1 ); + + g_object_get( object, name, &in, NULL ); + g_object_set( new_object, "in", in, NULL ); + g_object_unref( in ); + + if( vips_object_build( new_object ) ) { + g_object_unref( new_object ); + return( -1 ); + } + + g_object_unref( new_object ); + } + else if( g_type_is_a( otype, VIPS_TYPE_OBJECT ) && (oclass = g_type_class_ref( otype )) && oclass->output_to_arg ) { VipsObject *value; @@ -1570,11 +1603,6 @@ vips_object_new_from_string( VipsObjectClass *object_class, const char *p ) } } - if( vips_object_build( object ) ) { - g_object_unref( object ); - return( NULL ); - } - return( object ); }