diff --git a/ChangeLog b/ChangeLog index ef427506..7037565b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -17,6 +17,8 @@ - moved im_format_t to VipsFormat, now sits over VipsObject - IM_FORMAT_FLAG_PARTIAL -> VIPS_FORMAT_PARTIAL - updated docs +- interpolators use type introspection +- added vips --list interpolators 11/9/08 started 7.16.3 - oop typo in manpage for im_project() diff --git a/TODO b/TODO index 00feb666..a2b2d4e0 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,7 @@ +- nip2 Interpolate needs updating to new affinei thing + + + - started adding #define IM_TYPE_GOBJECT "gobject" /* A GObject of a specified class */ diff --git a/doc/src/func.tex b/doc/src/func.tex index 6373bfe5..1448bd04 100644 --- a/doc/src/func.tex +++ b/doc/src/func.tex @@ -1,7 +1,7 @@ \section{Function dispatch and plug-ins} As image processing libraries increase in size it becomes progressively more -difficult to build applications which present the operations the libbrary +difficult to build applications which present the operations the library offers to the user. Every time a new operation is added, every user interface needs to be adapted --- a job which can rapidly become unmanageable. diff --git a/include/vips/Makefile.am b/include/vips/Makefile.am index f1b5ea83..e5e8534f 100644 --- a/include/vips/Makefile.am +++ b/include/vips/Makefile.am @@ -3,7 +3,6 @@ pkginclude_HEADERS = \ VError.h \ VImage.h \ VMask.h \ - bicubic.h \ vipscpp.h \ colour.h \ debug.h \ @@ -25,8 +24,6 @@ pkginclude_HEADERS = \ meta.h \ version.h \ vips.h \ - yafrsmooth.h \ - yafrnohalo.h \ vips \ intl.h \ buf.h \ diff --git a/include/vips/bicubic.h b/include/vips/bicubic.h deleted file mode 100644 index e2418b6c..00000000 --- a/include/vips/bicubic.h +++ /dev/null @@ -1,86 +0,0 @@ -/* Bicubic (catmull-rom) interpolator. - */ - -/* - - This file is part of VIPS. - - VIPS is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - */ - -/* - - These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk - - */ - -#ifndef VIPS_BICUBIC_H -#define VIPS_BICUBIC_H - -#ifdef __cplusplus -extern "C" { -#endif /*__cplusplus*/ - -#define VIPS_TYPE_INTERPOLATE_BICUBIC \ - (vips_interpolate_bicubic_get_type()) -#define VIPS_INTERPOLATE_BICUBIC( obj ) \ - (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ - VIPS_TYPE_INTERPOLATE_BICUBIC, VipsInterpolateBicubic )) -#define VIPS_INTERPOLATE_BICUBIC_CLASS( klass ) \ - (G_TYPE_CHECK_CLASS_CAST( (klass), \ - VIPS_TYPE_INTERPOLATE_BICUBIC, VipsInterpolateBicubicClass)) -#define VIPS_IS_INTERPOLATE_BICUBIC( obj ) \ - (G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_INTERPOLATE_BICUBIC )) -#define VIPS_IS_INTERPOLATE_BICUBIC_CLASS( klass ) \ - (G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_INTERPOLATE_BICUBIC )) -#define VIPS_INTERPOLATE_BICUBIC_GET_CLASS( obj ) \ - (G_TYPE_INSTANCE_GET_CLASS( (obj), \ - VIPS_TYPE_INTERPOLATE_BICUBIC, VipsInterpolateBicubicClass )) - -typedef struct _VipsInterpolateBicubic { - VipsInterpolate parent_object; - -} VipsInterpolateBicubic; - -typedef struct _VipsInterpolateBicubicClass { - VipsInterpolateClass parent_class; - - /* Precalculated interpolation matricies. int (used for pel sizes up - * to short), and double (for all others). We go to scale + 1, so - * we can round-to-nearest safely. - */ - - /* We could keep a large set of 2d 4x4 matricies, but this actually - * works out slower, since for many resizes the thing will no longer - * fit in L1. - */ - int matrixi[VIPS_TRANSFORM_SCALE + 1][4]; - double matrixf[VIPS_TRANSFORM_SCALE + 1][4]; -} VipsInterpolateBicubicClass; - -GType vips_interpolate_bicubic_get_type( void ); -VipsInterpolate *vips_interpolate_bicubic_new( void ); - -/* Convenience: return a static default bicubic, so no need to free it. - */ -VipsInterpolate *vips_interpolate_bicubic_static( void ); - -#ifdef __cplusplus -} -#endif /*__cplusplus*/ - -#endif /*VIPS_BICUBIC_H*/ - diff --git a/include/vips/interpolate.h b/include/vips/interpolate.h index 117c8e6b..bc937b66 100644 --- a/include/vips/interpolate.h +++ b/include/vips/interpolate.h @@ -75,7 +75,7 @@ typedef struct _VipsInterpolateClass { */ int (*get_window_size)( VipsInterpolate * ); - /* Or just set this if you want constant. + /* Or just set this if you want a constant. */ int window_size; } VipsInterpolateClass; @@ -86,44 +86,6 @@ void vips_interpolate( VipsInterpolate *interpolate, VipsInterpolateMethod vips_interpolate_get_method( VipsInterpolate * ); int vips_interpolate_get_window_size( VipsInterpolate *interpolate ); -/* Nearest class starts. - */ - -#define VIPS_TYPE_INTERPOLATE_NEAREST (vips_interpolate_nearest_get_type()) -#define VIPS_INTERPOLATE_NEAREST( obj ) \ - (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ - VIPS_TYPE_INTERPOLATE_NEAREST, VipsInterpolateNearest )) -#define VIPS_INTERPOLATE_NEAREST_CLASS( klass ) \ - (G_TYPE_CHECK_CLASS_CAST( (klass), \ - VIPS_TYPE_INTERPOLATE_NEAREST, VipsInterpolateNearestClass)) -#define VIPS_IS_INTERPOLATE_NEAREST( obj ) \ - (G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_INTERPOLATE_NEAREST )) -#define VIPS_IS_INTERPOLATE_NEAREST_CLASS( klass ) \ - (G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_INTERPOLATE_NEAREST )) -#define VIPS_INTERPOLATE_NEAREST_GET_CLASS( obj ) \ - (G_TYPE_INSTANCE_GET_CLASS( (obj), \ - VIPS_TYPE_INTERPOLATE_NEAREST, VipsInterpolateNearestClass )) - -typedef struct _VipsInterpolateNearest { - VipsInterpolate parent_object; - -} VipsInterpolateNearest; - -typedef struct _VipsInterpolateNearestClass { - VipsInterpolateClass parent_class; - -} VipsInterpolateNearestClass; - -VipsInterpolate *vips_interpolate_nearest_new( void ); -GType vips_interpolate_nearest_get_type( void ); - -/* Convenience: return a static fast nearest, so no need to free it. - */ -VipsInterpolate *vips_interpolate_nearest_static( void ); - -/* Bilinear class starts. - */ - /* How many bits of precision we keep for transformations, ie. how many * pre-computed matricies we have. */ @@ -138,44 +100,20 @@ VipsInterpolate *vips_interpolate_nearest_static( void ); #define VIPS_INTERPOLATE_SHIFT (8) #define VIPS_INTERPOLATE_SCALE (1 << VIPS_INTERPOLATE_SHIFT) -#define VIPS_TYPE_INTERPOLATE_BILINEAR (vips_interpolate_bilinear_get_type()) -#define VIPS_INTERPOLATE_BILINEAR( obj ) \ - (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ - VIPS_TYPE_INTERPOLATE_BILINEAR, VipsInterpolateBilinear )) -#define VIPS_INTERPOLATE_BILINEAR_CLASS( klass ) \ - (G_TYPE_CHECK_CLASS_CAST( (klass), \ - VIPS_TYPE_INTERPOLATE_BILINEAR, VipsInterpolateBilinearClass)) -#define VIPS_IS_INTERPOLATE_BILINEAR( obj ) \ - (G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_INTERPOLATE_BILINEAR )) -#define VIPS_IS_INTERPOLATE_BILINEAR_CLASS( klass ) \ - (G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_INTERPOLATE_BILINEAR )) -#define VIPS_INTERPOLATE_BILINEAR_GET_CLASS( obj ) \ - (G_TYPE_INSTANCE_GET_CLASS( (obj), \ - VIPS_TYPE_INTERPOLATE_BILINEAR, VipsInterpolateBilinearClass )) - -typedef struct _VipsInterpolateBilinear { - VipsInterpolate parent_object; - -} VipsInterpolateBilinear; - -typedef struct _VipsInterpolateBilinearClass { - VipsInterpolateClass parent_class; - - /* Precalculated interpolation matricies. int (used for pel sizes up - * to short), and float (for all others). We go to scale + 1, so - * we can round-to-nearest safely. Don't bother with double, since - * this is an approximation anyway. - */ - int matrixi[VIPS_TRANSFORM_SCALE + 1][VIPS_TRANSFORM_SCALE + 1][4]; - float matrixd[VIPS_TRANSFORM_SCALE + 1][VIPS_TRANSFORM_SCALE + 1][4]; -} VipsInterpolateBilinearClass; - -GType vips_interpolate_bilinear_get_type( void ); -VipsInterpolate *vips_interpolate_bilinear_new( void ); - -/* Convenience: return a static bilinear, so no need to free it. +/* Convenience: return static interpolators, no need to unref. */ +VipsInterpolate *vips_interpolate_nearest_static( void ); VipsInterpolate *vips_interpolate_bilinear_static( void ); +VipsInterpolate *vips_interpolate_bicubic_static( void ); + +/* Convenience: make an interpolator from a nickname. g_object_unref() when + * you're done with it. + */ +VipsInterpolate *vips_interpolate_new( const char *nickname ); + +/* Register base vips types, called during startup. + */ +void vips__interpolate_init( void ); #ifdef __cplusplus } diff --git a/include/vips/util.h b/include/vips/util.h index d0e6a11a..66df0db6 100644 --- a/include/vips/util.h +++ b/include/vips/util.h @@ -306,6 +306,7 @@ typedef void *(*VipsClassMap)( VipsObjectClass *, void * ); void *vips_type_map( GType base, VipsTypeMap2 fn, void *a, void *b ); void *vips_type_map_concrete_all( GType base, VipsTypeMap fn, void *a ); void *vips_class_map_concrete_all( GType base, VipsClassMap fn, void *a ); +VipsObjectClass *vips_class_find( const char *basename, const char *nickname ); GType vips_type_find( const char *basename, const char *nickname ); char *im_strncpy( char *dest, const char *src, int n ); diff --git a/include/vips/vips.h b/include/vips/vips.h index c1651282..08601396 100644 --- a/include/vips/vips.h +++ b/include/vips/vips.h @@ -501,9 +501,6 @@ typedef struct { #include #include #include -#include -#include -#include #include #include #include diff --git a/include/vips/yafrnohalo.h b/include/vips/yafrnohalo.h deleted file mode 100644 index be5ee680..00000000 --- a/include/vips/yafrnohalo.h +++ /dev/null @@ -1,100 +0,0 @@ -/* YAFRNOHALO interpolator. - */ - -/* - - This file is part of VIPS. - - VIPS is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - */ - -/* - - These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk - - */ - -#ifndef VIPS_YAFRNOHALO_H -#define VIPS_YAFRNOHALO_H - -#ifdef __cplusplus -extern "C" { -#endif /*__cplusplus*/ - -#define VIPS_TYPE_INTERPOLATE_YAFRNOHALO (vips_interpolate_yafrnohalo_get_type()) -#define VIPS_INTERPOLATE_YAFRNOHALO( obj ) \ - (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ - VIPS_TYPE_INTERPOLATE_YAFRNOHALO, VipsInterpolateYafrnohalo )) -#define VIPS_INTERPOLATE_YAFRNOHALO_CLASS( klass ) \ - (G_TYPE_CHECK_CLASS_CAST( (klass), \ - VIPS_TYPE_INTERPOLATE_YAFRNOHALO, VipsInterpolateYafrnohaloClass)) -#define VIPS_IS_INTERPOLATE_YAFRNOHALO( obj ) \ - (G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_INTERPOLATE_YAFRNOHALO )) -#define VIPS_IS_INTERPOLATE_YAFRNOHALO_CLASS( klass ) \ - (G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_INTERPOLATE_YAFRNOHALO )) -#define VIPS_INTERPOLATE_YAFRNOHALO_GET_CLASS( obj ) \ - (G_TYPE_INSTANCE_GET_CLASS( (obj), \ - VIPS_TYPE_INTERPOLATE_YAFRNOHALO, VipsInterpolateYafrnohaloClass )) - -typedef struct _VipsInterpolateYafrnohalo { - VipsInterpolate parent_object; - - /* "sharpening" is a continuous method parameter which is - * proportional to the amount of "diagonal straightening" which the - * nonlinear correction part of the method may add to the underlying - * linear scheme. You may also think of it as a sharpening - * parameter: higher values correspond to more sharpening, and - * negative values lead to strange looking effects. - * - * The default value is sharpening = 4/3 when the scheme being - * "straightened" is bilinear---as is the case here. This value - * fixes key pixel values near the diagonal boundary between two - * monochrome regions (the diagonal boundary pixel values being set - * to the halfway colour). - * - * If resampling seems to add unwanted texture artifacts, push - * sharpening toward 0. It is not generally not recommended to set - * sharpening to a value larger than 2. - * - * In order to simplify interfacing with users, the parameter which - * should be set by the user is normalized so that user_sharpening = - * 1 when sharpening is equal to the recommended value. Consistently - * with the above discussion, values of user_sharpening between 0 - * and about 1.5 give good results. - */ - double sharpening; -} VipsInterpolateYafrnohalo; - -typedef struct _VipsInterpolateYafrnohaloClass { - VipsInterpolateClass parent_class; - -} VipsInterpolateYafrnohaloClass; - -GType vips_interpolate_yafrnohalo_get_type( void ); -VipsInterpolate *vips_interpolate_yafrnohalo_new( void ); -void vips_interpolate_yafrnohalo_set_sharpening( VipsInterpolateYafrnohalo *, - double sharpening ); - -/* Convenience: return a static default yafrnohalo, so no need to free it. - */ -VipsInterpolate *vips_interpolate_yafrnohalo_static( void ); - -#ifdef __cplusplus -} -#endif /*__cplusplus*/ - -#endif /*VIPS_YAFRNOHALO_H*/ - diff --git a/include/vips/yafrsmooth.h b/include/vips/yafrsmooth.h deleted file mode 100644 index c5ecc6ef..00000000 --- a/include/vips/yafrsmooth.h +++ /dev/null @@ -1,118 +0,0 @@ -/* Yafrsmooth (catmull-rom) interpolator. - */ - -/* - - This file is part of VIPS. - - VIPS is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - */ - -/* - - These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk - - */ - -#ifndef VIPS_YAFRSMOOTH_H -#define VIPS_YAFRSMOOTH_H - -#ifdef __cplusplus -extern "C" { -#endif /*__cplusplus*/ - -#define VIPS_TYPE_INTERPOLATE_YAFRSMOOTH \ - (vips_interpolate_yafrsmooth_get_type()) -#define VIPS_INTERPOLATE_YAFRSMOOTH( obj ) \ - (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ - VIPS_TYPE_INTERPOLATE_YAFRSMOOTH, VipsInterpolateYafrsmooth )) -#define VIPS_INTERPOLATE_YAFRSMOOTH_CLASS( klass ) \ - (G_TYPE_CHECK_CLASS_CAST( (klass), \ - VIPS_TYPE_INTERPOLATE_YAFRSMOOTH, VipsInterpolateYafrsmoothClass)) -#define VIPS_IS_INTERPOLATE_YAFRSMOOTH( obj ) \ - (G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_INTERPOLATE_YAFRSMOOTH )) -#define VIPS_IS_INTERPOLATE_YAFRSMOOTH_CLASS( klass ) \ - (G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_INTERPOLATE_YAFRSMOOTH )) -#define VIPS_INTERPOLATE_YAFRSMOOTH_GET_CLASS( obj ) \ - (G_TYPE_INSTANCE_GET_CLASS( (obj), \ - VIPS_TYPE_INTERPOLATE_YAFRSMOOTH, VipsInterpolateYafrsmoothClass )) - -typedef struct _VipsInterpolateYafrsmooth { - VipsInterpolate parent_object; - - /* "sharpening" is a continuous method parameter which is - * proportional to the amount of "diagonal straightening" which the - * nonlinear correction part of the method may add to the underlying - * linear scheme. You may also think of it as a sharpening - * parameter: higher values correspond to more sharpening, and - * negative values lead to strange looking effects. - * - * The default value is sharpening = 29/32 when the scheme being - * "straightened" is Catmull-Rom---as is the case here. This value - * fixes key pixel values near the diagonal boundary between two - * monochrome regions (the diagonal boundary pixel values being set - * to the halfway colour). - * - * If resampling seems to add unwanted texture artifacts, push - * sharpening toward 0. It is not generally not recommended to set - * sharpening to a value larger than 4. - * - * Sharpening is halved because the .5 which has to do with the - * relative coordinates of the evaluation points (which has to do - * with .5*rite_width etc) is folded into the constant to save - * flops. Consequently, the largest recommended value of - * sharpening_over_two is 2=4/2. - * - * In order to simplify interfacing with users, the parameter which - * should be set by the user is normalized so that user_sharpening = - * 1 when sharpening is equal to the recommended value. Consistently - * with the above discussion, values of user_sharpening between 0 - * and about 3.625 give good results. - */ - double sharpening; -} VipsInterpolateYafrsmooth; - -typedef struct _VipsInterpolateYafrsmoothClass { - VipsInterpolateClass parent_class; - - /* Precalculated interpolation matricies. int (used for pel sizes up - * to short), and double (for all others). We go to scale + 1, so - * we can round-to-nearest safely. - */ - - /* We could keep a large set of 2d 4x4 matricies, but this actually - * works out slower, since for many resizes the thing will no longer - * fit in L1. - */ - int matrixi[VIPS_TRANSFORM_SCALE + 1][4]; - double matrixf[VIPS_TRANSFORM_SCALE + 1][4]; -} VipsInterpolateYafrsmoothClass; - -GType vips_interpolate_yafrsmooth_get_type( void ); -VipsInterpolate *vips_interpolate_yafrsmooth_new( void ); -void vips_interpolate_yafrsmooth_set_sharpening( VipsInterpolateYafrsmooth *, - double sharpening ); - -/* Convenience: return a static default yafrsmooth, so no need to free it. - */ -VipsInterpolate *vips_interpolate_yafrsmooth_static( void ); - -#ifdef __cplusplus -} -#endif /*__cplusplus*/ - -#endif /*VIPS_YAFRSMOOTH_H*/ - diff --git a/libsrc/iofuncs/im_init_world.c b/libsrc/iofuncs/im_init_world.c index 8d10ee1a..5410cd2b 100644 --- a/libsrc/iofuncs/im_init_world.c +++ b/libsrc/iofuncs/im_init_world.c @@ -131,13 +131,11 @@ im_init_world( const char *argv0 ) bindtextdomain( GETTEXT_PACKAGE, name ); bind_textdomain_codeset( GETTEXT_PACKAGE, "UTF-8" ); - /* Start up converters for builtin types. + /* Register base vips types. */ im__meta_init_types(); - - /* Add the base format load/save operations. - */ im__format_init(); + vips__interpolate_init(); /* Load up any plugins in the vips libdir. We don't error on failure, * it's too annoying to have VIPS refuse to start because of a broken diff --git a/libsrc/iofuncs/util.c b/libsrc/iofuncs/util.c index 308df164..f432f5f6 100644 --- a/libsrc/iofuncs/util.c +++ b/libsrc/iofuncs/util.c @@ -315,12 +315,12 @@ vips_class_map_concrete_all( GType type, VipsClassMap fn, void *a ) static void * test_name( VipsObjectClass *class, const char *nickname ) { - if( strcasecmp( class->nickname, nickname ) != 0 ) + if( strcasecmp( class->nickname, nickname ) == 0 ) return( class ); /* Check the class name too, why not. */ - if( strcasecmp( G_OBJECT_CLASS_NAME( class ), nickname ) != 0 ) + if( strcasecmp( G_OBJECT_CLASS_NAME( class ), nickname ) == 0 ) return( class ); return( NULL ); @@ -351,6 +351,20 @@ vips_class_find( const char *basename, const char *nickname ) return( class ); } +GType +vips_type_find( const char *basename, const char *nickname ) +{ + VipsObjectClass *class; + + if( !(class = vips_class_find( "VipsInterpolate", nickname )) ) + return( 0 ); + + /* FIXME ... we've not supposed to use G_TYPE_FROM_CLASS(), I think. + * I'm not * sure what the alternative is. + */ + return( G_TYPE_FROM_CLASS( class ) ); +} + /* 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 b16fdb49..0bc0af56 100644 --- a/libsrc/mosaicing/bicubic.cpp +++ b/libsrc/mosaicing/bicubic.cpp @@ -52,7 +52,49 @@ #include #endif /*WITH_DMALLOC*/ -static VipsInterpolateClass *vips_interpolate_bicubic_parent_class = NULL; +#define VIPS_TYPE_INTERPOLATE_BICUBIC \ + (vips_interpolate_bicubic_get_type()) +#define VIPS_INTERPOLATE_BICUBIC( obj ) \ + (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ + VIPS_TYPE_INTERPOLATE_BICUBIC, VipsInterpolateBicubic )) +#define VIPS_INTERPOLATE_BICUBIC_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_CAST( (klass), \ + VIPS_TYPE_INTERPOLATE_BICUBIC, VipsInterpolateBicubicClass)) +#define VIPS_IS_INTERPOLATE_BICUBIC( obj ) \ + (G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_INTERPOLATE_BICUBIC )) +#define VIPS_IS_INTERPOLATE_BICUBIC_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_INTERPOLATE_BICUBIC )) +#define VIPS_INTERPOLATE_BICUBIC_GET_CLASS( obj ) \ + (G_TYPE_INSTANCE_GET_CLASS( (obj), \ + VIPS_TYPE_INTERPOLATE_BICUBIC, VipsInterpolateBicubicClass )) + +typedef struct _VipsInterpolateBicubic { + VipsInterpolate parent_object; + +} VipsInterpolateBicubic; + +typedef struct _VipsInterpolateBicubicClass { + VipsInterpolateClass parent_class; + + /* Precalculated interpolation matricies. int (used for pel sizes up + * to short), and double (for all others). We go to scale + 1, so + * we can round-to-nearest safely. + */ + + /* We could keep a large set of 2d 4x4 matricies, but this actually + * works out slower, since for many resizes the thing will no longer + * fit in L1. + */ + int matrixi[VIPS_TRANSFORM_SCALE + 1][4]; + double matrixf[VIPS_TRANSFORM_SCALE + 1][4]; +} VipsInterpolateBicubicClass; + +/* We need C linkage for this. + */ +extern "C" { +G_DEFINE_TYPE( VipsInterpolateBicubic, vips_interpolate_bicubic, + VIPS_TYPE_INTERPOLATE ); +} /* Pointers to write to / read from, number of bands, * how many bytes to add to move down a line. @@ -384,9 +426,6 @@ vips_interpolate_bicubic_class_init( VipsInterpolateBicubicClass *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)" ); @@ -416,48 +455,3 @@ vips_interpolate_bicubic_init( VipsInterpolateBicubic *bicubic ) } -GType -vips_interpolate_bicubic_get_type() -{ - static GType type = 0; - - if( !type ) { - static const GTypeInfo info = { - sizeof( VipsInterpolateBicubicClass ), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) vips_interpolate_bicubic_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof( VipsInterpolateBicubic ), - 32, /* n_preallocs */ - (GInstanceInitFunc) vips_interpolate_bicubic_init, - }; - - type = g_type_register_static( VIPS_TYPE_INTERPOLATE, - "VipsInterpolateBicubic", &info, - (GTypeFlags) 0 ); - } - - return( type ); -} - -VipsInterpolate * -vips_interpolate_bicubic_new( void ) -{ - return( VIPS_INTERPOLATE( g_object_new( - VIPS_TYPE_INTERPOLATE_BICUBIC, NULL ) ) ); -} - -/* Convenience: return a static bicubic you don't need to free. - */ -VipsInterpolate * -vips_interpolate_bicubic_static( void ) -{ - static VipsInterpolate *interpolate = NULL; - - if( !interpolate ) - interpolate = vips_interpolate_bicubic_new(); - - return( interpolate ); -} diff --git a/libsrc/mosaicing/im_affine.c b/libsrc/mosaicing/im_affine.c index 178e010c..701a9bf3 100644 --- a/libsrc/mosaicing/im_affine.c +++ b/libsrc/mosaicing/im_affine.c @@ -516,7 +516,7 @@ im_affine( IMAGE *in, IMAGE *out, int ox, int oy, int ow, int oh ) { return( im_affinei( in, out, - vips_interpolate_bicubic_static(), + vips_interpolate_bilinear_static(), a, b, c, d, dx, dy, ox, oy, ow, oh ) ); } diff --git a/libsrc/mosaicing/interpolate.c b/libsrc/mosaicing/interpolate.c index fdf490fb..51f9178c 100644 --- a/libsrc/mosaicing/interpolate.c +++ b/libsrc/mosaicing/interpolate.c @@ -52,9 +52,7 @@ */ #define FLOOR( V ) ((V) >= 0 ? (int)(V) : (int)((V) - 1)) -static VipsInterpolateClass *vips_interpolate_parent_class = NULL; -static VipsInterpolateClass *vips_interpolate_nearest_parent_class = NULL; -static VipsInterpolateClass *vips_interpolate_bilinear_parent_class = NULL; +G_DEFINE_ABSTRACT_TYPE( VipsInterpolate, vips_interpolate, VIPS_TYPE_OBJECT ); #ifdef DEBUG static void @@ -84,8 +82,6 @@ vips_interpolate_class_init( VipsInterpolateClass *class ) GObjectClass *gobject_class = G_OBJECT_CLASS( class ); #endif /*DEBUG*/ - vips_interpolate_parent_class = g_type_class_peek_parent( class ); - #ifdef DEBUG gobject_class->finalize = vips_interpolate_finalize; #endif /*DEBUG*/ @@ -103,31 +99,6 @@ vips_interpolate_init( VipsInterpolate *interpolate ) #endif /*DEBUG*/ } -GType -vips_interpolate_get_type( void ) -{ - static GType type = 0; - - if( !type ) { - static const GTypeInfo info = { - sizeof( VipsInterpolateClass ), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) vips_interpolate_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof( VipsInterpolate ), - 32, /* n_preallocs */ - (GInstanceInitFunc) vips_interpolate_init, - }; - - type = g_type_register_static( VIPS_TYPE_OBJECT, - "VipsInterpolate", &info, 0 ); - } - - return( type ); -} - /* Set the point out_x, out_y in REGION out to be the point interpolated at * in_x, in_y in REGION in. Don't do this as a signal ffor speed. */ @@ -168,6 +139,29 @@ vips_interpolate_get_window_size( VipsInterpolate *interpolate ) /* VipsInterpolateNearest class */ +#define VIPS_TYPE_INTERPOLATE_NEAREST (vips_interpolate_nearest_get_type()) +#define VIPS_INTERPOLATE_NEAREST( obj ) \ + (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ + VIPS_TYPE_INTERPOLATE_NEAREST, VipsInterpolateNearest )) +#define VIPS_INTERPOLATE_NEAREST_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_CAST( (klass), \ + VIPS_TYPE_INTERPOLATE_NEAREST, VipsInterpolateNearestClass)) +#define VIPS_IS_INTERPOLATE_NEAREST( obj ) \ + (G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_INTERPOLATE_NEAREST )) +#define VIPS_IS_INTERPOLATE_NEAREST_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_INTERPOLATE_NEAREST )) +#define VIPS_INTERPOLATE_NEAREST_GET_CLASS( obj ) \ + (G_TYPE_INSTANCE_GET_CLASS( (obj), \ + VIPS_TYPE_INTERPOLATE_NEAREST, VipsInterpolateNearestClass )) + +/* No new members. + */ +typedef VipsInterpolate VipsInterpolateNearest; +typedef VipsInterpolateClass VipsInterpolateNearestClass; + +G_DEFINE_TYPE( VipsInterpolateNearest, vips_interpolate_nearest, + VIPS_TYPE_INTERPOLATE ); + static void vips_interpolate_nearest_interpolate( VipsInterpolate *interpolate, PEL *out, REGION *in, double x, double y ) @@ -191,11 +185,12 @@ vips_interpolate_nearest_interpolate( VipsInterpolate *interpolate, static void vips_interpolate_nearest_class_init( VipsInterpolateNearestClass *class ) { + VipsObjectClass *object_class = VIPS_OBJECT_CLASS( class ); VipsInterpolateClass *interpolate_class = VIPS_INTERPOLATE_CLASS( class ); - vips_interpolate_nearest_parent_class = - g_type_class_peek_parent( class ); + object_class->nickname = "nearest"; + object_class->description = _( "Nearest-neighbour interpolation" ); interpolate_class->interpolate = vips_interpolate_nearest_interpolate; interpolate_class->window_size = 1; @@ -208,32 +203,6 @@ vips_interpolate_nearest_init( VipsInterpolateNearest *nearest ) printf( "vips_interpolate_nearest_init: " ); vips_object_print( VIPS_OBJECT( nearest ) ); #endif /*DEBUG*/ - -} - -GType -vips_interpolate_nearest_get_type( void ) -{ - static GType type = 0; - - if( !type ) { - static const GTypeInfo info = { - sizeof( VipsInterpolateNearestClass ), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) vips_interpolate_nearest_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof( VipsInterpolateNearest ), - 32, /* n_preallocs */ - (GInstanceInitFunc) vips_interpolate_nearest_init, - }; - - type = g_type_register_static( VIPS_TYPE_INTERPOLATE, - "VipsInterpolateNearest", &info, 0 ); - } - - return( type ); } VipsInterpolate * @@ -259,6 +228,38 @@ vips_interpolate_nearest_static( void ) /* VipsInterpolateBilinear class */ +#define VIPS_TYPE_INTERPOLATE_BILINEAR (vips_interpolate_bilinear_get_type()) +#define VIPS_INTERPOLATE_BILINEAR( obj ) \ + (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ + VIPS_TYPE_INTERPOLATE_BILINEAR, VipsInterpolateBilinear )) +#define VIPS_INTERPOLATE_BILINEAR_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_CAST( (klass), \ + VIPS_TYPE_INTERPOLATE_BILINEAR, VipsInterpolateBilinearClass)) +#define VIPS_IS_INTERPOLATE_BILINEAR( obj ) \ + (G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_INTERPOLATE_BILINEAR )) +#define VIPS_IS_INTERPOLATE_BILINEAR_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_INTERPOLATE_BILINEAR )) +#define VIPS_INTERPOLATE_BILINEAR_GET_CLASS( obj ) \ + (G_TYPE_INSTANCE_GET_CLASS( (obj), \ + VIPS_TYPE_INTERPOLATE_BILINEAR, VipsInterpolateBilinearClass )) + +typedef VipsInterpolate VipsInterpolateBilinear; + +typedef struct _VipsInterpolateBilinearClass { + VipsInterpolateClass parent_class; + + /* Precalculated interpolation matricies. int (used for pel sizes up + * to short), and float (for all others). We go to scale + 1, so + * we can round-to-nearest safely. Don't bother with double, since + * this is an approximation anyway. + */ + int matrixi[VIPS_TRANSFORM_SCALE + 1][VIPS_TRANSFORM_SCALE + 1][4]; + float matrixd[VIPS_TRANSFORM_SCALE + 1][VIPS_TRANSFORM_SCALE + 1][4]; +} VipsInterpolateBilinearClass; + +G_DEFINE_TYPE( VipsInterpolateBilinear, vips_interpolate_bilinear, + VIPS_TYPE_INTERPOLATE ); + /* in this class, name vars in the 2x2 grid as eg. * p1 p2 * p3 p4 @@ -364,12 +365,13 @@ vips_interpolate_bilinear_interpolate( VipsInterpolate *interpolate, static void vips_interpolate_bilinear_class_init( VipsInterpolateBilinearClass *class ) { + VipsObjectClass *object_class = VIPS_OBJECT_CLASS( class ); VipsInterpolateClass *interpolate_class = (VipsInterpolateClass *) class; int x, y; - vips_interpolate_bilinear_parent_class = - g_type_class_peek_parent( class ); + object_class->nickname = "bilinear"; + object_class->description = _( "Bilinear interpolation" ); interpolate_class->interpolate = vips_interpolate_bilinear_interpolate; interpolate_class->window_size = 2; @@ -417,31 +419,6 @@ vips_interpolate_bilinear_init( VipsInterpolateBilinear *bilinear ) } -GType -vips_interpolate_bilinear_get_type( void ) -{ - static GType type = 0; - - if( !type ) { - static const GTypeInfo info = { - sizeof( VipsInterpolateBilinearClass ), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) vips_interpolate_bilinear_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof( VipsInterpolateBilinear ), - 32, /* n_preallocs */ - (GInstanceInitFunc) vips_interpolate_bilinear_init, - }; - - type = g_type_register_static( VIPS_TYPE_INTERPOLATE, - "VipsInterpolateBilinear", &info, 0 ); - } - - return( type ); -} - VipsInterpolate * vips_interpolate_bilinear_new( void ) { @@ -462,3 +439,31 @@ vips_interpolate_bilinear_static( void ) return( interpolate ); } +/* Called on startup: register the base vips interpolators. + */ +void +vips__interpolate_init( void ) +{ + extern GType vips_interpolate_bicubic_get_type( void ); + extern GType vips_interpolate_yafrsmooth_get_type( void ); + extern GType vips_interpolate_yafrnohalo_get_type( void ); + + vips_interpolate_nearest_get_type(); + vips_interpolate_bilinear_get_type(); + vips_interpolate_bicubic_get_type(); + vips_interpolate_yafrsmooth_get_type(); + vips_interpolate_yafrnohalo_get_type(); +} + +/* Make an interpolator from a nickname. + */ +VipsInterpolate * +vips_interpolate_new( const char *nickname ) +{ + GType type; + + if( !(type = vips_type_find( "VipsInterpolate", nickname )) ) + return( NULL ); + + return( VIPS_INTERPOLATE( g_object_new( type, NULL ) ) ); +} diff --git a/libsrc/mosaicing/mosaicing_dispatch.c b/libsrc/mosaicing/mosaicing_dispatch.c index 4c251cf4..d0153d82 100644 --- a/libsrc/mosaicing/mosaicing_dispatch.c +++ b/libsrc/mosaicing/mosaicing_dispatch.c @@ -522,7 +522,7 @@ static im_function affine_desc = { static im_arg_desc affinei_args[] = { IM_INPUT_IMAGE( "in" ), IM_OUTPUT_IMAGE( "out" ), - IM_INPUT_INT( "interpolate" ), + IM_INPUT_STRING( "interpolate" ), IM_INPUT_DOUBLE( "a" ), IM_INPUT_DOUBLE( "b" ), IM_INPUT_DOUBLE( "c" ), @@ -535,46 +535,12 @@ static im_arg_desc affinei_args[] = { IM_INPUT_INT( "h" ) }; -static VipsInterpolate * -get_interpolate( int interpol ) -{ - VipsInterpolate *interpolate; - - switch( interpol ) { - case 1: - interpolate = vips_interpolate_nearest_new(); - break; - - case 2: - interpolate = vips_interpolate_bilinear_new(); - break; - - case 3: - interpolate = vips_interpolate_bicubic_new(); - break; - - case 4: - interpolate = vips_interpolate_yafrsmooth_new(); - break; - - case 5: - interpolate = vips_interpolate_yafrnohalo_new(); - break; - - default: - im_error( "affinei_vec", "%s", _( "bad interpolation" ) ); - interpolate = NULL; - } - - return( interpolate ); -} - /* Call im_affinei via arg vector. */ static int affinei_vec( im_object *argv ) { - int interpol = *((int *) argv[2]); + const char *interpol = argv[2]; double a = *((double *) argv[3]); double b = *((double *) argv[4]); double c = *((double *) argv[5]); @@ -588,7 +554,7 @@ affinei_vec( im_object *argv ) VipsInterpolate *interpolate; int result; - if( !(interpolate = get_interpolate( interpol )) ) + if( !(interpolate = vips_interpolate_new( interpol )) ) return( -1 ); result = im_affinei( argv[0], argv[1], interpolate, a, b, c, d, dx, dy, x, y, w, h ); @@ -613,7 +579,7 @@ static im_function affinei_desc = { static im_arg_desc affinei_all_args[] = { IM_INPUT_IMAGE( "in" ), IM_OUTPUT_IMAGE( "out" ), - IM_INPUT_INT( "interpolate" ), + IM_INPUT_STRING( "interpolate" ), IM_INPUT_DOUBLE( "a" ), IM_INPUT_DOUBLE( "b" ), IM_INPUT_DOUBLE( "c" ), @@ -627,7 +593,7 @@ static im_arg_desc affinei_all_args[] = { static int affinei_all_vec( im_object *argv ) { - int interpol = *((int *) argv[2]); + const char *interpol = argv[2]; double a = *((double *) argv[3]); double b = *((double *) argv[4]); double c = *((double *) argv[5]); @@ -637,7 +603,7 @@ affinei_all_vec( im_object *argv ) VipsInterpolate *interpolate; int result; - if( !(interpolate = get_interpolate( interpol )) ) + if( !(interpolate = vips_interpolate_new( interpol )) ) return( -1 ); result = im_affinei_all( argv[0], argv[1], interpolate, a, b, c, d, dx, dy ); diff --git a/libsrc/mosaicing/yafrnohalo.c b/libsrc/mosaicing/yafrnohalo.c index ae4f6ff8..bdda6767 100644 --- a/libsrc/mosaicing/yafrnohalo.c +++ b/libsrc/mosaicing/yafrnohalo.c @@ -50,7 +50,58 @@ */ #define FLOOR( V ) ((V) >= 0 ? (int)(V) : (int)((V) - 1)) -static VipsInterpolateClass *vips_interpolate_yafrnohalo_parent_class = NULL; +#define VIPS_TYPE_INTERPOLATE_YAFRNOHALO \ + (vips_interpolate_yafrnohalo_get_type()) +#define VIPS_INTERPOLATE_YAFRNOHALO( obj ) \ + (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ + VIPS_TYPE_INTERPOLATE_YAFRNOHALO, VipsInterpolateYafrnohalo )) +#define VIPS_INTERPOLATE_YAFRNOHALO_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_CAST( (klass), \ + VIPS_TYPE_INTERPOLATE_YAFRNOHALO, VipsInterpolateYafrnohaloClass)) +#define VIPS_IS_INTERPOLATE_YAFRNOHALO( obj ) \ + (G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_INTERPOLATE_YAFRNOHALO )) +#define VIPS_IS_INTERPOLATE_YAFRNOHALO_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_INTERPOLATE_YAFRNOHALO )) +#define VIPS_INTERPOLATE_YAFRNOHALO_GET_CLASS( obj ) \ + (G_TYPE_INSTANCE_GET_CLASS( (obj), \ + VIPS_TYPE_INTERPOLATE_YAFRNOHALO, VipsInterpolateYafrnohaloClass )) + +typedef struct _VipsInterpolateYafrnohalo { + VipsInterpolate parent_object; + + /* "sharpening" is a continuous method parameter which is + * proportional to the amount of "diagonal straightening" which the + * nonlinear correction part of the method may add to the underlying + * linear scheme. You may also think of it as a sharpening + * parameter: higher values correspond to more sharpening, and + * negative values lead to strange looking effects. + * + * The default value is sharpening = 4/3 when the scheme being + * "straightened" is bilinear---as is the case here. This value + * fixes key pixel values near the diagonal boundary between two + * monochrome regions (the diagonal boundary pixel values being set + * to the halfway colour). + * + * If resampling seems to add unwanted texture artifacts, push + * sharpening toward 0. It is not generally not recommended to set + * sharpening to a value larger than 2. + * + * In order to simplify interfacing with users, the parameter which + * should be set by the user is normalized so that user_sharpening = + * 1 when sharpening is equal to the recommended value. Consistently + * with the above discussion, values of user_sharpening between 0 + * and about 1.5 give good results. + */ + double sharpening; +} VipsInterpolateYafrnohalo; + +typedef struct _VipsInterpolateYafrnohaloClass { + VipsInterpolateClass parent_class; + +} VipsInterpolateYafrnohaloClass; + +G_DEFINE_TYPE( VipsInterpolateYafrnohalo, vips_interpolate_yafrnohalo, + VIPS_TYPE_INTERPOLATE ); /* Copy-paste of gegl-sampler-yafr-nohalo.c starts */ @@ -1007,11 +1058,12 @@ vips_interpolate_yafrnohalo_interpolate( VipsInterpolate *interpolate, static void vips_interpolate_yafrnohalo_class_init( VipsInterpolateYafrnohaloClass *class ) { + VipsObjectClass *object_class = VIPS_OBJECT_CLASS( class ); VipsInterpolateClass *interpolate_class = VIPS_INTERPOLATE_CLASS( class ); - vips_interpolate_yafrnohalo_parent_class = - g_type_class_peek_parent( class ); + object_class->nickname = "yafrnohalo"; + object_class->description = _( "YAFR nohalo interpolation" ); interpolate_class->interpolate = vips_interpolate_yafrnohalo_interpolate; @@ -1028,58 +1080,3 @@ vips_interpolate_yafrnohalo_init( VipsInterpolateYafrnohalo *yafrnohalo ) yafrnohalo->sharpening = 1.0; } - -GType -vips_interpolate_yafrnohalo_get_type( void ) -{ - static GType type = 0; - - if( !type ) { - static const GTypeInfo info = { - sizeof( VipsInterpolateYafrnohaloClass ), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) vips_interpolate_yafrnohalo_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof( VipsInterpolateYafrnohalo ), - 32, /* n_preallocs */ - (GInstanceInitFunc) vips_interpolate_yafrnohalo_init, - }; - - type = g_type_register_static( VIPS_TYPE_INTERPOLATE, - "VipsInterpolateYafrnohalo", &info, 0 ); - } - - return( type ); -} - -VipsInterpolate * -vips_interpolate_yafrnohalo_new( void ) -{ - return( VIPS_INTERPOLATE( g_object_new( - VIPS_TYPE_INTERPOLATE_YAFRNOHALO, NULL ) ) ); -} - -void -vips_interpolate_yafrnohalo_set_sharpening( - VipsInterpolateYafrnohalo *yafrnohalo, - double sharpening ) -{ - yafrnohalo->sharpening = sharpening; -} - -/* Convenience: return a static yafrnohalo you don't need to free. - */ -VipsInterpolate * -vips_interpolate_yafrnohalo_static( void ) -{ - static VipsInterpolate *interpolate = NULL; - - if( !interpolate ) - interpolate = vips_interpolate_yafrnohalo_new(); - - return( interpolate ); -} - - diff --git a/libsrc/mosaicing/yafrsmooth.cpp b/libsrc/mosaicing/yafrsmooth.cpp index 6c127168..188c9f2b 100644 --- a/libsrc/mosaicing/yafrsmooth.cpp +++ b/libsrc/mosaicing/yafrsmooth.cpp @@ -128,7 +128,79 @@ */ #define SMOOTH_SHARPENING_SCALE (0.453125f) -static VipsInterpolateClass *vips_interpolate_yafrsmooth_parent_class = NULL; +#define VIPS_TYPE_INTERPOLATE_YAFRSMOOTH \ + (vips_interpolate_yafrsmooth_get_type()) +#define VIPS_INTERPOLATE_YAFRSMOOTH( obj ) \ + (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ + VIPS_TYPE_INTERPOLATE_YAFRSMOOTH, VipsInterpolateYafrsmooth )) +#define VIPS_INTERPOLATE_YAFRSMOOTH_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_CAST( (klass), \ + VIPS_TYPE_INTERPOLATE_YAFRSMOOTH, VipsInterpolateYafrsmoothClass)) +#define VIPS_IS_INTERPOLATE_YAFRSMOOTH( obj ) \ + (G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_INTERPOLATE_YAFRSMOOTH )) +#define VIPS_IS_INTERPOLATE_YAFRSMOOTH_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_INTERPOLATE_YAFRSMOOTH )) +#define VIPS_INTERPOLATE_YAFRSMOOTH_GET_CLASS( obj ) \ + (G_TYPE_INSTANCE_GET_CLASS( (obj), \ + VIPS_TYPE_INTERPOLATE_YAFRSMOOTH, VipsInterpolateYafrsmoothClass )) + +typedef struct _VipsInterpolateYafrsmooth { + VipsInterpolate parent_object; + + /* "sharpening" is a continuous method parameter which is + * proportional to the amount of "diagonal straightening" which the + * nonlinear correction part of the method may add to the underlying + * linear scheme. You may also think of it as a sharpening + * parameter: higher values correspond to more sharpening, and + * negative values lead to strange looking effects. + * + * The default value is sharpening = 29/32 when the scheme being + * "straightened" is Catmull-Rom---as is the case here. This value + * fixes key pixel values near the diagonal boundary between two + * monochrome regions (the diagonal boundary pixel values being set + * to the halfway colour). + * + * If resampling seems to add unwanted texture artifacts, push + * sharpening toward 0. It is not generally not recommended to set + * sharpening to a value larger than 4. + * + * Sharpening is halved because the .5 which has to do with the + * relative coordinates of the evaluation points (which has to do + * with .5*rite_width etc) is folded into the constant to save + * flops. Consequently, the largest recommended value of + * sharpening_over_two is 2=4/2. + * + * In order to simplify interfacing with users, the parameter which + * should be set by the user is normalized so that user_sharpening = + * 1 when sharpening is equal to the recommended value. Consistently + * with the above discussion, values of user_sharpening between 0 + * and about 3.625 give good results. + */ + double sharpening; +} VipsInterpolateYafrsmooth; + +typedef struct _VipsInterpolateYafrsmoothClass { + VipsInterpolateClass parent_class; + + /* Precalculated interpolation matricies. int (used for pel sizes up + * to short), and double (for all others). We go to scale + 1, so + * we can round-to-nearest safely. + */ + + /* We could keep a large set of 2d 4x4 matricies, but this actually + * works out slower, since for many resizes the thing will no longer + * fit in L1. + */ + int matrixi[VIPS_TRANSFORM_SCALE + 1][4]; + double matrixf[VIPS_TRANSFORM_SCALE + 1][4]; +} VipsInterpolateYafrsmoothClass; + +/* We need C linkage for this. + */ +extern "C" { +G_DEFINE_TYPE( VipsInterpolateYafrsmooth, vips_interpolate_yafrsmooth, + VIPS_TYPE_INTERPOLATE ); +} /* T is the type of pixels we are computing, D is a type large enough to hold * (Ta - Tb) ** 2. @@ -668,11 +740,12 @@ vips_interpolate_yafrsmooth_interpolate( VipsInterpolate *interpolate, static void vips_interpolate_yafrsmooth_class_init( VipsInterpolateYafrsmoothClass *iclass ) { + VipsObjectClass *object_class = VIPS_OBJECT_CLASS( iclass ); VipsInterpolateClass *interpolate_class = VIPS_INTERPOLATE_CLASS( iclass ); - vips_interpolate_yafrsmooth_parent_class = - VIPS_INTERPOLATE_CLASS( g_type_class_peek_parent( iclass ) ); + object_class->nickname = "yafrsmooth"; + object_class->description = _( "YAFR smooth interpolation" ); interpolate_class->interpolate = vips_interpolate_yafrsmooth_interpolate; @@ -701,59 +774,3 @@ vips_interpolate_yafrsmooth_init( VipsInterpolateYafrsmooth *yafrsmooth ) yafrsmooth->sharpening = 1.0; } - -GType -vips_interpolate_yafrsmooth_get_type() -{ - static GType type = 0; - - if( !type ) { - static const GTypeInfo info = { - sizeof( VipsInterpolateYafrsmoothClass ), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) vips_interpolate_yafrsmooth_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof( VipsInterpolateYafrsmooth ), - 32, /* n_preallocs */ - (GInstanceInitFunc) vips_interpolate_yafrsmooth_init, - }; - - type = g_type_register_static( VIPS_TYPE_INTERPOLATE, - "VipsInterpolateYafrsmooth", &info, - (GTypeFlags) 0 ); - } - - return( type ); -} - -VipsInterpolate * -vips_interpolate_yafrsmooth_new( void ) -{ - return( VIPS_INTERPOLATE( g_object_new( - VIPS_TYPE_INTERPOLATE_YAFRSMOOTH, NULL ) ) ); -} - -void -vips_interpolate_yafrsmooth_set_sharpening( - VipsInterpolateYafrsmooth *yafrsmooth, - double sharpening ) -{ - yafrsmooth->sharpening = sharpening; -} - -/* Convenience: return a static yafrsmooth you don't need to free. - */ -VipsInterpolate * -vips_interpolate_yafrsmooth_static( void ) -{ - static VipsInterpolate *interpolate = NULL; - - if( !interpolate ) - interpolate = vips_interpolate_yafrsmooth_new(); - - return( interpolate ); -} - - diff --git a/src/iofuncs/vips.c b/src/iofuncs/vips.c index 5d29502a..e3c68c9e 100644 --- a/src/iofuncs/vips.c +++ b/src/iofuncs/vips.c @@ -26,6 +26,8 @@ * - add input *VEC arg types to C++ binding * 17/8/08 * - add --list formats + * 29/11/08 + * - add --list interpolators */ /* @@ -164,33 +166,43 @@ list_function( im_function *func ) } static void * -list_format( VipsFormatClass *format ) +list_format( VipsFormatClass *class ) { const char **p; printf( "%-20s - ", - VIPS_OBJECT_CLASS( format )->description ); + VIPS_OBJECT_CLASS( class )->description ); printf( "(" ); - for( p = format->suffs; *p; p++ ) { + for( p = class->suffs; *p; p++ ) { printf( "%s", *p ); if( p[1] ) printf( ", " ); } printf( ") " ); - if( format->is_a ) + if( class->is_a ) printf( "is_a " ); - if( format->header ) + if( class->header ) printf( "header " ); - if( format->load ) + if( class->load ) printf( "load " ); - if( format->save ) + if( class->save ) printf( "save " ); - if( format->get_flags ) + if( class->get_flags ) printf( "get_flags " ); printf( "\n" ); - + + return( NULL ); +} + +static void * +list_interpolate( VipsInterpolateClass *class ) +{ + printf( "%-20s - %s\n", + VIPS_OBJECT_CLASS( class )->nickname, + VIPS_OBJECT_CLASS( class )->description ); + return( NULL ); } @@ -201,6 +213,11 @@ print_list( const char *name ) im_map_packages( (VSListMap2Fn) list_package, NULL ); else if( strcmp( name, "formats" ) == 0 ) vips_format_map( (VSListMap2Fn) list_format, NULL, NULL ); + else if( strcmp( name, "interpolators" ) == 0 ) { + vips_class_map_concrete_all( + g_type_from_name( "VipsInterpolate" ), + (VipsClassMap) list_interpolate, NULL ); + } else { if( map_name( name, list_function ) ) error_exit( "unknown package \"%s\"", name );