new-style CLI save working

This commit is contained in:
John Cupitt 2011-11-27 21:31:21 +00:00
parent d6240ac11a
commit b9db7249f4
8 changed files with 150 additions and 103 deletions

12
TODO
View File

@ -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 sure we are using the operation cache for jpegload
make compat wrappers for old im_jpeg2vips() and im_vips2jpeg()
move format/* to deprecated move format/* to deprecated
@ -15,7 +9,7 @@
- return missing just after read_xmp() in master?

View File

@ -876,6 +876,10 @@ input_interpolate_init( im_object *obj, char *str )
interpolate_class = vips_class_find( "VipsInterpolate", "interpolate" ); interpolate_class = vips_class_find( "VipsInterpolate", "interpolate" );
if( !(object = vips_object_new_from_string( interpolate_class, str )) ) if( !(object = vips_object_new_from_string( interpolate_class, str )) )
return( -1 ); return( -1 );
if( vips_object_build( object ) ) {
g_object_unref( object );
return( -1 );
}
*obj = object; *obj = object;
return( 0 ); return( 0 );

View File

@ -547,24 +547,34 @@ vips_file_load_build( VipsObject *object )
build( object ) ) build( object ) )
return( -1 ); return( -1 );
/* Read header fields to init the return image. THINSTRIP since this is /* Read the header into @out.
* probably a disc file. We can't tell yet whether we will be opening
* to memory, sadly, so we can't suggest ANY.
*/ */
if( class->header && if( class->header &&
class->header( load ) ) class->header( load ) )
return( -1 ); return( -1 );
vips_demand_hint( load->out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
/* Then 'start' creates the real image and 'gen' fetches pixels for /* If there's no ->load() method then the header read has done
* 'out' from real on demand. * everything. Otherwise, it's just set fields and we now must
* convert pixels on demand.
*/ */
if( vips_image_generate( load->out, if( class->load ) {
vips_file_load_start_cb, /* THINSTRIP since this is probably a disc file.
vips_file_load_generate_cb, * We can't tell yet whether we will be opening
vips_stop_one, * to memory, sadly, so we can't suggest ANY.
load, NULL ) ) */
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( vips_image_generate( load->out,
vips_file_load_start_cb,
vips_file_load_generate_cb,
vips_stop_one,
load, NULL ) )
return( -1 );
}
return( 0 ); return( 0 );
} }
@ -640,6 +650,69 @@ vips_file_save_print_class( VipsObjectClass *object_class, VipsBuf *buf )
VIPS_ENUM_NICK( VIPS_TYPE_SAVEABLE, class->saveable ) ); 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. /* Generate the saveable image.
*/ */
static int static int
@ -864,10 +937,11 @@ vips_file_save_class_init( VipsFileSaveClass *class )
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;
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->nickname = "filesave";
object_class->description = _( "file savers" ); 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, VIPS_ARG_IMAGE( class, "in", 0,
_( "Input" ), _( "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: * vips_file_read:
* @filename: file to load * @filename: file to load

View File

@ -49,16 +49,6 @@ typedef VipsFileLoadClass VipsFileLoadVipsClass;
G_DEFINE_TYPE( VipsFileLoadVips, vips_file_load_vips, VIPS_TYPE_FILE_LOAD ); 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 static gboolean
vips_file_load_vips_is_a( const char *filename ) vips_file_load_vips_is_a( const char *filename )
{ {
@ -86,20 +76,19 @@ static int
vips_file_load_vips_header( VipsFileLoad *load ) vips_file_load_vips_header( VipsFileLoad *load )
{ {
VipsFile *file = VIPS_FILE( 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( -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 g_object_set( load, "out", out2, NULL );
vips_file_load_vips_load( VipsFileLoad *load )
{
VipsFile *file = VIPS_FILE( load );
if( !(load->real = vips_image_new_from_file( file->filename )) )
return( -1 );
return( 0 ); return( 0 );
} }
@ -115,14 +104,13 @@ vips_file_load_vips_class_init( VipsFileLoadVipsClass *class )
object_class->nickname = "vipsload"; object_class->nickname = "vipsload";
object_class->description = _( "load vips from file" ); object_class->description = _( "load vips from file" );
object_class->build = vips_file_load_vips_build;
file_class->suffs = vips_suffs; file_class->suffs = vips_suffs;
load_class->is_a = vips_file_load_vips_is_a; load_class->is_a = vips_file_load_vips_is_a;
load_class->get_flags = vips_file_load_vips_get_flags; load_class->get_flags = vips_file_load_vips_get_flags;
load_class->header = vips_file_load_vips_header; load_class->header = vips_file_load_vips_header;
load_class->load = vips_file_load_vips_load; load_class->load = NULL;
} }
static void static void

View File

@ -145,11 +145,13 @@ typedef struct _VipsFileLoadClass {
*/ */
int (*get_flags)( VipsFileLoad * ); 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 * ); 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 * ); int (*load)( VipsFileLoad * );

View File

@ -682,7 +682,7 @@ vips_image_generate( VipsImage *image,
*/ */
vips_error( "VipsImage", vips_error( "VipsImage",
_( "unable to output to a %s image" ), _( "unable to output to a %s image" ),
VIPS_ENUM_NICK( VIPS_TYPE_DEMAND_STYLE, VIPS_ENUM_NICK( VIPS_TYPE_IMAGE_TYPE,
image->dtype ) ); image->dtype ) );
return( -1 ); return( -1 );
} }

View File

@ -1796,7 +1796,7 @@ vips_image_write_line( VipsImage *image, int ypos, PEL *linebuffer )
default: default:
vips_error( "VipsImage", vips_error( "VipsImage",
_( "unable to output to a %s image" ), _( "unable to output to a %s image" ),
VIPS_ENUM_STRING( VIPS_TYPE_DEMAND_STYLE, VIPS_ENUM_STRING( VIPS_TYPE_IMAGE_TYPE,
image->dtype ) ); image->dtype ) );
return( -1 ); return( -1 );
} }

View File

@ -1236,28 +1236,33 @@ vips_object_set_argument_from_string( VipsObject *object,
VipsObject *new_object; VipsObject *new_object;
VipsImage *out; VipsImage *out;
/* Use VipsFile to build images, then pull 'out' from it and /* Use VipsFile to build images, then pull @out from it and
* set that to set the value. * use that to set the value.
*/ */
if( !(new_object = if( !(new_object =
vips_object_new_from_string( oclass, value )) ) vips_object_new_from_string( oclass, value )) )
return( -1 ); return( -1 );
if( vips_object_build( new_object ) ) {
g_object_unref( new_object );
return( -1 );
}
g_object_get( new_object, "out", &out, NULL ); 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. * hold the only ref to it.
*/ */
g_object_unref( out ); 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_object_unref( new_object );
g_value_init( &gvalue, VIPS_TYPE_IMAGE ); g_value_init( &gvalue, VIPS_TYPE_IMAGE );
g_value_set_object( &gvalue, out ); 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. * go back to 1 so that gvalue has the only ref.
*/ */
g_object_unref( out ); g_object_unref( out );
@ -1270,6 +1275,11 @@ vips_object_set_argument_from_string( VipsObject *object,
vips_object_new_from_string( oclass, value )) ) vips_object_new_from_string( oclass, value )) )
return( -1 ); return( -1 );
if( vips_object_build( new_object ) ) {
g_object_unref( new_object );
return( -1 );
}
g_value_init( &gvalue, G_TYPE_OBJECT ); g_value_init( &gvalue, G_TYPE_OBJECT );
g_value_set_object( &gvalue, new_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 ); 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 = g_type_class_ref( otype )) &&
oclass->output_to_arg ) { oclass->output_to_arg ) {
VipsObject *value; 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 ); return( object );
} }