make CLI arg handling into vfuncs
add vfuncs to vipsobject for the CLI interface
This commit is contained in:
parent
26c0ce8fde
commit
0b902bfbd4
22
TODO
22
TODO
@ -1,28 +1,10 @@
|
||||
- try
|
||||
- test the vfunc system for CLI args
|
||||
|
||||
$ vips im_add k2.v babe.v out.v
|
||||
VIPS:ERROR:image.c:300:vips_image_finalize:
|
||||
assertion failed: (!image->regions)
|
||||
|
||||
during the close of k2.v, triggered by destroy_args() in package.c as it
|
||||
junks the argv ... there's one region there
|
||||
|
||||
I suppose we are unreffing one time too many during cleanup after
|
||||
im_run_command()
|
||||
|
||||
should the wrapper for im_open() do sink_ref to make sure it returns a real
|
||||
reference?
|
||||
vips_object_new_from_string() is now very confusingly named
|
||||
|
||||
|
||||
|
||||
|
||||
- vips_object_get_argument_to_string(),
|
||||
vips_object_get_argument_needs_string(),
|
||||
vips_object_set_argument_from_string()
|
||||
|
||||
should all be vfuncs on object
|
||||
|
||||
|
||||
|
||||
|
||||
- make something for Python as well
|
||||
|
@ -57,7 +57,7 @@ im_open( const char *filename, const char *mode )
|
||||
{
|
||||
VipsImage *image;
|
||||
|
||||
if( !(image = vips_image_new_from_file( filename, mode )) )
|
||||
if( !(image = vips_image_new_mode( filename, mode )) )
|
||||
return( NULL );
|
||||
|
||||
/* We have to refsink since the im_open() result is used like a hard
|
||||
|
@ -285,7 +285,7 @@ typedef struct _VipsImageClass {
|
||||
void (*posteval)( VipsImage *image, VipsProgress *progress );
|
||||
|
||||
/* An image has been written to.
|
||||
* Used by eg. vips_image_new_from_file("x.jpg", "w") to do the
|
||||
* Used by eg. vips_image_new_mode("x.jpg", "w") to do the
|
||||
* final write to jpeg.
|
||||
* Set *result to non-zero to indicate an error on write.
|
||||
*/
|
||||
@ -357,7 +357,8 @@ void vips_image_set_kill( VipsImage *image, gboolean kill );
|
||||
|
||||
VipsImage *vips_image_new( void );
|
||||
int vips_image_new_array( VipsObject *parent, VipsImage **images, int n );
|
||||
VipsImage *vips_image_new_from_file( const char *filename, const char *mode );
|
||||
VipsImage *vips_image_new_mode( const char *filename, const char *mode );
|
||||
VipsImage *vips_image_new_from_file( const char *filename );
|
||||
VipsImage *vips_image_new_from_file_raw( const char *filename,
|
||||
int xsize, int ysize, int bands, int offset );
|
||||
VipsImage *vips_image_new_from_memory( void *buffer,
|
||||
|
@ -261,6 +261,26 @@ struct _VipsObjectClass {
|
||||
*/
|
||||
void (*postclose)( VipsObject * );
|
||||
|
||||
/* The CLI interface. Implement these three to get CLI input and output
|
||||
* for your object.
|
||||
*/
|
||||
|
||||
/* Given a command-line arg (eg. a filename), make an instance of the
|
||||
* object.
|
||||
*/
|
||||
VipsObject *(*new_from_string)( const char *string );
|
||||
|
||||
/* Does this output arg need an arg from the command line? Image
|
||||
* output, for example, needs a filename to write to.
|
||||
*/
|
||||
gboolean output_needs_arg;
|
||||
|
||||
/* Write the object to the string. Return 0 for success, or -1 on
|
||||
* error setting vips_error(). string is NULL if output_needs_arg()
|
||||
* was FALSE.
|
||||
*/
|
||||
int (*output_to_arg)( VipsObject *object, const char *string );
|
||||
|
||||
/* Class nickname, eg. "VipsInterpolateBicubic" has "bicubic" as a
|
||||
* nickname. Not internationalised.
|
||||
*/
|
||||
|
@ -93,8 +93,8 @@
|
||||
* |[
|
||||
* IMAGE *im;
|
||||
*
|
||||
* if( !(im = vips_image_new_from_file( filename, "r" )) )
|
||||
* // vips_image_new_from_file() will set a mmessage, we don't need to
|
||||
* if( !(im = vips_image_new_from_file( filename )) )
|
||||
* // vips_image_new_from_file() will set a message, we don't need to
|
||||
* return( -1 );
|
||||
*
|
||||
* if( vips_image_get_width( im ) < 100 ) {
|
||||
|
@ -388,6 +388,20 @@ vips_image_dispose( GObject *gobject )
|
||||
G_OBJECT_CLASS( vips_image_parent_class )->dispose( gobject );
|
||||
}
|
||||
|
||||
|
||||
|
||||
static VipsObject *
|
||||
vips_image_new_from_file_object( const char *string )
|
||||
{
|
||||
return( VIPS_OBJECT( vips_image_new_from_file( string ) ) );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_image_write_object( VipsObject *object, const char *string )
|
||||
{
|
||||
return( vips_image_write( VIPS_IMAGE( object ), string ) );
|
||||
}
|
||||
|
||||
static void *
|
||||
print_field_fn( VipsImage *image, const char *field, GValue *value, void *a )
|
||||
{
|
||||
@ -1047,6 +1061,10 @@ vips_image_class_init( VipsImageClass *class )
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
vobject_class->new_from_string = vips_image_new_from_file_object;
|
||||
vobject_class->output_needs_arg = TRUE;
|
||||
vobject_class->output_to_arg = vips_image_write_object;
|
||||
|
||||
vobject_class->nickname = "image";
|
||||
vobject_class->description = _( "VIPS image class" );
|
||||
|
||||
@ -1435,7 +1453,7 @@ vips_image_temp_name( void )
|
||||
* vips_image_new() creates a "glue" descriptor you can use to join two image
|
||||
* processing operations together.
|
||||
*
|
||||
* It is the equivalent of vips_image_new_from_file("xxx", "p").
|
||||
* It is the equivalent of vips_image_new_mode("xxx", "p").
|
||||
*
|
||||
* Returns: the new #VipsImage, or %NULL on error.
|
||||
*/
|
||||
@ -1499,11 +1517,11 @@ vips_image_new_array( VipsObject *parent, VipsImage **images, int n )
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_image_new_from_file:
|
||||
* vips_image_new_mode:
|
||||
* @filename: file to open
|
||||
* @mode: mode to open with
|
||||
*
|
||||
* vips_image_new_from_file() examines the mode string and creates an
|
||||
* vips_image_new_mode() examines the mode string and creates an
|
||||
* appropriate #VipsImage.
|
||||
*
|
||||
* <itemizedlist>
|
||||
@ -1524,7 +1542,7 @@ vips_image_new_array( VipsObject *parent, VipsImage **images, int n )
|
||||
* <para>
|
||||
* <emphasis>"r"</emphasis>
|
||||
* opens the named file for reading. If the file is not in the native
|
||||
* VIPS format for your machine, vips_image_new_from_file()
|
||||
* VIPS format for your machine, vips_image_new_mode()
|
||||
* automatically converts the file for you in memory.
|
||||
*
|
||||
* For some large files (eg. TIFF) this may
|
||||
@ -1533,7 +1551,7 @@ vips_image_new_array( VipsObject *parent, VipsImage **images, int n )
|
||||
* API and control the loading process yourself. See
|
||||
* #VipsBandFormat.
|
||||
*
|
||||
* vips_image_new_from_file() can read files in most formats.
|
||||
* vips_image_new_mode() can read files in most formats.
|
||||
*
|
||||
* Note that <emphasis>"r"</emphasis> mode works in at least two stages.
|
||||
* It should return quickly and let you check header fields. It will
|
||||
@ -1545,7 +1563,7 @@ vips_image_new_array( VipsObject *parent, VipsImage **images, int n )
|
||||
* <emphasis>"rd"</emphasis>
|
||||
* opens the named file for reading. If the uncompressed image is larger
|
||||
* than a threshold and the file format does not support random access,
|
||||
* rather than uncompressing to memory, vips_image_new_from_file() will
|
||||
* rather than uncompressing to memory, vips_image_new_mode() will
|
||||
* uncompress to a temporary disc file. This file will be automatically
|
||||
* deleted when the IMAGE is closed.
|
||||
*
|
||||
@ -1574,7 +1592,7 @@ vips_image_new_array( VipsObject *parent, VipsImage **images, int n )
|
||||
* suffix to determine the type to write -- for example:
|
||||
*
|
||||
* |[
|
||||
* vips_image_new_from_file( "fred.tif", "w" )
|
||||
* vips_image_new_mode( "fred.tif", "w" )
|
||||
* ]|
|
||||
*
|
||||
* will write in TIFF format.
|
||||
@ -1593,7 +1611,7 @@ vips_image_new_array( VipsObject *parent, VipsImage **images, int n )
|
||||
* Returns: the new #VipsImage, or %NULL on error.
|
||||
*/
|
||||
VipsImage *
|
||||
vips_image_new_from_file( const char *filename, const char *mode )
|
||||
vips_image_new_mode( const char *filename, const char *mode )
|
||||
{
|
||||
VipsImage *image;
|
||||
|
||||
@ -1610,6 +1628,23 @@ vips_image_new_from_file( const char *filename, const char *mode )
|
||||
return( image );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_image_new_from_file:
|
||||
* @filename: file to open
|
||||
*
|
||||
* vips_image_new_from_file() opens @filename for reading. See
|
||||
* vips_image_new_mode() for details.
|
||||
*
|
||||
* See also: vips_image_new_mode().
|
||||
*
|
||||
* Returns: the new #VipsImage, or %NULL on error.
|
||||
*/
|
||||
VipsImage *
|
||||
vips_image_new_from_file( const char *filename )
|
||||
{
|
||||
return( vips_image_new_mode( filename, "r" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_image_new_from_file_raw:
|
||||
* @filename: filename to open
|
||||
@ -1721,7 +1756,7 @@ vips_image_new_disc_temp( const char *format )
|
||||
if( !(name = vips__temp_name( format )) )
|
||||
return( NULL );
|
||||
|
||||
if( !(image = vips_image_new_from_file( name, "w" )) ) {
|
||||
if( !(image = vips_image_new_mode( name, "w" )) ) {
|
||||
g_free( name );
|
||||
return( NULL );
|
||||
}
|
||||
@ -1750,7 +1785,7 @@ vips_image_write( VipsImage *image, const char *filename )
|
||||
{
|
||||
VipsImage *out;
|
||||
|
||||
if( !(out = vips_image_new_from_file( filename, "w" )) )
|
||||
if( !(out = vips_image_new_mode( filename, "w" )) )
|
||||
return( -1 );
|
||||
if( im_copy( image, out ) ) {
|
||||
g_object_unref( out );
|
||||
@ -2029,7 +2064,7 @@ vips_image_wio_input( VipsImage *image )
|
||||
/* Change to VIPS_IMAGE_SETBUF. First, make a memory
|
||||
* buffer and copy into that.
|
||||
*/
|
||||
if( !(t1 = vips_image_new_from_file( "wio_input", "t" )) )
|
||||
if( !(t1 = vips_image_new_mode( "wio_input", "t" )) )
|
||||
return( -1 );
|
||||
if( im_copy( image, t1 ) ) {
|
||||
g_object_unref( t1 );
|
||||
|
@ -1024,7 +1024,9 @@ vips_object_set_argument_from_string( VipsObject *object,
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
|
||||
GParamSpec *pspec;
|
||||
GType otype;
|
||||
VipsArgumentClass *argument_class;
|
||||
VipsObjectClass *oclass;
|
||||
GValue gvalue = { 0 };
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -1038,24 +1040,27 @@ vips_object_set_argument_from_string( VipsObject *object,
|
||||
G_OBJECT_TYPE_NAME( object ), name );
|
||||
return( -1 );
|
||||
}
|
||||
otype = G_PARAM_SPEC_VALUE_TYPE( pspec );
|
||||
|
||||
argument_class = (VipsArgumentClass *)
|
||||
vips__argument_table_lookup( class->argument_table, pspec );
|
||||
|
||||
g_assert( argument_class->flags & VIPS_ARGUMENT_INPUT );
|
||||
|
||||
if( G_IS_PARAM_SPEC_OBJECT( pspec ) &&
|
||||
G_PARAM_SPEC_VALUE_TYPE( pspec ) == VIPS_TYPE_IMAGE ) {
|
||||
VipsImage *image;
|
||||
if( g_type_is_a( otype, VIPS_TYPE_OBJECT ) &&
|
||||
(oclass = g_type_class_peek( otype )) &&
|
||||
oclass->new_from_string ) {
|
||||
VipsObject *object;
|
||||
|
||||
if( !(object = oclass->new_from_string( value )) )
|
||||
return( -1 );
|
||||
|
||||
g_value_init( &gvalue, G_TYPE_OBJECT );
|
||||
if( !(image = vips_image_new_from_file( value, "r" )) )
|
||||
return( -1 );
|
||||
|
||||
/* VipsObject is GInitiallyUnowned, so the gvalue now has a
|
||||
* ref count 1 image.
|
||||
*/
|
||||
g_value_set_object( &gvalue, image );
|
||||
g_value_set_object( &gvalue, object );
|
||||
}
|
||||
else if( G_IS_PARAM_SPEC_BOOLEAN( pspec ) ) {
|
||||
gboolean b;
|
||||
@ -1089,7 +1094,9 @@ vips_object_get_argument_needs_string( VipsObject *object, const char *name )
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
|
||||
GParamSpec *pspec;
|
||||
GType otype;
|
||||
VipsArgumentClass *argument_class;
|
||||
VipsObjectClass *oclass;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "vips_object_get_argument_needs_string: %s\n", name );
|
||||
@ -1101,19 +1108,20 @@ vips_object_get_argument_needs_string( VipsObject *object, const char *name )
|
||||
G_OBJECT_TYPE_NAME( object ), name );
|
||||
return( -1 );
|
||||
}
|
||||
otype = G_PARAM_SPEC_VALUE_TYPE( pspec );
|
||||
|
||||
argument_class = (VipsArgumentClass *)
|
||||
vips__argument_table_lookup( class->argument_table, pspec );
|
||||
|
||||
g_assert( argument_class->flags & VIPS_ARGUMENT_OUTPUT );
|
||||
|
||||
/* For now, we just support writing an image to a filename.
|
||||
/* For now, only vipsobject subclasses can ask for args.
|
||||
*/
|
||||
if( G_IS_PARAM_SPEC_OBJECT( pspec ) &&
|
||||
G_PARAM_SPEC_VALUE_TYPE( pspec ) == VIPS_TYPE_IMAGE )
|
||||
return( TRUE );
|
||||
else
|
||||
return( FALSE );
|
||||
if( g_type_is_a( otype, VIPS_TYPE_OBJECT ) &&
|
||||
(oclass = g_type_class_peek( otype )) )
|
||||
return( oclass->output_needs_arg );
|
||||
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1142,7 +1150,9 @@ vips_object_get_argument_to_string( VipsObject *object,
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
|
||||
GParamSpec *pspec;
|
||||
GType otype;
|
||||
VipsArgumentClass *argument_class;
|
||||
VipsObjectClass *oclass;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "vips_object_get_argument_to_string: %s -> %s\n",
|
||||
@ -1155,18 +1165,20 @@ vips_object_get_argument_to_string( VipsObject *object,
|
||||
G_OBJECT_TYPE_NAME( object ), name );
|
||||
return( -1 );
|
||||
}
|
||||
otype = G_PARAM_SPEC_VALUE_TYPE( pspec );
|
||||
|
||||
argument_class = (VipsArgumentClass *)
|
||||
vips__argument_table_lookup( class->argument_table, pspec );
|
||||
|
||||
g_assert( argument_class->flags & VIPS_ARGUMENT_OUTPUT );
|
||||
|
||||
if( G_IS_PARAM_SPEC_OBJECT( pspec ) &&
|
||||
G_PARAM_SPEC_VALUE_TYPE( pspec ) == VIPS_TYPE_IMAGE ) {
|
||||
VipsImage *value;
|
||||
if( g_type_is_a( otype, VIPS_TYPE_OBJECT ) &&
|
||||
(oclass = g_type_class_peek( otype )) &&
|
||||
oclass->output_to_arg ) {
|
||||
VipsObject *value;
|
||||
|
||||
g_object_get( object, name, &value, NULL );
|
||||
if( vips_image_write( value, arg ) ) {
|
||||
if( oclass->output_to_arg( value, arg ) ) {
|
||||
g_object_unref( value );
|
||||
return( -1 );
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user