diff --git a/ChangeLog b/ChangeLog index 7d403090..980152d5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,7 @@ - yafr-smooth reworked along the lines of bicubic - cleanups after yafr hacking - added affinei_all +- don't set im_error() on failed callback 11/9/08 started 7.16.3 - oop typo in manpage for im_project() diff --git a/TODO b/TODO index db11a52e..75ad9f5d 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,6 @@ -- make a new package for "resample"? im_shrink & friends could go in there too +- started adding +#define IM_TYPE_GOBJECT "gobject" /* A GObject of a specified class */ or maybe "transform"? flip/rot90/embed etc. as well? - make a "deprecated" package too @@ -9,11 +10,41 @@ - try walking the class hierarchy below VipsInterpolate and see if we can see all the interpolators - classes need some extra fields + want bicubic args to be - nickname, eg. "bicubic" - caption, eg. "catmull-rom bicubic interpolation" + IM_GOBJECT( "VipsInterpolate", "interpolate" ); + ie. pass a gobject which is a sub-type of VipsInterpolate in an arg called + "interpolate" + + then we need to create an object of that class, get the param list, set from + any args, call object_init, and pass + + on return, unref the object + + so + + im_affinei_all in.v out.v "yafrsmooth(2.4)" 0.9 0 0 0.9 0 0 + + creates a yafrsmooth, sets the param, + + + in nip2, + + inter = g_object_new "VipsInterpolateBicubic" [$sharpness => 2.4]; + + also need something to return a list of GTypes below a name etc., find class + description:w + + + need k + + + +- make a new package for "resample"? im_shrink & friends could go in there too + +- how to expose things like yafrsmooth's "sharpening" parameter to + nip2/C++/Python? can we write a find-by-nickname function? eg. GType vips_get_type (const char *base, const char *nickname) @@ -54,9 +85,6 @@ - im_render should use a hash for tile lookup ... or+shift x/y together -- eval callbacks shouldn't set an errormsg? or maybe it should for debugging - and stuff - - bilinear should be a true subclass of interpolate ... and put the tables into the base class diff --git a/include/vips/dispatch.h b/include/vips/dispatch.h index 751823f7..edddc9af 100644 --- a/include/vips/dispatch.h +++ b/include/vips/dispatch.h @@ -55,6 +55,7 @@ extern "C" { #define IM_TYPE_IMAGE "image" /* IMAGE descriptor */ #define IM_TYPE_DISPLAY "display" /* Display descriptor */ #define IM_TYPE_GVALUE "gvalue" /* GValue wrapper */ +#define IM_TYPE_GOBJECT "gobject" /* A GObject of a specified class */ typedef char *im_arg_type; /* Type of argument id */ /* Internal representation of an argument to an image processing function. diff --git a/include/vips/object.h b/include/vips/object.h index f25dbc1e..e21de826 100644 --- a/include/vips/object.h +++ b/include/vips/object.h @@ -65,6 +65,15 @@ typedef struct _VipsObjectClass { /* Try to print something about the object, handy for debugging. */ void (*print)( VipsObject *, im_buf_t * ); + + /* Class nickname, eg. "VipsInterpolateBicubic" has "bicubic" as a + * nickname. Not internationalised. + */ + const char *nickname; + + /* Class description. Used for help messages, so internationalised. + */ + const char *description; } VipsObjectClass; void *vips_object_changed( VipsObject *vips_object ); diff --git a/include/vips/util.h b/include/vips/util.h index 3b1b9caa..2002b577 100644 --- a/include/vips/util.h +++ b/include/vips/util.h @@ -300,6 +300,12 @@ void *im_map_equal( void *a, void *b ); void *im_hash_table_map( GHashTable *hash, VSListMap2Fn fn, void *a, void *b ); +typedef void *(*VTypeMapFn)( GType, void * ); +typedef void *(*VTypeMap2Fn)( GType, void *, void * ); +void *im_type_map( GType base, VTypeMap2Fn fn, void *a, void *b ); +void *im_type_map_concrete_all( GType base, VTypeMapFn fn, void *a ); +GType im_type_find( const char *basename, const char *nickname ); + char *im_strncpy( char *dest, const char *src, int n ); char *im_strrstr( const char *haystack, const char *needle ); char *im_strdup( IMAGE *im, const char *str ); diff --git a/libsrc/iofuncs/callback.c b/libsrc/iofuncs/callback.c index d01420b5..365118fa 100644 --- a/libsrc/iofuncs/callback.c +++ b/libsrc/iofuncs/callback.c @@ -9,6 +9,8 @@ * - now always calls all callbacks, even if some fail * 2/7/08 * - added invalidate callbacks + * 26/11/08 + * - don't set im_error() on callback failed, that's the user's job */ /* @@ -135,8 +137,9 @@ call_callback( VCallback *cbs, int *result ) int res; if( (res = cbs->fn( cbs->a, cbs->b )) ) { - im_error( "im__trigger_callbacks", _( "user callback " - "failed for %s" ), cbs->im->filename ); + /* We don't set im_error() here, that's the callback's + * responsibility. + */ *result = res; #ifdef DEBUG_IO diff --git a/libsrc/iofuncs/object.c b/libsrc/iofuncs/object.c index 560efd83..2cd0277e 100644 --- a/libsrc/iofuncs/object.c +++ b/libsrc/iofuncs/object.c @@ -148,6 +148,8 @@ vips_object_class_init( VipsObjectClass *class ) class->changed = vips_object_real_changed; class->print = vips_object_real_print; + class->nickname = "object"; + class->description = _( "VIPS base class" ); vips_object_signals[SIG_CHANGED] = g_signal_new( "changed", G_OBJECT_CLASS_TYPE( gobject_class ), diff --git a/libsrc/iofuncs/util.c b/libsrc/iofuncs/util.c index d8e31fc2..87a8a1a4 100644 --- a/libsrc/iofuncs/util.c +++ b/libsrc/iofuncs/util.c @@ -242,6 +242,101 @@ im_hash_table_map( GHashTable *hash, VSListMap2Fn fn, void *a, void *b ) return( pair.result ); } +/* Map over all a type's children. + */ +void * +im_type_map( GType base, VTypeMap2Fn fn, void *a, void *b ) +{ + GType *child; + guint n_children; + int i; + void *result; + + child = g_type_children( base, &n_children ); + result = NULL; + for( i = 0; i < n_children && !result; i++ ) + result = fn( child[i], a, b ); + g_free( child ); + + return( result ); +} + +/* Loop over all the concrete subtypes of a base type. + */ +void * +im_type_map_concrete_all( GType base, VTypeMapFn fn, void *a ) +{ + void *result; + + result = NULL; + if( !G_TYPE_IS_ABSTRACT( base ) ) + result = fn( base, a ); + if( !result ) + result = im_type_map( base, + (VTypeMap2Fn) im_type_map_concrete_all, fn, a ); + + return( result ); +} + +static GType +test_name( GType type, const char *nickname ) +{ + GTypeClass *class; + VipsObjectClass *vips_class; + + /* Does this class exist? Try to create if not. + */ + if( !(class = g_type_class_peek( type )) ) + /* We don't unref, so the class is never finalized. This will + * make the peek work next time around and save us from + * constantly building and destroying classes. + */ + if( !(class = g_type_class_ref( type )) ) + return( 0 ); + + if( !VIPS_IS_OBJECT_CLASS( class ) ) + return( 0 ); + vips_class = VIPS_OBJECT_CLASS( class ); + if( strcasecmp( vips_class->nickname, nickname ) != 0 ) + return( 0 ); + + return( type ); +} + +/* Find a GType ... search below base, return the first match on a nickname or + * a name. + */ +GType +im_type_find( const char *basename, const char *nickname ) +{ + GType base; + GType type; + + if( !(base = g_type_from_name( basename )) ) { + im_error( "im_type_find", + _( "base type \"%s\" not found" ), basename ); + return( 0 ); + } + + /* Users can pass the real name instead of a nickname, provided the + * real name names a subclass of base. + */ + if( (type = g_type_from_name( nickname )) ) + if( g_type_is_a( type, base ) ) + return( type ); + + /* Nope, need to search. + */ + if( (type = (GType) im_type_map_concrete_all( base, + (VTypeMapFn) test_name, (void *) nickname )) ) + return( type ); + + im_error( "im_type_find", + _( "type \"%s\" not found" ), nickname ); + + return( 0 ); +} + /* Like strncpy(), but always NULL-terminate, and don't pad with NULLs. */ char * diff --git a/libsrc/mosaicing/bicubic.cpp b/libsrc/mosaicing/bicubic.cpp index b72276be..b16fdb49 100644 --- a/libsrc/mosaicing/bicubic.cpp +++ b/libsrc/mosaicing/bicubic.cpp @@ -380,12 +380,16 @@ vips_interpolate_bicubic_interpolate( VipsInterpolate *interpolate, static void vips_interpolate_bicubic_class_init( VipsInterpolateBicubicClass *iclass ) { + VipsObjectClass *object_class = VIPS_OBJECT_CLASS( iclass ); VipsInterpolateClass *interpolate_class = VIPS_INTERPOLATE_CLASS( iclass ); vips_interpolate_bicubic_parent_class = VIPS_INTERPOLATE_CLASS( g_type_class_peek_parent( iclass ) ); + object_class->nickname = "bicubic"; + object_class->description = _( "Bicubic interpolation (Catmull-Rom)" ); + interpolate_class->interpolate = vips_interpolate_bicubic_interpolate; interpolate_class->window_size = 4;