diff --git a/ChangeLog b/ChangeLog index 980152d5..c0aa28e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,7 @@ - cleanups after yafr hacking - added affinei_all - don't set im_error() on failed callback +- moved im_format_t to VipsFormat, now sits over VipsObject 11/9/08 started 7.16.3 - oop typo in manpage for im_project() diff --git a/TODO b/TODO index 75ad9f5d..3ebdea83 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,25 @@ +- format/ now uses VipsFormat + + im_format docs need redoing + + nip2 needs revising + + user G_DEFINE_ABSTRACT_TYPE for VipsObject + +- we have + + VipsFormatFlags + VIPS_FORMAT_FLAG_PARTIAL + + is this right? should we use singular or plural? + + + + - 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 diff --git a/include/vips/format.h b/include/vips/format.h index 42423c79..6f45bac8 100644 --- a/include/vips/format.h +++ b/include/vips/format.h @@ -1,4 +1,5 @@ -/* Suppprted image formats. +/* Abstract base type for supported image formats. Subclass this to add a new + * format. */ /* @@ -34,56 +35,85 @@ extern "C" { #endif /*__cplusplus*/ +#define VIPS_TYPE_FORMAT (vips_format_get_type()) +#define VIPS_FORMAT( obj ) \ + (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ + VIPS_TYPE_FORMAT, VipsFormat )) +#define VIPS_FORMAT_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_CAST( (klass), \ + VIPS_TYPE_FORMAT, VipsFormatClass)) +#define VIPS_IS_FORMAT( obj ) \ + (G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_FORMAT )) +#define VIPS_IS_FORMAT_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_FORMAT )) +#define VIPS_FORMAT_GET_CLASS( obj ) \ + (G_TYPE_INSTANCE_GET_CLASS( (obj), \ + VIPS_TYPE_FORMAT, VipsFormatClass )) + /* Image file properties. OR these together to get the result of * im_format_flags_fn(). 0 is default. */ typedef enum { - IM_FORMAT_FLAG_NONE = 0,/* No flags set */ - IM_FORMAT_FLAG_PARTIAL = 1/* Lazy read OK (eg. tiled tiff) */ -} im_format_flags; + VIPS_FORMAT_FLAG_NONE = 0, /* No flags set */ + VIPS_FORMAT_FLAG_PARTIAL = 1 /* Lazy read OK (eg. tiled tiff) */ +} VipsFormatFlags; /* Function protos for formats. */ -typedef gboolean (*im_format_is_a_fn)( const char * ); -typedef int (*im_format_header_fn)( const char *, IMAGE * ); -typedef int (*im_format_load_fn)( const char *, IMAGE * ); -typedef int (*im_format_save_fn)( IMAGE *, const char * ); -typedef im_format_flags (*im_format_flags_fn)( const char * ); -/* A VIPS image format. - */ -typedef struct im__format_t { - const char *name; /* Format name, same as mime */ - const char *name_user; /* I18n'd name for users */ - int priority; /* Keep formats sorted by this, default 0 */ - const char **suffs; /* Allowed suffixes */ - im_format_is_a_fn is_a; /* Filename is in format */ - im_format_header_fn header;/* Load header only from filename */ - im_format_load_fn load; /* Load image from filename */ - im_format_save_fn save; /* Save image to filename */ - im_format_flags_fn flags;/* Get flags for filename */ -} im_format_t; +typedef struct _VipsFormat { + VipsObject parent_object; -/* Register/unregister formats. - */ -im_format_t *im_format_register( - const char *name, const char *name_user, const char **suffs, - im_format_is_a_fn is_a, im_format_header_fn header, - im_format_load_fn load, im_format_save_fn save, - im_format_flags_fn flags ); -void im_format_set_priority( im_format_t *format, int priority ); -void im_format_unregister( im_format_t *format ); +} VipsFormat; -/* Map over and find formats. - */ -void *im_format_map( VSListMap2Fn fn, void *a, void *b ); -im_format_t *im_format_for_file( const char *filename ); -im_format_t *im_format_for_name( const char *filename ); +typedef struct _VipsFormatClass { + VipsObjectClass parent_class; -/* Write an image convenience function. + /* Is a file in this format. + */ + gboolean (*is_a)( const char * ); + + /* Read just the header into the IMAGE. + */ + int (*header)( const char *, IMAGE * ); + + /* Load the whole image. + */ + int (*load)( const char *, IMAGE * ); + + /* Write the IMAGE to the file in this format. + */ + int (*save)( IMAGE *, const char * ); + + /* Get the flags for this file in this format. + */ + VipsFormatFlags (*get_flags)( const char * ); + + /* Loop over formats in this order, default 0. We need this because + * some formats can be read by several loaders (eg. tiff can be read + * by the libMagick loader as well as by the tiff loader), and we want + * to make sure the better loader comes first. + */ + int priority; + + /* Null-terminated list of allowed suffixes, eg. ".tif", ".tiff". + */ + const char **suffs; +} VipsFormatClass; + +GType vips_format_get_type( void ); + +/* Map over and find formats. This uses type introspection to loop over + * subclasses of VipsFormat. */ -int im_format_read( const char *name, IMAGE *out ); -int im_format_write( IMAGE *im, const char *name ); +void *vips_format_map( VSListMap2Fn fn, void *a, void *b ); +VipsFormatClass *vips_format_for_file( const char *filename ); +VipsFormatClass *vips_format_for_name( const char *filename ); + +/* Read/write an image convenience functions. + */ +int vips_format_read( const char *name, IMAGE *out ); +int vips_format_write( IMAGE *im, const char *name ); #ifdef __cplusplus } diff --git a/include/vips/util.h b/include/vips/util.h index 2002b577..d0e6a11a 100644 --- a/include/vips/util.h +++ b/include/vips/util.h @@ -300,11 +300,13 @@ 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 ); +typedef void *(*VipsTypeMap)( GType, void * ); +typedef void *(*VipsTypeMap2)( GType, void *, void * ); +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 ); +GType vips_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 ); diff --git a/libsrc/format/format.c b/libsrc/format/format.c index bba63500..a47e406f 100644 --- a/libsrc/format/format.c +++ b/libsrc/format/format.c @@ -41,71 +41,60 @@ #include #endif /*WITH_DMALLOC*/ -/* List of loaded formats. +/* To iterate over supported formats, we build a temp list of subclasses of + * VipsFormat, sort by priority, iterate, and free. */ -static GSList *format_list = NULL; + +static void * +format_add_class( VipsFormatClass *format, GSList **formats ) +{ + /* Append so we don't reverse the list of formats. + */ + *formats = g_slist_append( *formats, format ); + + return( NULL ); +} static gint -format_compare( im_format_t *a, im_format_t *b ) +format_compare( VipsFormatClass *a, VipsFormatClass *b ) { return( b->priority - a->priority ); } -/* Sort the format list after a change. +void * +vips_format_map( VSListMap2Fn fn, void *a, void *b ) +{ + GSList *formats; + void *result; + + formats = NULL; + (void) vips_class_map_concrete_all( g_type_from_name( "VipsFormat" ), + (VipsClassMap) format_add_class, (void *) &formats ); + + formats = g_slist_sort( formats, (GCompareFunc) format_compare ); + result = im_slist_map2( formats, fn, a, b ); + g_slist_free( formats ); + + return( result ); +} + +/* Abstract base class for image formats. */ + static void -format_sort( void ) +vips_format_class_init( VipsFormatClass *class ) { - format_list = g_slist_sort( format_list, - (GCompareFunc) format_compare ); } -/* Register/unregister formats. +static void +vips_format_init( VipsFormat *object ) +{ +} + +G_DEFINE_ABSTRACT_TYPE( VipsFormat, vips_format, VIPS_TYPE_OBJECT ); + +/* VIPS format class. */ -im_format_t * -im_format_register( - const char *name, const char *name_user, const char **suffs, - im_format_is_a_fn is_a, im_format_header_fn header, - im_format_load_fn load, im_format_save_fn save, - im_format_flags_fn flags ) -{ - im_format_t *format; - - if( !(format = IM_NEW( NULL, im_format_t )) ) - return( NULL ); - format->name = name; - format->name_user = name_user; - format->priority = 0; - format->suffs = suffs; - format->is_a = is_a; - format->header = header; - format->load = load; - format->save = save; - format->flags = flags; - - /* Append, so we keep the ordering where possible. - */ - format_list = g_slist_append( format_list, format ); - format_sort(); - - return( format ); -} - -void -im_format_set_priority( im_format_t *format, int priority ) -{ - g_assert( format ); - - format->priority = priority; - format_sort(); -} - -void -im_format_unregister( im_format_t *format ) -{ - format_list = g_slist_remove( format_list, format ); - IM_FREE( format ); -} static const char *vips_suffs[] = { ".v", NULL }; @@ -133,60 +122,80 @@ vips2file( IMAGE *im, const char *filename ) return( 0 ); } -static im_format_flags +static VipsFormatFlags vips_flags( const char *filename ) { - return( IM_FORMAT_FLAG_PARTIAL ); + return( VIPS_FORMAT_FLAG_PARTIAL ); } +/* Vips format adds no new members. + */ +typedef VipsFormat VipsFormatVips; +typedef VipsFormatClass VipsFormatVipsClass; + +static void +vips_format_vips_class_init( VipsFormatVipsClass *class ) +{ + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsFormatClass *format_class = (VipsFormatClass *) class; + + object_class->nickname = "vips"; + object_class->description = _( "VIPS" ); + + format_class->is_a = im_isvips; + format_class->header = file2vips; + format_class->load = file2vips; + format_class->save = vips2file; + format_class->get_flags = vips_flags; + format_class->suffs = vips_suffs; +} + +static void +vips_format_vips_init( VipsFormatVips *object ) +{ +} + +G_DEFINE_TYPE( VipsFormatVips, vips_format_vips, VIPS_TYPE_FORMAT ); + /* Called on startup: register the base vips formats. */ void im__format_init( void ) { - im_format_register( - "vips", /* internal name */ - _( "VIPS" ), /* i18n'd visible name */ - vips_suffs, /* Allowed suffixes */ - im_isvips, /* is_a */ - file2vips, /* Load header only */ - file2vips, /* Load */ - vips2file, /* Save */ - vips_flags /* Flags */ - ); + extern GType vips_format_csv_get_type(); + extern GType vips_format_ppm_get_type(); + extern GType vips_format_analyze_get_type(); + vips_format_vips_get_type(); #ifdef HAVE_JPEG - im__jpeg_register(); + extern GType vips_format_jpeg_get_type(); + vips_format_jpeg_get_type(); #endif /*HAVE_JPEG*/ #ifdef HAVE_PNG - im__png_register(); + extern GType vips_format_png_get_type(); + vips_format_png_get_type(); #endif /*HAVE_PNG*/ - im__csv_register(); - im__ppm_register(); - im__analyze_register(); + vips_format_csv_get_type(); + vips_format_ppm_get_type(); + vips_format_analyze_get_type(); #ifdef HAVE_OPENEXR - im__exr_register(); + extern GType vips_format_exr_get_type(); + vips_format_exr_get_type(); #endif /*HAVE_OPENEXR*/ #ifdef HAVE_MAGICK - im__magick_register(); + extern GType vips_format_magick_get_type(); + vips_format_magick_get_type(); #endif /*HAVE_MAGICK*/ #ifdef HAVE_TIFF - im__tiff_register(); + extern GType vips_format_tiff_get_type(); + vips_format_tiff_get_type(); #endif /*HAVE_TIFF*/ } -/* Map a function over all formats. - */ -void * -im_format_map( VSListMap2Fn fn, void *a, void *b ) -{ - return( im_slist_map2( format_list, fn, a, b ) ); -} - /* Can this format open this file? */ static void * -format_for_file_sub( im_format_t *format, +format_for_file_sub( VipsFormatClass *format, const char *name, const char *filename ) { if( format->is_a ) { @@ -199,12 +208,12 @@ format_for_file_sub( im_format_t *format, return( NULL ); } -im_format_t * -im_format_for_file( const char *name ) +VipsFormatClass * +vips_format_for_file( const char *name ) { char filename[FILENAME_MAX]; char options[FILENAME_MAX]; - im_format_t *format; + VipsFormatClass *format; /* Break any options off the name ... eg. "fred.tif:jpeg,tile" * etc. @@ -212,15 +221,15 @@ im_format_for_file( const char *name ) im_filename_split( name, filename, options ); if( !im_existsf( "%s", filename ) ) { - im_error( "im_format_for_file", + im_error( "vips_format_for_file", _( "\"%s\" is not readable" ), filename ); return( NULL ); } - if( !(format = (im_format_t *) im_format_map( + if( !(format = (VipsFormatClass *) vips_format_map( (VSListMap2Fn) format_for_file_sub, (void *) name, (void *) filename )) ) { - im_error( "im_format_for_file", + im_error( "vips_format_for_file", _( "\"%s\" is not in a supported format" ), filename ); return( NULL ); } @@ -232,7 +241,7 @@ im_format_for_file( const char *name ) * method. */ static void * -format_for_name_sub( im_format_t *format, const char *name ) +format_for_name_sub( VipsFormatClass *format, const char *name ) { if( format->save && im_filename_suffix_match( name, format->suffs ) ) @@ -241,17 +250,17 @@ format_for_name_sub( im_format_t *format, const char *name ) return( NULL ); } -im_format_t * -im_format_for_name( const char *name ) +VipsFormatClass * +vips_format_for_name( const char *name ) { - im_format_t *format; + VipsFormatClass *format; - if( !(format = (im_format_t *) im_format_map( + if( !(format = (VipsFormatClass *) vips_format_map( (VSListMap2Fn) format_for_name_sub, (void *) name, NULL )) ) { char suffix[FILENAME_MAX]; im_filename_suffix( name, suffix ); - im_error( "im_format_for_name", + im_error( "vips_format_for_name", _( "\"%s\" is not a supported image format." ), suffix ); @@ -262,11 +271,11 @@ im_format_for_name( const char *name ) } int -im_format_read( const char *name, IMAGE *out ) +vips_format_read( const char *name, IMAGE *out ) { - im_format_t *format; + VipsFormatClass *format; - if( !(format = im_format_for_file( name )) || + if( !(format = vips_format_for_file( name )) || format->load( name, out ) ) return( -1 ); @@ -274,11 +283,11 @@ im_format_read( const char *name, IMAGE *out ) } int -im_format_write( IMAGE *im, const char *name ) +vips_format_write( IMAGE *im, const char *name ) { - im_format_t *format; + VipsFormatClass *format; - if( !(format = im_format_for_name( name )) || + if( !(format = vips_format_for_name( name )) || format->save( im, name ) ) return( -1 ); diff --git a/libsrc/format/im_analyze2vips.c b/libsrc/format/im_analyze2vips.c index 4c19367b..666f1a35 100644 --- a/libsrc/format/im_analyze2vips.c +++ b/libsrc/format/im_analyze2vips.c @@ -583,23 +583,37 @@ im_analyze2vips( const char *filename, IMAGE *out ) static const char *analyze_suffs[] = { ".img", ".hdr", NULL }; -static im_format_flags +static VipsFormatFlags analyze_flags( const char *filename ) { - return( IM_FORMAT_FLAG_PARTIAL ); + return( VIPS_FORMAT_FLAG_PARTIAL ); } -void -im__analyze_register( void ) +/* analyze format adds no new members. + */ +typedef VipsFormat VipsFormatAnalyze; +typedef VipsFormatClass VipsFormatAnalyzeClass; + +static void +vips_format_analyze_class_init( VipsFormatAnalyzeClass *class ) { - im_format_register( - "analyze", /* internal name */ - _( "Analyze 6.0" ), /* i18n'd visible name */ - analyze_suffs, /* Allowed suffixes */ - isanalyze, /* is_a */ - analyze2vips_header, /* Load header only */ - im_analyze2vips, /* Load */ - NULL, /* Save */ - analyze_flags /* Flags */ - ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsFormatClass *format_class = (VipsFormatClass *) class; + + object_class->nickname = "analyze"; + object_class->description = _( "Analyze 6.0" ); + + format_class->is_a = isanalyze; + format_class->header = analyze2vips_header; + format_class->load = im_analyze2vips; + format_class->get_flags = analyze_flags; + format_class->suffs = analyze_suffs; } + +static void +vips_format_analyze_init( VipsFormatAnalyze *object ) +{ +} + +G_DEFINE_TYPE( VipsFormatAnalyze, vips_format_analyze, VIPS_TYPE_FORMAT ); + diff --git a/libsrc/format/im_csv2vips.c b/libsrc/format/im_csv2vips.c index 1383a71a..8e8d417d 100644 --- a/libsrc/format/im_csv2vips.c +++ b/libsrc/format/im_csv2vips.c @@ -318,17 +318,29 @@ csv2vips_header( const char *filename, IMAGE *out ) static const char *csv_suffs[] = { ".csv", NULL }; -void -im__csv_register( void ) +/* csv format adds no new members. + */ +typedef VipsFormat VipsFormatCsv; +typedef VipsFormatClass VipsFormatCsvClass; + +static void +vips_format_csv_class_init( VipsFormatCsvClass *class ) { - im_format_register( - "csv", /* internal name */ - _( "CSV" ), /* i18n'd visible name */ - csv_suffs, /* Allowed suffixes */ - NULL, /* is_a */ - csv2vips_header, /* Load header only */ - im_csv2vips, /* Load */ - im_vips2csv, /* Save */ - NULL /* Flags */ - ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsFormatClass *format_class = (VipsFormatClass *) class; + + object_class->nickname = "csv"; + object_class->description = _( "CSV" ); + + format_class->header = csv2vips_header; + format_class->load = im_csv2vips; + format_class->save = im_vips2csv; + format_class->suffs = csv_suffs; } + +static void +vips_format_csv_init( VipsFormatCsv *object ) +{ +} + +G_DEFINE_TYPE( VipsFormatCsv, vips_format_csv, VIPS_TYPE_FORMAT ); diff --git a/libsrc/format/im_exr2vips.c b/libsrc/format/im_exr2vips.c index 613161e6..84e505e3 100644 --- a/libsrc/format/im_exr2vips.c +++ b/libsrc/format/im_exr2vips.c @@ -449,31 +449,44 @@ isexr( const char *filename ) static const char *exr_suffs[] = { ".exr", NULL }; -static im_format_flags +static VipsFormatFlags exr_flags( const char *filename ) { - im_format_flags flags; + VipsFormatFlags flags; flags = 0; if( isexrtiled( filename ) ) - flags |= IM_FORMAT_FLAG_PARTIAL; + flags |= VIPS_FORMAT_FLAG_PARTIAL; return( flags ); } -void -im__exr_register( void ) +/* exr format adds no new members. + */ +typedef VipsFormat VipsFormatExr; +typedef VipsFormatClass VipsFormatExrClass; + +static void +vips_format_exr_class_init( VipsFormatExrClass *class ) { - im_format_register( - "exr", /* internal name */ - _( "OpenEXR" ), /* i18n'd visible name */ - exr_suffs, /* Allowed suffixes */ - isexr, /* is_a */ - exr2vips_header, /* Load header only */ - im_exr2vips, /* Load */ - NULL, /* Save */ - exr_flags /* Flags */ - ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsFormatClass *format_class = (VipsFormatClass *) class; + + object_class->nickname = "exr"; + object_class->description = _( "OpenEXR" ); + + format_class->is_a = isexr; + format_class->header = exr2vips_header; + format_class->load = im_exr2vips; + format_class->get_flags = exr_flags; + format_class->suffs = exr_suffs; } +static void +vips_format_exr_init( VipsFormatExr *object ) +{ +} + +G_DEFINE_TYPE( VipsFormatExr, vips_format_exr, VIPS_TYPE_FORMAT ); + #endif /*HAVE_OPENEXR*/ diff --git a/libsrc/format/im_jpeg2vips.c b/libsrc/format/im_jpeg2vips.c index 36e98753..f717cbd3 100644 --- a/libsrc/format/im_jpeg2vips.c +++ b/libsrc/format/im_jpeg2vips.c @@ -720,19 +720,32 @@ jpeg2vips_header( const char *name, IMAGE *out ) static const char *jpeg_suffs[] = { ".jpg", ".jpeg", ".jpe", NULL }; -void -im__jpeg_register( void ) +/* jpeg format adds no new members. + */ +typedef VipsFormat VipsFormatJpeg; +typedef VipsFormatClass VipsFormatJpegClass; + +static void +vips_format_jpeg_class_init( VipsFormatJpegClass *class ) { - im_format_register( - "jpeg", /* internal name */ - _( "JPEG" ), /* i18n'd visible name */ - jpeg_suffs, /* Allowed suffixes */ - isjpeg, /* is_a */ - jpeg2vips_header, /* Load header only */ - im_jpeg2vips, /* Load */ - im_vips2jpeg, /* Save */ - NULL /* Flags */ - ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsFormatClass *format_class = (VipsFormatClass *) class; + + object_class->nickname = "jpeg"; + object_class->description = _( "JPEG" ); + + format_class->is_a = isjpeg; + format_class->header = jpeg2vips_header; + format_class->load = im_jpeg2vips; + format_class->save = im_vips2jpeg; + format_class->suffs = jpeg_suffs; } +static void +vips_format_jpeg_init( VipsFormatJpeg *object ) +{ +} + +G_DEFINE_TYPE( VipsFormatJpeg, vips_format_jpeg, VIPS_TYPE_FORMAT ); + #endif /*HAVE_JPEG*/ diff --git a/libsrc/format/im_magick2vips.c b/libsrc/format/im_magick2vips.c index cf39d62a..90e3db4b 100644 --- a/libsrc/format/im_magick2vips.c +++ b/libsrc/format/im_magick2vips.c @@ -657,22 +657,36 @@ ismagick( const char *filename ) static const char *magick_suffs[] = { NULL }; -void -im__magick_register( void ) -{ - im_format_t *format; +/* magick format adds no new members. + */ +typedef VipsFormat VipsFormatMagick; +typedef VipsFormatClass VipsFormatMagickClass; - format = im_format_register( - "magick", /* internal name */ - _( "libMagick-supported" ),/* i18n'd visible name */ - magick_suffs, /* Allowed suffixes */ - ismagick, /* is_a */ - magick2vips_header, /* Load header only */ - im_magick2vips, /* Load */ - NULL, /* Save */ - NULL /* Flags */ - ); - im_format_set_priority( format, -1000 ); +static void +vips_format_magick_class_init( VipsFormatMagickClass *class ) +{ + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsFormatClass *format_class = (VipsFormatClass *) class; + + object_class->nickname = "magick"; + object_class->description = _( "libMagick-supported" ); + + format_class->is_a = ismagick; + format_class->header = magick2vips_header; + format_class->load = im_magick2vips; + format_class->suffs = magick_suffs; + + /* This can be very slow :-( Use our own jpeg/tiff/png etc. loaders in + * preference if we can. + */ + format_class->priority = -1000; } +static void +vips_format_magick_init( VipsFormatMagick *object ) +{ +} + +G_DEFINE_TYPE( VipsFormatMagick, vips_format_magick, VIPS_TYPE_FORMAT ); + #endif /*HAVE_MAGICK*/ diff --git a/libsrc/format/im_png2vips.c b/libsrc/format/im_png2vips.c index ff72dfb7..6428883d 100644 --- a/libsrc/format/im_png2vips.c +++ b/libsrc/format/im_png2vips.c @@ -383,19 +383,32 @@ ispng( const char *filename ) static const char *png_suffs[] = { ".png", NULL }; -void -im__png_register( void ) +/* png format adds no new members. + */ +typedef VipsFormat VipsFormatPng; +typedef VipsFormatClass VipsFormatPngClass; + +static void +vips_format_png_class_init( VipsFormatPngClass *class ) { - im_format_register( - "png", /* internal name */ - _( "PNG" ), /* i18n'd visible name */ - png_suffs, /* Allowed suffixes */ - ispng, /* is_a */ - png2vips_header, /* Load header only */ - im_png2vips, /* Load */ - im_vips2png, /* Save */ - NULL /* Flags */ - ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsFormatClass *format_class = (VipsFormatClass *) class; + + object_class->nickname = "png"; + object_class->description = _( "PNG" ); + + format_class->is_a = ispng; + format_class->header = png2vips_header; + format_class->load = im_png2vips; + format_class->save = im_vips2png; + format_class->suffs = png_suffs; } +static void +vips_format_png_init( VipsFormatPng *object ) +{ +} + +G_DEFINE_TYPE( VipsFormatPng, vips_format_png, VIPS_TYPE_FORMAT ); + #endif /*HAVE_PNG*/ diff --git a/libsrc/format/im_ppm2vips.c b/libsrc/format/im_ppm2vips.c index c2ef0569..cb864e62 100644 --- a/libsrc/format/im_ppm2vips.c +++ b/libsrc/format/im_ppm2vips.c @@ -489,31 +489,46 @@ isppm( const char *filename ) /* ppm flags function. */ -static im_format_flags +static VipsFormatFlags ppm_flags( const char *filename ) { - im_format_flags flags; + VipsFormatFlags flags; flags = 0; if( isppmmmap( filename ) ) - flags |= IM_FORMAT_FLAG_PARTIAL; + flags |= VIPS_FORMAT_FLAG_PARTIAL; return( flags ); } static const char *ppm_suffs[] = { ".ppm", ".pgm", ".pbm", NULL }; -void -im__ppm_register( void ) +/* ppm format adds no new members. + */ +typedef VipsFormat VipsFormatPpm; +typedef VipsFormatClass VipsFormatPpmClass; + +static void +vips_format_ppm_class_init( VipsFormatPpmClass *class ) { - im_format_register( - "ppm", /* internal name */ - _( "PPM/PBM/PNM" ), /* i18n'd visible name */ - ppm_suffs, /* Allowed suffixes */ - isppm, /* is_a */ - ppm2vips_header, /* Load header only */ - im_ppm2vips, /* Load */ - im_vips2ppm, /* Save */ - ppm_flags /* Flags */ - ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsFormatClass *format_class = (VipsFormatClass *) class; + + object_class->nickname = "ppm"; + object_class->description = _( "PPM/PBM/PNM" ); + + format_class->is_a = isppm; + format_class->header = ppm2vips_header; + format_class->load = im_ppm2vips; + format_class->save = im_vips2ppm; + format_class->get_flags = ppm_flags; + format_class->suffs = ppm_suffs; } + +static void +vips_format_ppm_init( VipsFormatPpm *object ) +{ +} + +G_DEFINE_TYPE( VipsFormatPpm, vips_format_ppm, VIPS_TYPE_FORMAT ); + diff --git a/libsrc/format/im_tiff2vips.c b/libsrc/format/im_tiff2vips.c index 564f4155..3cd90206 100644 --- a/libsrc/format/im_tiff2vips.c +++ b/libsrc/format/im_tiff2vips.c @@ -1538,33 +1538,47 @@ istifftiled( const char *filename ) /* TIFF flags function. */ -static im_format_flags +static VipsFormatFlags tiff_flags( const char *filename ) { - im_format_flags flags; + VipsFormatFlags flags; flags = 0; if( istifftiled( filename ) ) - flags |= IM_FORMAT_FLAG_PARTIAL; + flags |= VIPS_FORMAT_FLAG_PARTIAL; return( flags ); } static const char *tiff_suffs[] = { ".tif", ".tiff", NULL }; -void -im__tiff_register( void ) +/* tiff format adds no new members. + */ +typedef VipsFormat VipsFormatTiff; +typedef VipsFormatClass VipsFormatTiffClass; + +static void +vips_format_tiff_class_init( VipsFormatTiffClass *class ) { - im_format_register( - "tiff", /* internal name */ - _( "TIFF" ), /* i18n'd visible name */ - tiff_suffs, /* Allowed suffixes */ - istiff, /* is_a */ - tiff2vips_header, /* Load header only */ - im_tiff2vips, /* Load */ - im_vips2tiff, /* Save */ - tiff_flags /* Flags */ - ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsFormatClass *format_class = (VipsFormatClass *) class; + + object_class->nickname = "tiff"; + object_class->description = _( "TIFF" ); + + format_class->is_a = istiff; + format_class->header = tiff2vips_header; + format_class->load = im_tiff2vips; + format_class->save = im_vips2tiff; + format_class->get_flags = tiff_flags; + format_class->suffs = tiff_suffs; } +static void +vips_format_tiff_init( VipsFormatTiff *object ) +{ +} + +G_DEFINE_TYPE( VipsFormatTiff, vips_format_tiff, VIPS_TYPE_FORMAT ); + #endif /*HAVE_TIFF*/ diff --git a/libsrc/iofuncs/im_open.c b/libsrc/iofuncs/im_open.c index abf19515..3cd0da81 100644 --- a/libsrc/iofuncs/im_open.c +++ b/libsrc/iofuncs/im_open.c @@ -344,7 +344,7 @@ IMAGE * im_open( const char *filename, const char *mode ) { IMAGE *im; - im_format_t *format; + VipsFormatClass *format; /* Pass in a nonsense name for argv0 ... this init world is only here * for old programs which are missing an im_init_world() call. We must @@ -370,8 +370,9 @@ im_open( const char *filename, const char *mode ) switch( mode[0] ) { case 'r': - if( (format = im_format_for_file( filename )) ) { - if( strcmp( format->name, "vips" ) == 0 ) { + if( (format = vips_format_for_file( filename )) ) { + if( strcmp( VIPS_OBJECT_CLASS( format )->nickname, + "vips" ) == 0 ) { if( !(im = im_open_vips( filename )) ) return( NULL ); } @@ -388,8 +389,9 @@ im_open( const char *filename, const char *mode ) break; case 'w': - if( (format = im_format_for_name( filename )) ) { - if( strcmp( format->name, "vips" ) == 0 ) + if( (format = vips_format_for_name( filename )) ) { + if( strcmp( VIPS_OBJECT_CLASS( format )->nickname, + "vips" ) == 0 ) im = im_openout( filename ); else { if( !(im = im_open( "im_open:lw:1", "p" )) ) diff --git a/libsrc/iofuncs/util.c b/libsrc/iofuncs/util.c index 87a8a1a4..308df164 100644 --- a/libsrc/iofuncs/util.c +++ b/libsrc/iofuncs/util.c @@ -245,7 +245,7 @@ im_hash_table_map( GHashTable *hash, VSListMap2Fn fn, void *a, void *b ) /* Map over all a type's children. */ void * -im_type_map( GType base, VTypeMap2Fn fn, void *a, void *b ) +vips_type_map( GType base, VipsTypeMap2 fn, void *a, void *b ) { GType *child; guint n_children; @@ -264,7 +264,7 @@ im_type_map( GType base, VTypeMap2Fn fn, void *a, void *b ) /* Loop over all the concrete subtypes of a base type. */ void * -im_type_map_concrete_all( GType base, VTypeMapFn fn, void *a ) +vips_type_map_concrete_all( GType base, VipsTypeMap fn, void *a ) { void *result; @@ -272,69 +272,83 @@ im_type_map_concrete_all( GType base, VTypeMapFn fn, void *a ) 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 ); + result = vips_type_map( base, + (VipsTypeMap2) vips_type_map_concrete_all, fn, a ); return( result ); } -static GType -test_name( GType type, const char *nickname ) +/* Loop over all the subclasses of a base type. + */ +void * +vips_class_map_concrete_all( GType type, VipsClassMap fn, void *a ) { - GTypeClass *class; - VipsObjectClass *vips_class; + void *result; - /* 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. + result = NULL; + if( !G_TYPE_IS_ABSTRACT( type ) ) { + GTypeClass *class; + + /* Does this class exist? Try to create if not. */ - if( !(class = g_type_class_ref( type )) ) - return( 0 ); + 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 )) ) { + im_error( "vips_class_map_concrete_all", + "%s", _( "unable to build class" ) ); + return( NULL ); + } - if( !VIPS_IS_OBJECT_CLASS( class ) ) - return( 0 ); - vips_class = VIPS_OBJECT_CLASS( class ); - if( strcasecmp( vips_class->nickname, nickname ) != 0 ) - return( 0 ); + result = fn( VIPS_OBJECT_CLASS( class ), a ); + } + if( !result ) + result = vips_type_map( type, + (VipsTypeMap2) vips_class_map_concrete_all, fn, a ); - return( type ); + return( result ); } -/* Find a GType ... search below base, return the first match on a nickname or +static void * +test_name( VipsObjectClass *class, const char *nickname ) +{ + if( strcasecmp( class->nickname, nickname ) != 0 ) + return( class ); + + /* Check the class name too, why not. + */ + if( strcasecmp( G_OBJECT_CLASS_NAME( class ), nickname ) != 0 ) + return( class ); + + return( NULL ); +} + +/* Find a class ... search below base, return the first match on a nickname or * a name. */ -GType -im_type_find( const char *basename, const char *nickname ) +VipsObjectClass * +vips_class_find( const char *basename, const char *nickname ) { + VipsObjectClass *class; GType base; - GType type; if( !(base = g_type_from_name( basename )) ) { - im_error( "im_type_find", - _( "base type \"%s\" not found" ), basename ); - return( 0 ); + im_error( "vips_class_find", + _( "base class \"%s\" not found" ), basename ); + return( NULL ); } - /* 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 ); + if( !(class = vips_class_map_concrete_all( base, + (VipsClassMap) test_name, (void *) nickname )) ) { + im_error( "vips_class_find", + _( "class \"%s\" not found" ), nickname ); + return( NULL ); + } - /* 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 ); + return( class ); } /* Like strncpy(), but always NULL-terminate, and don't pad with NULLs. diff --git a/man/im_format.3 b/man/VipsFormat..3 similarity index 100% rename from man/im_format.3 rename to man/VipsFormat..3 diff --git a/src/iofuncs/vips.c b/src/iofuncs/vips.c index 767e76c9..5d29502a 100644 --- a/src/iofuncs/vips.c +++ b/src/iofuncs/vips.c @@ -164,11 +164,12 @@ list_function( im_function *func ) } static void * -list_format( im_format_t *format ) +list_format( VipsFormatClass *format ) { const char **p; - printf( "%-20s - ", format->name_user ); + printf( "%-20s - ", + VIPS_OBJECT_CLASS( format )->description ); printf( "(" ); for( p = format->suffs; *p; p++ ) { @@ -186,8 +187,8 @@ list_format( im_format_t *format ) printf( "load " ); if( format->save ) printf( "save " ); - if( format->flags ) - printf( "flags " ); + if( format->get_flags ) + printf( "get_flags " ); printf( "\n" ); return( NULL ); @@ -199,7 +200,7 @@ print_list( const char *name ) if( strcmp( name, "packages" ) == 0 ) im_map_packages( (VSListMap2Fn) list_package, NULL ); else if( strcmp( name, "formats" ) == 0 ) - im_format_map( (VSListMap2Fn) list_format, NULL, NULL ); + vips_format_map( (VSListMap2Fn) list_format, NULL, NULL ); else { if( map_name( name, list_function ) ) error_exit( "unknown package \"%s\"", name );