From 1eb86415321c8ae0538197908f8c47e1578962c4 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 26 Oct 2021 17:52:34 +0100 Subject: [PATCH 01/20] tell buffer and target savers the file format Currently, buffer and target savers are not told the format they should write. This is usually OK (the JPEG saver already knows it should write JPEG), but some savers can write several formats, and these currently need an extra parameter. For example: ```ruby buf = x.write_to_buffer ".bmp", format: "bmp" ``` The first ".bmp" gets libvips to pick magicksave, the second `format:` param is necessary to tell magicksave to write BMP. This patch makes `vips_image_write_to_buffer` and `vips_image_write_to_target` add an extra image metadata item called `format_string` which contains the string used to pick the write format. Savers can use this extra field (if present) to pick a default save format. In this case, the magick saver will extract the "bmp". See: https://github.com/libvips/ruby-vips/issues/319 --- libvips/foreign/vips2magick.c | 19 +++++++++++++++- libvips/iofuncs/image.c | 42 ++++++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/libvips/foreign/vips2magick.c b/libvips/foreign/vips2magick.c index 21eedc8247..6f2e381f1e 100644 --- a/libvips/foreign/vips2magick.c +++ b/libvips/foreign/vips2magick.c @@ -102,6 +102,7 @@ vips_foreign_save_magick_dispose( GObject *gobject ) printf( "vips_foreign_save_magick_dispose: %p\n", gobject ); #endif /*DEBUG*/ + VIPS_FREE( magick->filename ); VIPS_FREE( magick->map ); VIPS_FREEF( DestroyImageList, magick->images ); VIPS_FREEF( DestroyImageInfo, magick->image_info ); @@ -274,6 +275,7 @@ vips_foreign_save_magick_build( VipsObject *object ) VipsForeignSaveMagick *magick = (VipsForeignSaveMagick *) object; VipsImage *im; + const char *format_string; #ifdef DEBUG printf( "vips_foreign_save_magick_build: %p\n", object ); @@ -349,6 +351,21 @@ vips_foreign_save_magick_build( VipsObject *object ) return( -1 ); } + /* There might be a format_string hint set on the image we are saving. + * Extract the filename component to imagemagick can guess the format. + */ + if( !vips_object_argument_isset( object, "format" ) && + !vips_image_get_string( im, + "format_string", &format_string ) ) { + char filename[VIPS_PATH_MAX]; + char option_string[VIPS_PATH_MAX]; + char *suffix; + + vips__filename_split8( format_string, filename, option_string ); + if( (suffix = strrchr( filename, '.' )) ) + VIPS_SETSTR( magick->format, suffix + 1 ); + } + if( magick->format ) { vips_strncpy( magick->image_info->magick, magick->format, MaxPathExtent ); @@ -512,7 +529,7 @@ vips_foreign_save_magick_file_build( VipsObject *object ) VipsForeignSaveMagick *magick = (VipsForeignSaveMagick *) object; VipsForeignSaveMagickFile *file = (VipsForeignSaveMagickFile *) object; - magick->filename = file->filename; + magick->filename = g_strdup( file->filename ); if( VIPS_OBJECT_CLASS( vips_foreign_save_magick_file_parent_class )-> build( object ) ) diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index c59f28a773..838f0a4b78 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -2713,6 +2713,18 @@ vips_image_write_to_file( VipsImage *image, const char *name, ... ) return( result ); } +static VipsImage * +vips_image_note_format( VipsImage *image, const char *format_string ) +{ + VipsImage *copy; + + if( vips_copy( image, ©, NULL ) ) + return( NULL ); + vips_image_set_string( copy, "format_string", format_string ); + + return( copy ); +} + /** * vips_image_write_to_buffer: (method) * @in: image to write @@ -2752,15 +2764,23 @@ vips_image_write_to_buffer( VipsImage *in, if( (operation_name = vips_foreign_find_save_target( filename )) ) { VipsTarget *target; + VipsImage *copy; if( !(target = vips_target_new_to_memory()) ) return( -1 ); + /* Note the suffix for loaders. + */ + if( !(copy = vips_image_note_format( in, suffix )) ) + return( -1 ); + va_start( ap, size ); result = vips_call_split_option_string( operation_name, - option_string, ap, in, target ); + option_string, ap, copy, target ); va_end( ap ); + VIPS_UNREF( copy ); + if( result ) { VIPS_UNREF( target ); return( -1 ); @@ -2771,12 +2791,20 @@ vips_image_write_to_buffer( VipsImage *in, } else if( (operation_name = vips_foreign_find_save_buffer( filename )) ) { + VipsImage *copy; + + /* Note the suffix for loaders. + */ + if( !(copy = vips_image_note_format( in, suffix )) ) + return( -1 ); va_start( ap, size ); result = vips_call_split_option_string( operation_name, - option_string, ap, in, &blob ); + option_string, ap, copy, &blob ); va_end( ap ); + VIPS_UNREF( copy ); + if( result ) return( -1 ); } @@ -2829,17 +2857,25 @@ vips_image_write_to_target( VipsImage *in, char option_string[VIPS_PATH_MAX]; const char *operation_name; va_list ap; + VipsImage *copy; int result; vips__filename_split8( suffix, filename, option_string ); if( !(operation_name = vips_foreign_find_save_target( filename )) ) return( -1 ); + /* Note the suffix for loaders. + */ + if( !(copy = vips_image_note_format( in, suffix )) ) + return( -1 ); + va_start( ap, target ); result = vips_call_split_option_string( operation_name, option_string, - ap, in, target ); + ap, copy, target ); va_end( ap ); + VIPS_UNREF( copy ); + if( result ) return( -1 ); From db7d320a9e0f130de6a4c6165eaad33b4131444f Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 27 Oct 2021 13:49:21 +0100 Subject: [PATCH 02/20] heifsave tests for format_string --- libvips/foreign/heifsave.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/libvips/foreign/heifsave.c b/libvips/foreign/heifsave.c index 686c9933ef..418bfef629 100644 --- a/libvips/foreign/heifsave.c +++ b/libvips/foreign/heifsave.c @@ -335,6 +335,7 @@ vips_foreign_save_heif_build( VipsObject *object ) VipsForeignSave *save = (VipsForeignSave *) object; VipsForeignSaveHeif *heif = (VipsForeignSaveHeif *) object; + const char *format_string; const char *filename; struct heif_error error; struct heif_writer writer; @@ -357,10 +358,31 @@ vips_foreign_save_heif_build( VipsObject *object ) if( vips_copy( save->ready, &heif->image, NULL ) ) return( -1 ); + /* Try various ways to get the filename. + */ + filename = NULL; + + /* There might be a format_string hint set on the image we are saving. + * Extract the filename component. + */ + if( !filename && + !vips_image_get_string( heif->image, + "format_string", &format_string ) ) { + char filename_buffer[VIPS_PATH_MAX]; + char option_string[VIPS_PATH_MAX]; + + vips__filename_split8( format_string, + filename_buffer, option_string ); + filename = filename_buffer; + } + + if( !filename ) + filename = vips_connection_filename( + VIPS_CONNECTION( heif->target ) ); + /* Compression defaults to VIPS_FOREIGN_HEIF_COMPRESSION_AV1 for .avif * suffix. */ - filename = vips_connection_filename( VIPS_CONNECTION( heif->target ) ); if( !vips_object_argument_isset( object, "compression" ) && filename && vips_iscasepostfix( filename, ".avif" ) ) From b6823db7e259fb3f81910ba480ef39457c43723a Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 27 Oct 2021 14:35:30 +0100 Subject: [PATCH 03/20] ppm looks for the file suffix --- libvips/foreign/heifsave.c | 23 ++++++--------- libvips/foreign/ppmsave.c | 59 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 15 deletions(-) diff --git a/libvips/foreign/heifsave.c b/libvips/foreign/heifsave.c index 418bfef629..11902cfb90 100644 --- a/libvips/foreign/heifsave.c +++ b/libvips/foreign/heifsave.c @@ -335,8 +335,10 @@ vips_foreign_save_heif_build( VipsObject *object ) VipsForeignSave *save = (VipsForeignSave *) object; VipsForeignSaveHeif *heif = (VipsForeignSaveHeif *) object; - const char *format_string; const char *filename; + const char *format_string; + char filename_buffer[VIPS_PATH_MAX]; + char option_string[VIPS_PATH_MAX]; struct heif_error error; struct heif_writer writer; char *chroma; @@ -361,30 +363,21 @@ vips_foreign_save_heif_build( VipsObject *object ) /* Try various ways to get the filename. */ filename = NULL; - - /* There might be a format_string hint set on the image we are saving. - * Extract the filename component. - */ - if( !filename && - !vips_image_get_string( heif->image, - "format_string", &format_string ) ) { - char filename_buffer[VIPS_PATH_MAX]; - char option_string[VIPS_PATH_MAX]; - + if( !vips_image_get_string( heif->image, + "format_string", &format_string ) ) { vips__filename_split8( format_string, filename_buffer, option_string ); filename = filename_buffer; } - - if( !filename ) + else filename = vips_connection_filename( VIPS_CONNECTION( heif->target ) ); /* Compression defaults to VIPS_FOREIGN_HEIF_COMPRESSION_AV1 for .avif * suffix. */ - if( !vips_object_argument_isset( object, "compression" ) && - filename && + if( filename && + !vips_object_argument_isset( object, "compression" ) && vips_iscasepostfix( filename, ".avif" ) ) heif->compression = VIPS_FOREIGN_HEIF_COMPRESSION_AV1; diff --git a/libvips/foreign/ppmsave.c b/libvips/foreign/ppmsave.c index 8e719c6eb3..719656772c 100644 --- a/libvips/foreign/ppmsave.c +++ b/libvips/foreign/ppmsave.c @@ -216,8 +216,13 @@ vips_foreign_save_ppm_build( VipsObject *object ) { VipsForeignSave *save = (VipsForeignSave *) object; VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) object; + VipsImage **t = (VipsImage **) vips_object_local_array( object, 2 ); VipsImage *image; + const char *filename; + const char *format_string; + char filename_buffer[VIPS_PATH_MAX]; + char option_string[VIPS_PATH_MAX]; char *magic; char *date; @@ -227,6 +232,60 @@ vips_foreign_save_ppm_build( VipsObject *object ) image = save->ready; + /* Try various ways to guess the write suffix. + */ + filename = NULL; + if( !vips_image_get_string( image, "format_string", &format_string ) ) { + vips__filename_split8( format_string, + filename_buffer, option_string ); + filename = filename_buffer; + } + else + filename = vips_connection_filename( + VIPS_CONNECTION( ppm->target ) ); + + /* ppm types. We use the suffix (if avail.) to set the defaults for + * bitdepth etc. + * + * pbm ... 1 band 1 bit + * pgm ... 1 band many bit + * ppm ... 3 band many bit + * pfm ... 1 or 3 bands, 32 bit + */ + if( filename ) { + VipsBandFormat target_format; + VipsInterpretation target_interpretation; + + target_format = image->BandFmt; + target_interpretation = image->Type; + + if( vips_iscasepostfix( filename, ".pbm" ) || + vips_iscasepostfix( filename, ".pgm" ) ) + target_interpretation = VIPS_INTERPRETATION_B_W; + else if( vips_iscasepostfix( filename, ".ppm" ) ) + target_interpretation = VIPS_INTERPRETATION_sRGB; + else if( vips_iscasepostfix( filename, ".pfm" ) ) + target_format = VIPS_FORMAT_FLOAT; + + if( target_format == VIPS_FORMAT_USHORT && + target_interpretation == VIPS_INTERPRETATION_B_W ) + target_interpretation = VIPS_INTERPRETATION_GREY16; + if( target_format == VIPS_FORMAT_USHORT && + target_interpretation == VIPS_INTERPRETATION_sRGB ) + target_interpretation = VIPS_INTERPRETATION_RGB16; + + if( vips_cast( image, &t[0], target_format, NULL ) ) + return( -1 ); + image = t[0]; + + if( image->Type != target_interpretation ) { + if( vips_colourspace( image, &t[1], + target_interpretation, NULL ) ) + return( -1 ); + image = t[1]; + } + } + /* Handle the deprecated squash parameter. */ if( vips_object_argument_isset( object, "squash" ) ) From 00a4da61df54389cd2c3de5087e1fd603814a20e Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 27 Oct 2021 15:07:28 +0100 Subject: [PATCH 04/20] add ppmsave_buffer --- ChangeLog | 1 + libvips/foreign/foreign.c | 2 + libvips/foreign/ppmsave.c | 122 +++++++++++++++++++++++++++++++-- libvips/include/vips/foreign.h | 2 + 4 files changed, 123 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8657826c40..03e98098eb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,7 @@ - added restart_interval option to jpegsave [manthey] - add IIIF3 support to dzsaave [martimpassos] - add atan2 [indus] +- add vips_ppmsave_buffer() 16/8/21 started 8.11.4 - fix off-by-one error in new rank fast path diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 48f2261121..24c7abcd94 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -2782,6 +2782,7 @@ vips_foreign_operation_init( void ) extern GType vips_foreign_load_ppm_file_get_type( void ); extern GType vips_foreign_load_ppm_source_get_type( void ); extern GType vips_foreign_save_ppm_file_get_type( void ); + extern GType vips_foreign_save_ppm_buffer_get_type( void ); extern GType vips_foreign_save_ppm_target_get_type( void ); extern GType vips_foreign_load_png_file_get_type( void ); @@ -2922,6 +2923,7 @@ vips_foreign_operation_init( void ) vips_foreign_load_ppm_file_get_type(); vips_foreign_load_ppm_source_get_type(); vips_foreign_save_ppm_file_get_type(); + vips_foreign_save_ppm_buffer_get_type(); vips_foreign_save_ppm_target_get_type(); #endif /*HAVE_PPM*/ diff --git a/libvips/foreign/ppmsave.c b/libvips/foreign/ppmsave.c index 719656772c..189cbe393c 100644 --- a/libvips/foreign/ppmsave.c +++ b/libvips/foreign/ppmsave.c @@ -546,6 +546,70 @@ vips_foreign_save_ppm_file_init( VipsForeignSavePpmFile *file ) { } +typedef struct _VipsForeignSavePpmBuffer { + VipsForeignSavePpm parent_object; + + /* Save to a buffer. + */ + VipsArea *buf; + +} VipsForeignSavePpmBuffer; + +typedef VipsForeignSavePpmClass VipsForeignSavePpmBufferClass; + +G_DEFINE_TYPE( VipsForeignSavePpmBuffer, vips_foreign_save_ppm_buffer, + vips_foreign_save_ppm_get_type() ); + +static int +vips_foreign_save_ppm_buffer_build( VipsObject *object ) +{ + VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) object; + VipsForeignSavePpmBuffer *buffer = + (VipsForeignSavePpmBuffer *) object; + + VipsBlob *blob; + + if( !(ppm->target = vips_target_new_to_memory()) ) + return( -1 ); + + if( VIPS_OBJECT_CLASS( vips_foreign_save_ppm_buffer_parent_class )-> + build( object ) ) + return( -1 ); + + g_object_get( ppm->target, "blob", &blob, NULL ); + g_object_set( buffer, "buffer", blob, NULL ); + vips_area_unref( VIPS_AREA( blob ) ); + + return( 0 ); +} + +static void +vips_foreign_save_ppm_buffer_class_init( + VipsForeignSavePpmBufferClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + object_class->nickname = "ppmsave_buffer"; + object_class->build = vips_foreign_save_ppm_buffer_build; + + VIPS_ARG_BOXED( class, "buffer", 1, + _( "Buffer" ), + _( "Buffer to save to" ), + VIPS_ARGUMENT_REQUIRED_OUTPUT, + G_STRUCT_OFFSET( VipsForeignSavePpmBuffer, buf ), + VIPS_TYPE_BLOB ); + +} + +static void +vips_foreign_save_ppm_buffer_init( VipsForeignSavePpmBuffer *buffer ) +{ +} + typedef struct _VipsForeignSavePpmTarget { VipsForeignSavePpm parent_object; @@ -611,8 +675,8 @@ vips_foreign_save_ppm_target_init( VipsForeignSavePpmTarget *target ) * * Optional arguments: * - * * @ascii: save as ASCII rather than binary - * * @squash: squash 8-bit images down to one bit + * * @ascii: %gboolean, save as ASCII rather than binary + * * @bitdepth: %gint, bitdepth to save at * * Write a VIPS image to a file as PPM. It can write 1, 8, 16 or * 32 bit unsigned integer images, float images, colour or monochrome, @@ -625,8 +689,7 @@ vips_foreign_save_ppm_target_init( VipsForeignSavePpmTarget *target ) * Set @ascii to %TRUE to write as human-readable ASCII. Normally data is * written in binary. * - * Set @squash to %TRUE to squash 8-bit images down to one bit. The saver does - * no dithering, that's up to you. + * Set @bitdepth to 1 to write a one-bit image. * * See also: vips_image_write_to_file(). * @@ -645,12 +708,63 @@ vips_ppmsave( VipsImage *in, const char *filename, ... ) return( result ); } +/** + * vips_ppmsave_buffer: (method) + * @in: image to save + * @buf: (array length=len) (element-type guint8): return output buffer here + * @len: (type gsize): return output length here + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @ascii: %gboolean, save as ASCII rather than binary + * * @bitdepth: %gint, bitdepth to save at + * + * As vips_ppmsave(), but save to a target. + * + * See also: vips_ppmsave(). + * + * Returns: 0 on success, -1 on error. + */ +int +vips_ppmsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) +{ + va_list ap; + VipsArea *area; + int result; + + area = NULL; + + va_start( ap, len ); + result = vips_call_split( "ppmsave_buffer", ap, in, &area ); + va_end( ap ); + + if( !result && + area ) { + if( buf ) { + *buf = area->data; + area->free_fn = NULL; + } + if( len ) + *len = area->length; + + vips_area_unref( area ); + } + + return( result ); +} + /** * vips_ppmsave_target: (method) * @in: image to save * @target: save image to this target * @...: %NULL-terminated list of optional named arguments * + * Optional arguments: + * + * * @ascii: %gboolean, save as ASCII rather than binary + * * @bitdepth: %gint, bitdepth to save at + * * As vips_ppmsave(), but save to a target. * * See also: vips_ppmsave(). diff --git a/libvips/include/vips/foreign.h b/libvips/include/vips/foreign.h index e8d0d1acfd..3e5e5ca4c7 100644 --- a/libvips/include/vips/foreign.h +++ b/libvips/include/vips/foreign.h @@ -618,6 +618,8 @@ int vips_ppmload_source( VipsSource *source, VipsImage **out, ... ) __attribute__((sentinel)); int vips_ppmsave( VipsImage *in, const char *filename, ... ) __attribute__((sentinel)); +int vips_ppmsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) + __attribute__((sentinel)); int vips_ppmsave_target( VipsImage *in, VipsTarget *target, ... ) __attribute__((sentinel)); From 772365280ac4d92a0b081930d72067c2be6ff51a Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 27 Oct 2021 15:20:42 +0100 Subject: [PATCH 05/20] fix up pfm save and remove gif from the list of things that magick supports (since we have our own saver now) --- libvips/foreign/ppmsave.c | 9 ++++++--- libvips/foreign/vips2magick.c | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libvips/foreign/ppmsave.c b/libvips/foreign/ppmsave.c index 189cbe393c..908bcc311e 100644 --- a/libvips/foreign/ppmsave.c +++ b/libvips/foreign/ppmsave.c @@ -377,9 +377,12 @@ vips_foreign_save_ppm_build( VipsObject *object ) double scale; char buf[G_ASCII_DTOSTR_BUF_SIZE]; - if( vips_image_get_double( image, - "pfm-scale", &scale ) ) - scale = 1; + scale = 1; + if( vips_image_get_typeof( image, "pfm-scale" ) && + !vips_image_get_double( image, + "pfm-scale", &scale ) ) + ; + if( !vips_amiMSBfirst() ) scale *= -1; /* Need to be locale independent. diff --git a/libvips/foreign/vips2magick.c b/libvips/foreign/vips2magick.c index 6f2e381f1e..272cfe588d 100644 --- a/libvips/foreign/vips2magick.c +++ b/libvips/foreign/vips2magick.c @@ -431,7 +431,7 @@ vips_foreign_save_magick_build( VipsObject *object ) * Instead, just list the commonly-used formats that all libMagicks support and * that libvips does not. */ -static const char *vips__save_magick_suffs[] = { ".gif", ".bmp", NULL }; +static const char *vips__save_magick_suffs[] = { ".bmp", NULL }; /* Save a bit of typing. */ From faf540549bba98b524321e37d4e025f916bee05b Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 27 Oct 2021 15:33:58 +0100 Subject: [PATCH 06/20] add support for format_string to the C++ binding --- cplusplus/VImage.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cplusplus/VImage.cpp b/cplusplus/VImage.cpp index 01e1a6f3e6..494d742d59 100644 --- a/cplusplus/VImage.cpp +++ b/cplusplus/VImage.cpp @@ -724,9 +724,12 @@ VImage::write_to_buffer( const char *suffix, void **buf, size_t *size, throw VError(); } + VImage copy = this->copy(); + copy.set("format_string", suffix); + call_option_string( operation_name, option_string, (options ? options : VImage::option())-> - set( "in", *this )-> + set( "in", copy )-> set( "buffer", &blob ) ); if( blob ) { @@ -755,9 +758,12 @@ VImage::write_to_target( const char *suffix, VTarget target, throw VError(); } + VImage copy = this->copy(); + copy.set("format_string", suffix); + call_option_string( operation_name, option_string, (options ? options : VImage::option())-> - set( "in", *this )-> + set( "in", copy )-> set( "target", target ) ); } From 33e07acc9f255a7688f410e65e94ae35a485a559 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 27 Oct 2021 15:42:09 +0100 Subject: [PATCH 07/20] switch to format-string since we use kebab-case elsewhere for image metadata --- cplusplus/VImage.cpp | 4 ++-- libvips/foreign/heifsave.c | 2 +- libvips/foreign/ppmsave.c | 2 +- libvips/foreign/vips2magick.c | 2 +- libvips/iofuncs/image.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cplusplus/VImage.cpp b/cplusplus/VImage.cpp index 494d742d59..518555ad7f 100644 --- a/cplusplus/VImage.cpp +++ b/cplusplus/VImage.cpp @@ -725,7 +725,7 @@ VImage::write_to_buffer( const char *suffix, void **buf, size_t *size, } VImage copy = this->copy(); - copy.set("format_string", suffix); + copy.set("format-string", suffix); call_option_string( operation_name, option_string, (options ? options : VImage::option())-> @@ -759,7 +759,7 @@ VImage::write_to_target( const char *suffix, VTarget target, } VImage copy = this->copy(); - copy.set("format_string", suffix); + copy.set("format-string", suffix); call_option_string( operation_name, option_string, (options ? options : VImage::option())-> diff --git a/libvips/foreign/heifsave.c b/libvips/foreign/heifsave.c index 11902cfb90..8cabc72f75 100644 --- a/libvips/foreign/heifsave.c +++ b/libvips/foreign/heifsave.c @@ -364,7 +364,7 @@ vips_foreign_save_heif_build( VipsObject *object ) */ filename = NULL; if( !vips_image_get_string( heif->image, - "format_string", &format_string ) ) { + "format-string", &format_string ) ) { vips__filename_split8( format_string, filename_buffer, option_string ); filename = filename_buffer; diff --git a/libvips/foreign/ppmsave.c b/libvips/foreign/ppmsave.c index 908bcc311e..ada2f22d76 100644 --- a/libvips/foreign/ppmsave.c +++ b/libvips/foreign/ppmsave.c @@ -235,7 +235,7 @@ vips_foreign_save_ppm_build( VipsObject *object ) /* Try various ways to guess the write suffix. */ filename = NULL; - if( !vips_image_get_string( image, "format_string", &format_string ) ) { + if( !vips_image_get_string( image, "format-string", &format_string ) ) { vips__filename_split8( format_string, filename_buffer, option_string ); filename = filename_buffer; diff --git a/libvips/foreign/vips2magick.c b/libvips/foreign/vips2magick.c index 272cfe588d..834edb618e 100644 --- a/libvips/foreign/vips2magick.c +++ b/libvips/foreign/vips2magick.c @@ -356,7 +356,7 @@ vips_foreign_save_magick_build( VipsObject *object ) */ if( !vips_object_argument_isset( object, "format" ) && !vips_image_get_string( im, - "format_string", &format_string ) ) { + "format-string", &format_string ) ) { char filename[VIPS_PATH_MAX]; char option_string[VIPS_PATH_MAX]; char *suffix; diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index 838f0a4b78..05dd050b8d 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -2720,7 +2720,7 @@ vips_image_note_format( VipsImage *image, const char *format_string ) if( vips_copy( image, ©, NULL ) ) return( NULL ); - vips_image_set_string( copy, "format_string", format_string ); + vips_image_set_string( copy, "format-string", format_string ); return( copy ); } From 921922b360c9c4d6c51d6b70a4a62ec726bc62b6 Mon Sep 17 00:00:00 2001 From: Kleis Auke Wolthuizen Date: Wed, 27 Oct 2021 20:09:18 +0200 Subject: [PATCH 08/20] Set format hint in vips__filename_split8 Seems to work. --- cplusplus/VImage.cpp | 10 ++------ libvips/foreign/foreign.c | 14 ++++++++++++ libvips/foreign/heifsave.c | 21 ++--------------- libvips/foreign/ppmsave.c | 26 ++++----------------- libvips/foreign/vips2magick.c | 30 +++--------------------- libvips/include/vips/foreign.h | 8 +++++++ libvips/iofuncs/image.c | 42 +++------------------------------- libvips/iofuncs/util.c | 9 ++++++++ 8 files changed, 46 insertions(+), 114 deletions(-) diff --git a/cplusplus/VImage.cpp b/cplusplus/VImage.cpp index 518555ad7f..01e1a6f3e6 100644 --- a/cplusplus/VImage.cpp +++ b/cplusplus/VImage.cpp @@ -724,12 +724,9 @@ VImage::write_to_buffer( const char *suffix, void **buf, size_t *size, throw VError(); } - VImage copy = this->copy(); - copy.set("format-string", suffix); - call_option_string( operation_name, option_string, (options ? options : VImage::option())-> - set( "in", copy )-> + set( "in", *this )-> set( "buffer", &blob ) ); if( blob ) { @@ -758,12 +755,9 @@ VImage::write_to_target( const char *suffix, VTarget target, throw VError(); } - VImage copy = this->copy(); - copy.set("format-string", suffix); - call_option_string( operation_name, option_string, (options ? options : VImage::option())-> - set( "in", copy )-> + set( "in", *this )-> set( "target", target ) ); } diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 24c7abcd94..72c880053c 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -1205,6 +1205,13 @@ vips_foreign_load_class_init( VipsForeignLoadClass *class ) G_STRUCT_OFFSET( VipsForeignLoad, disc ), TRUE ); + VIPS_ARG_STRING( class, "format", 112, + _( "Format" ), + _( "Format hint" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignLoad, format ), + NULL ); + } static void @@ -1795,6 +1802,13 @@ vips_foreign_save_class_init( VipsForeignSaveClass *class ) VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET( VipsForeignSave, page_height ), 0, VIPS_MAX_COORD, 0 ); + + VIPS_ARG_STRING( class, "format", 103, + _( "Format" ), + _( "Format to save in" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignSave, format ), + NULL ); } static void diff --git a/libvips/foreign/heifsave.c b/libvips/foreign/heifsave.c index 8cabc72f75..f4d6aad433 100644 --- a/libvips/foreign/heifsave.c +++ b/libvips/foreign/heifsave.c @@ -335,10 +335,6 @@ vips_foreign_save_heif_build( VipsObject *object ) VipsForeignSave *save = (VipsForeignSave *) object; VipsForeignSaveHeif *heif = (VipsForeignSaveHeif *) object; - const char *filename; - const char *format_string; - char filename_buffer[VIPS_PATH_MAX]; - char option_string[VIPS_PATH_MAX]; struct heif_error error; struct heif_writer writer; char *chroma; @@ -360,25 +356,12 @@ vips_foreign_save_heif_build( VipsObject *object ) if( vips_copy( save->ready, &heif->image, NULL ) ) return( -1 ); - /* Try various ways to get the filename. - */ - filename = NULL; - if( !vips_image_get_string( heif->image, - "format-string", &format_string ) ) { - vips__filename_split8( format_string, - filename_buffer, option_string ); - filename = filename_buffer; - } - else - filename = vips_connection_filename( - VIPS_CONNECTION( heif->target ) ); - /* Compression defaults to VIPS_FOREIGN_HEIF_COMPRESSION_AV1 for .avif * suffix. */ - if( filename && + if( save->format && !vips_object_argument_isset( object, "compression" ) && - vips_iscasepostfix( filename, ".avif" ) ) + g_ascii_strcasecmp( save->format, "avif" ) == 0 ) heif->compression = VIPS_FOREIGN_HEIF_COMPRESSION_AV1; error = heif_context_get_encoder_for_format( heif->ctx, diff --git a/libvips/foreign/ppmsave.c b/libvips/foreign/ppmsave.c index ada2f22d76..e29ae16391 100644 --- a/libvips/foreign/ppmsave.c +++ b/libvips/foreign/ppmsave.c @@ -219,10 +219,6 @@ vips_foreign_save_ppm_build( VipsObject *object ) VipsImage **t = (VipsImage **) vips_object_local_array( object, 2 ); VipsImage *image; - const char *filename; - const char *format_string; - char filename_buffer[VIPS_PATH_MAX]; - char option_string[VIPS_PATH_MAX]; char *magic; char *date; @@ -232,18 +228,6 @@ vips_foreign_save_ppm_build( VipsObject *object ) image = save->ready; - /* Try various ways to guess the write suffix. - */ - filename = NULL; - if( !vips_image_get_string( image, "format-string", &format_string ) ) { - vips__filename_split8( format_string, - filename_buffer, option_string ); - filename = filename_buffer; - } - else - filename = vips_connection_filename( - VIPS_CONNECTION( ppm->target ) ); - /* ppm types. We use the suffix (if avail.) to set the defaults for * bitdepth etc. * @@ -252,19 +236,19 @@ vips_foreign_save_ppm_build( VipsObject *object ) * ppm ... 3 band many bit * pfm ... 1 or 3 bands, 32 bit */ - if( filename ) { + if( save->format ) { VipsBandFormat target_format; VipsInterpretation target_interpretation; target_format = image->BandFmt; target_interpretation = image->Type; - if( vips_iscasepostfix( filename, ".pbm" ) || - vips_iscasepostfix( filename, ".pgm" ) ) + if( g_ascii_strcasecmp( save->format, "pbm" ) == 0 || + g_ascii_strcasecmp( save->format, "pgm" ) == 0 ) target_interpretation = VIPS_INTERPRETATION_B_W; - else if( vips_iscasepostfix( filename, ".ppm" ) ) + else if( g_ascii_strcasecmp( save->format, "ppm" ) == 0 ) target_interpretation = VIPS_INTERPRETATION_sRGB; - else if( vips_iscasepostfix( filename, ".pfm" ) ) + else if( g_ascii_strcasecmp( save->format, "pfm" ) == 0 ) target_format = VIPS_FORMAT_FLOAT; if( target_format == VIPS_FORMAT_USHORT && diff --git a/libvips/foreign/vips2magick.c b/libvips/foreign/vips2magick.c index 834edb618e..42ca1af3fe 100644 --- a/libvips/foreign/vips2magick.c +++ b/libvips/foreign/vips2magick.c @@ -65,7 +65,6 @@ typedef struct _VipsForeignSaveMagick { /* Parameters. */ char *filename; /* NULL during buffer output */ - char *format; int quality; gboolean optimize_gif_frames; gboolean optimize_gif_transparency; @@ -275,7 +274,6 @@ vips_foreign_save_magick_build( VipsObject *object ) VipsForeignSaveMagick *magick = (VipsForeignSaveMagick *) object; VipsImage *im; - const char *format_string; #ifdef DEBUG printf( "vips_foreign_save_magick_build: %p\n", object ); @@ -351,28 +349,13 @@ vips_foreign_save_magick_build( VipsObject *object ) return( -1 ); } - /* There might be a format_string hint set on the image we are saving. - * Extract the filename component to imagemagick can guess the format. - */ - if( !vips_object_argument_isset( object, "format" ) && - !vips_image_get_string( im, - "format-string", &format_string ) ) { - char filename[VIPS_PATH_MAX]; - char option_string[VIPS_PATH_MAX]; - char *suffix; - - vips__filename_split8( format_string, filename, option_string ); - if( (suffix = strrchr( filename, '.' )) ) - VIPS_SETSTR( magick->format, suffix + 1 ); - } - - if( magick->format ) { + if( save->format ) { vips_strncpy( magick->image_info->magick, - magick->format, MaxPathExtent ); + save->format, MaxPathExtent ); if( magick->filename ) (void) vips_snprintf( magick->image_info->filename, MaxPathExtent, "%s:%s", - magick->format, magick->filename ); + save->format, magick->filename ); } else if( magick->filename ) { vips_strncpy( magick->image_info->filename, @@ -471,13 +454,6 @@ vips_foreign_save_magick_class_init( VipsForeignSaveMagickClass *class ) save_class->saveable = VIPS_SAVEABLE_ANY; save_class->format_table = bandfmt_magick; - VIPS_ARG_STRING( class, "format", 2, - _( "Format" ), - _( "Format to save in" ), - VIPS_ARGUMENT_OPTIONAL_INPUT, - G_STRUCT_OFFSET( VipsForeignSaveMagick, format ), - NULL ); - VIPS_ARG_INT( class, "quality", 3, _( "Quality" ), _( "Quality to use" ), diff --git a/libvips/include/vips/foreign.h b/libvips/include/vips/foreign.h index 3e5e5ca4c7..342ccaf892 100644 --- a/libvips/include/vips/foreign.h +++ b/libvips/include/vips/foreign.h @@ -135,6 +135,10 @@ typedef struct _VipsForeignLoad { */ gboolean fail; + /* Format hint. + */ + char *format; + /* Deprecated and unused, just here for compat. */ gboolean sequential; @@ -303,6 +307,10 @@ typedef struct _VipsForeignSave { */ int page_height; + /* Format to save in. + */ + char *format; + /*< public >*/ /* The image we are to save, as supplied by our caller. diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index 05dd050b8d..c59f28a773 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -2713,18 +2713,6 @@ vips_image_write_to_file( VipsImage *image, const char *name, ... ) return( result ); } -static VipsImage * -vips_image_note_format( VipsImage *image, const char *format_string ) -{ - VipsImage *copy; - - if( vips_copy( image, ©, NULL ) ) - return( NULL ); - vips_image_set_string( copy, "format-string", format_string ); - - return( copy ); -} - /** * vips_image_write_to_buffer: (method) * @in: image to write @@ -2764,23 +2752,15 @@ vips_image_write_to_buffer( VipsImage *in, if( (operation_name = vips_foreign_find_save_target( filename )) ) { VipsTarget *target; - VipsImage *copy; if( !(target = vips_target_new_to_memory()) ) return( -1 ); - /* Note the suffix for loaders. - */ - if( !(copy = vips_image_note_format( in, suffix )) ) - return( -1 ); - va_start( ap, size ); result = vips_call_split_option_string( operation_name, - option_string, ap, copy, target ); + option_string, ap, in, target ); va_end( ap ); - VIPS_UNREF( copy ); - if( result ) { VIPS_UNREF( target ); return( -1 ); @@ -2791,20 +2771,12 @@ vips_image_write_to_buffer( VipsImage *in, } else if( (operation_name = vips_foreign_find_save_buffer( filename )) ) { - VipsImage *copy; - - /* Note the suffix for loaders. - */ - if( !(copy = vips_image_note_format( in, suffix )) ) - return( -1 ); va_start( ap, size ); result = vips_call_split_option_string( operation_name, - option_string, ap, copy, &blob ); + option_string, ap, in, &blob ); va_end( ap ); - VIPS_UNREF( copy ); - if( result ) return( -1 ); } @@ -2857,25 +2829,17 @@ vips_image_write_to_target( VipsImage *in, char option_string[VIPS_PATH_MAX]; const char *operation_name; va_list ap; - VipsImage *copy; int result; vips__filename_split8( suffix, filename, option_string ); if( !(operation_name = vips_foreign_find_save_target( filename )) ) return( -1 ); - /* Note the suffix for loaders. - */ - if( !(copy = vips_image_note_format( in, suffix )) ) - return( -1 ); - va_start( ap, target ); result = vips_call_split_option_string( operation_name, option_string, - ap, copy, target ); + ap, in, target ); va_end( ap ); - VIPS_UNREF( copy ); - if( result ) return( -1 ); diff --git a/libvips/iofuncs/util.c b/libvips/iofuncs/util.c index 471ae43010..e2450b4612 100644 --- a/libvips/iofuncs/util.c +++ b/libvips/iofuncs/util.c @@ -1565,12 +1565,21 @@ void vips__filename_split8( const char *name, char *filename, char *option_string ) { char *p; + const char *format; + size_t len; vips_strncpy( filename, name, VIPS_PATH_MAX ); if( (p = (char *) vips__find_rightmost_brackets( filename )) ) { vips_strncpy( option_string, p, VIPS_PATH_MAX ); + len = strlen( p ); *p = '\0'; + if( (format = strrchr( filename, '.' )) ) + vips_snprintf( option_string + len - 1, + VIPS_PATH_MAX - len - 1, ",format=%s]", format + 1 ); } + else if( (format = strrchr( filename, '.' )) ) + vips_snprintf( option_string, + VIPS_PATH_MAX, "[format=%s]", format + 1 ); else vips_strncpy( option_string, "", VIPS_PATH_MAX ); } From d415a9b19096dbddf21e79d0cc0acd7cbcad27cf Mon Sep 17 00:00:00 2001 From: Kleis Auke Wolthuizen Date: Thu, 28 Oct 2021 10:49:04 +0200 Subject: [PATCH 09/20] [WiP] Subclass savers that can store in multiple formats See: https://github.com/libvips/libvips/pull/2499. --- libvips/foreign/foreign.c | 15 ++-------- libvips/foreign/heifload.c | 11 +++++++ libvips/foreign/heifsave.c | 54 ++++++++++++++++++++++++++++------ libvips/foreign/pforeign.h | 2 ++ libvips/foreign/ppmsave.c | 5 ++-- libvips/foreign/vips2magick.c | 14 +++++++-- libvips/include/vips/foreign.h | 8 ----- libvips/iofuncs/util.c | 9 ------ libvips/module/heif.c | 2 ++ 9 files changed, 76 insertions(+), 44 deletions(-) diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 72c880053c..cf4cd317c3 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -1205,13 +1205,6 @@ vips_foreign_load_class_init( VipsForeignLoadClass *class ) G_STRUCT_OFFSET( VipsForeignLoad, disc ), TRUE ); - VIPS_ARG_STRING( class, "format", 112, - _( "Format" ), - _( "Format hint" ), - VIPS_ARGUMENT_OPTIONAL_INPUT, - G_STRUCT_OFFSET( VipsForeignLoad, format ), - NULL ); - } static void @@ -1803,12 +1796,6 @@ vips_foreign_save_class_init( VipsForeignSaveClass *class ) G_STRUCT_OFFSET( VipsForeignSave, page_height ), 0, VIPS_MAX_COORD, 0 ); - VIPS_ARG_STRING( class, "format", 103, - _( "Format" ), - _( "Format to save in" ), - VIPS_ARGUMENT_OPTIONAL_INPUT, - G_STRUCT_OFFSET( VipsForeignSave, format ), - NULL ); } static void @@ -2894,6 +2881,7 @@ vips_foreign_operation_init( void ) extern GType vips_foreign_load_heif_buffer_get_type( void ); extern GType vips_foreign_load_heif_source_get_type( void ); extern GType vips_foreign_save_heif_file_get_type( void ); + extern GType vips_foreign_save_avif_file_get_type( void ); extern GType vips_foreign_save_heif_buffer_get_type( void ); extern GType vips_foreign_save_heif_target_get_type( void ); @@ -3095,6 +3083,7 @@ vips_foreign_operation_init( void ) #if defined(HAVE_HEIF_ENCODER) && !defined(HEIF_MODULE) vips_foreign_save_heif_file_get_type(); + vips_foreign_save_avif_file_get_type(); vips_foreign_save_heif_buffer_get_type(); vips_foreign_save_heif_target_get_type(); #endif /*defined(HAVE_HEIF_ENCODER) && !defined(HEIF_MODULE)*/ diff --git a/libvips/foreign/heifload.c b/libvips/foreign/heifload.c index 34916e3afd..cd631bd3b4 100644 --- a/libvips/foreign/heifload.c +++ b/libvips/foreign/heifload.c @@ -76,6 +76,17 @@ #include "pforeign.h" +const char *vips__heic_suffs[] = { + ".heic", + ".heif", + NULL +}; + +const char *vips__avif_suffs[] = { + ".avif", + NULL +}; + const char *vips__heif_suffs[] = { ".heic", ".heif", diff --git a/libvips/foreign/heifsave.c b/libvips/foreign/heifsave.c index f4d6aad433..2dfb5a55ae 100644 --- a/libvips/foreign/heifsave.c +++ b/libvips/foreign/heifsave.c @@ -356,14 +356,6 @@ vips_foreign_save_heif_build( VipsObject *object ) if( vips_copy( save->ready, &heif->image, NULL ) ) return( -1 ); - /* Compression defaults to VIPS_FOREIGN_HEIF_COMPRESSION_AV1 for .avif - * suffix. - */ - if( save->format && - !vips_object_argument_isset( object, "compression" ) && - g_ascii_strcasecmp( save->format, "avif" ) == 0 ) - heif->compression = VIPS_FOREIGN_HEIF_COMPRESSION_AV1; - error = heif_context_get_encoder_for_format( heif->ctx, (enum heif_compression_format) heif->compression, &heif->encoder ); @@ -498,7 +490,7 @@ vips_foreign_save_heif_class_init( VipsForeignSaveHeifClass *class ) object_class->description = _( "save image in HEIF format" ); object_class->build = vips_foreign_save_heif_build; - foreign_class->suffs = vips__heif_suffs; + foreign_class->suffs = vips__heic_suffs; save_class->saveable = VIPS_SAVEABLE_RGBA_ONLY; save_class->format_table = vips_heif_bandfmt; @@ -619,6 +611,50 @@ vips_foreign_save_heif_file_init( VipsForeignSaveHeifFile *file ) { } +typedef VipsForeignSaveHeifFile VipsForeignSaveAvifFile; +typedef VipsForeignSaveHeifFileClass VipsForeignSaveAvifFileClass; + +G_DEFINE_TYPE( VipsForeignSaveAvifFile, vips_foreign_save_avif_file, + vips_foreign_save_heif_file_get_type() ); + +static int +vips_foreign_save_avif_file_build( VipsObject *object ) +{ + if( VIPS_OBJECT_CLASS( vips_foreign_save_avif_file_parent_class )-> + build( object ) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_foreign_save_avif_file_class_init( VipsForeignSaveAvifFileClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsForeignClass *foreign_class = (VipsForeignClass *) class; + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + object_class->nickname = "avifsave"; + object_class->description = _( "save image in AVIF format" ); + object_class->build = vips_foreign_save_avif_file_build; + + foreign_class->suffs = vips__avif_suffs; + + /* Hide from UI. + */ + object_class->deprecated = TRUE; +} + +static void +vips_foreign_save_avif_file_init( VipsForeignSaveAvifFile *file ) +{ + VipsForeignSaveHeif *heif = (VipsForeignSaveHeif *) file; + heif->compression = VIPS_FOREIGN_HEIF_COMPRESSION_AV1; +} + typedef struct _VipsForeignSaveHeifBuffer { VipsForeignSaveHeif parent_object; diff --git a/libvips/foreign/pforeign.h b/libvips/foreign/pforeign.h index 7017172b55..7ef142c511 100644 --- a/libvips/foreign/pforeign.h +++ b/libvips/foreign/pforeign.h @@ -235,6 +235,8 @@ typedef void *(*VipsNiftiMapFn)( const char *name, GValue *value, glong offset, void *a, void *b ); void *vips__foreign_nifti_map( VipsNiftiMapFn fn, void *a, void *b ); +extern const char *vips__heic_suffs[]; +extern const char *vips__avif_suffs[]; extern const char *vips__heif_suffs[]; extern const char *vips__jp2k_suffs[]; diff --git a/libvips/foreign/ppmsave.c b/libvips/foreign/ppmsave.c index e29ae16391..318d4d4829 100644 --- a/libvips/foreign/ppmsave.c +++ b/libvips/foreign/ppmsave.c @@ -236,7 +236,8 @@ vips_foreign_save_ppm_build( VipsObject *object ) * ppm ... 3 band many bit * pfm ... 1 or 3 bands, 32 bit */ - if( save->format ) { + // FIXME(kleisauke): Subclass ppmsave + /*if( save->format ) { VipsBandFormat target_format; VipsInterpretation target_interpretation; @@ -268,7 +269,7 @@ vips_foreign_save_ppm_build( VipsObject *object ) return( -1 ); image = t[1]; } - } + }*/ /* Handle the deprecated squash parameter. */ diff --git a/libvips/foreign/vips2magick.c b/libvips/foreign/vips2magick.c index 42ca1af3fe..79b312ac15 100644 --- a/libvips/foreign/vips2magick.c +++ b/libvips/foreign/vips2magick.c @@ -65,6 +65,7 @@ typedef struct _VipsForeignSaveMagick { /* Parameters. */ char *filename; /* NULL during buffer output */ + char *format; int quality; gboolean optimize_gif_frames; gboolean optimize_gif_transparency; @@ -349,13 +350,13 @@ vips_foreign_save_magick_build( VipsObject *object ) return( -1 ); } - if( save->format ) { + if( magick->format ) { vips_strncpy( magick->image_info->magick, - save->format, MaxPathExtent ); + magick->format, MaxPathExtent ); if( magick->filename ) (void) vips_snprintf( magick->image_info->filename, MaxPathExtent, "%s:%s", - save->format, magick->filename ); + magick->format, magick->filename ); } else if( magick->filename ) { vips_strncpy( magick->image_info->filename, @@ -454,6 +455,13 @@ vips_foreign_save_magick_class_init( VipsForeignSaveMagickClass *class ) save_class->saveable = VIPS_SAVEABLE_ANY; save_class->format_table = bandfmt_magick; + VIPS_ARG_STRING( class, "format", 2, + _( "Format" ), + _( "Format to save in" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignSaveMagick, format ), + NULL ); + VIPS_ARG_INT( class, "quality", 3, _( "Quality" ), _( "Quality to use" ), diff --git a/libvips/include/vips/foreign.h b/libvips/include/vips/foreign.h index 342ccaf892..3e5e5ca4c7 100644 --- a/libvips/include/vips/foreign.h +++ b/libvips/include/vips/foreign.h @@ -135,10 +135,6 @@ typedef struct _VipsForeignLoad { */ gboolean fail; - /* Format hint. - */ - char *format; - /* Deprecated and unused, just here for compat. */ gboolean sequential; @@ -307,10 +303,6 @@ typedef struct _VipsForeignSave { */ int page_height; - /* Format to save in. - */ - char *format; - /*< public >*/ /* The image we are to save, as supplied by our caller. diff --git a/libvips/iofuncs/util.c b/libvips/iofuncs/util.c index e2450b4612..471ae43010 100644 --- a/libvips/iofuncs/util.c +++ b/libvips/iofuncs/util.c @@ -1565,21 +1565,12 @@ void vips__filename_split8( const char *name, char *filename, char *option_string ) { char *p; - const char *format; - size_t len; vips_strncpy( filename, name, VIPS_PATH_MAX ); if( (p = (char *) vips__find_rightmost_brackets( filename )) ) { vips_strncpy( option_string, p, VIPS_PATH_MAX ); - len = strlen( p ); *p = '\0'; - if( (format = strrchr( filename, '.' )) ) - vips_snprintf( option_string + len - 1, - VIPS_PATH_MAX - len - 1, ",format=%s]", format + 1 ); } - else if( (format = strrchr( filename, '.' )) ) - vips_snprintf( option_string, - VIPS_PATH_MAX, "[format=%s]", format + 1 ); else vips_strncpy( option_string, "", VIPS_PATH_MAX ); } diff --git a/libvips/module/heif.c b/libvips/module/heif.c index 7d43949fdb..f4bd45a543 100644 --- a/libvips/module/heif.c +++ b/libvips/module/heif.c @@ -62,6 +62,7 @@ g_module_check_init( GModule *module ) extern GType vips_foreign_load_heif_buffer_get_type( void ); extern GType vips_foreign_load_heif_source_get_type( void ); extern GType vips_foreign_save_heif_file_get_type( void ); + extern GType vips_foreign_save_avif_file_get_type( void ); extern GType vips_foreign_save_heif_buffer_get_type( void ); extern GType vips_foreign_save_heif_target_get_type( void ); @@ -73,6 +74,7 @@ g_module_check_init( GModule *module ) #ifdef HAVE_HEIF_ENCODER vips_foreign_save_heif_file_get_type(); + vips_foreign_save_avif_file_get_type(); vips_foreign_save_heif_buffer_get_type(); vips_foreign_save_heif_target_get_type(); #endif /*HAVE_HEIF_ENCODER*/ From 9b33fb9e1c913c2565df71cb0a6085e451f86ce2 Mon Sep 17 00:00:00 2001 From: Kleis Auke Wolthuizen Date: Thu, 28 Oct 2021 12:55:06 +0200 Subject: [PATCH 10/20] Finish implementation See: https://github.com/libvips/libvips/pull/2499. --- libvips/foreign/foreign.c | 12 +++- libvips/foreign/heifsave.c | 89 ++++++++++++++------------- libvips/foreign/pforeign.h | 5 +- libvips/foreign/ppmload.c | 7 ++- libvips/foreign/ppmsave.c | 112 +++++++++++++++++++++++++++++++--- libvips/foreign/vips2magick.c | 92 +++++++++++++++++++++++++++- libvips/module/heif.c | 4 +- libvips/module/magick.c | 4 ++ 8 files changed, 265 insertions(+), 60 deletions(-) diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index cf4cd317c3..5111e22f87 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -2785,6 +2785,8 @@ vips_foreign_operation_init( void ) extern GType vips_foreign_save_ppm_file_get_type( void ); extern GType vips_foreign_save_ppm_buffer_get_type( void ); extern GType vips_foreign_save_ppm_target_get_type( void ); + extern GType vips_foreign_save_pgm_target_get_type( void ); + extern GType vips_foreign_save_pfm_target_get_type( void ); extern GType vips_foreign_load_png_file_get_type( void ); extern GType vips_foreign_load_png_buffer_get_type( void ); @@ -2843,7 +2845,9 @@ vips_foreign_operation_init( void ) extern GType vips_foreign_load_magick7_file_get_type( void ); extern GType vips_foreign_load_magick7_buffer_get_type( void ); extern GType vips_foreign_save_magick_file_get_type( void ); + extern GType vips_foreign_save_magick_bmp_file_get_type( void ); extern GType vips_foreign_save_magick_buffer_get_type( void ); + extern GType vips_foreign_save_magick_bmp_buffer_get_type( void ); extern GType vips_foreign_save_dz_file_get_type( void ); extern GType vips_foreign_save_dz_buffer_get_type( void ); @@ -2881,9 +2885,9 @@ vips_foreign_operation_init( void ) extern GType vips_foreign_load_heif_buffer_get_type( void ); extern GType vips_foreign_load_heif_source_get_type( void ); extern GType vips_foreign_save_heif_file_get_type( void ); - extern GType vips_foreign_save_avif_file_get_type( void ); extern GType vips_foreign_save_heif_buffer_get_type( void ); extern GType vips_foreign_save_heif_target_get_type( void ); + extern GType vips_foreign_save_avif_target_get_type( void ); extern GType vips_foreign_load_nifti_file_get_type( void ); extern GType vips_foreign_load_nifti_source_get_type( void ); @@ -2927,6 +2931,8 @@ vips_foreign_operation_init( void ) vips_foreign_save_ppm_file_get_type(); vips_foreign_save_ppm_buffer_get_type(); vips_foreign_save_ppm_target_get_type(); + vips_foreign_save_pgm_target_get_type(); + vips_foreign_save_pfm_target_get_type(); #endif /*HAVE_PPM*/ #ifdef HAVE_RADIANCE @@ -3056,7 +3062,9 @@ vips_foreign_operation_init( void ) #if defined(ENABLE_MAGICKSAVE) && !defined(MAGICK_MODULE) vips_foreign_save_magick_file_get_type(); + vips_foreign_save_magick_bmp_file_get_type(); vips_foreign_save_magick_buffer_get_type(); + vips_foreign_save_magick_bmp_buffer_get_type(); #endif /*defined(ENABLE_MAGICKSAVE) && !defined(MAGICK_MODULE)*/ #ifdef HAVE_CFITSIO @@ -3083,9 +3091,9 @@ vips_foreign_operation_init( void ) #if defined(HAVE_HEIF_ENCODER) && !defined(HEIF_MODULE) vips_foreign_save_heif_file_get_type(); - vips_foreign_save_avif_file_get_type(); vips_foreign_save_heif_buffer_get_type(); vips_foreign_save_heif_target_get_type(); + vips_foreign_save_avif_target_get_type(); #endif /*defined(HAVE_HEIF_ENCODER) && !defined(HEIF_MODULE)*/ vips__foreign_load_operation = diff --git a/libvips/foreign/heifsave.c b/libvips/foreign/heifsave.c index 2dfb5a55ae..ecf437dd9f 100644 --- a/libvips/foreign/heifsave.c +++ b/libvips/foreign/heifsave.c @@ -611,50 +611,6 @@ vips_foreign_save_heif_file_init( VipsForeignSaveHeifFile *file ) { } -typedef VipsForeignSaveHeifFile VipsForeignSaveAvifFile; -typedef VipsForeignSaveHeifFileClass VipsForeignSaveAvifFileClass; - -G_DEFINE_TYPE( VipsForeignSaveAvifFile, vips_foreign_save_avif_file, - vips_foreign_save_heif_file_get_type() ); - -static int -vips_foreign_save_avif_file_build( VipsObject *object ) -{ - if( VIPS_OBJECT_CLASS( vips_foreign_save_avif_file_parent_class )-> - build( object ) ) - return( -1 ); - - return( 0 ); -} - -static void -vips_foreign_save_avif_file_class_init( VipsForeignSaveAvifFileClass *class ) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS( class ); - VipsObjectClass *object_class = (VipsObjectClass *) class; - VipsForeignClass *foreign_class = (VipsForeignClass *) class; - - gobject_class->set_property = vips_object_set_property; - gobject_class->get_property = vips_object_get_property; - - object_class->nickname = "avifsave"; - object_class->description = _( "save image in AVIF format" ); - object_class->build = vips_foreign_save_avif_file_build; - - foreign_class->suffs = vips__avif_suffs; - - /* Hide from UI. - */ - object_class->deprecated = TRUE; -} - -static void -vips_foreign_save_avif_file_init( VipsForeignSaveAvifFile *file ) -{ - VipsForeignSaveHeif *heif = (VipsForeignSaveHeif *) file; - heif->compression = VIPS_FOREIGN_HEIF_COMPRESSION_AV1; -} - typedef struct _VipsForeignSaveHeifBuffer { VipsForeignSaveHeif parent_object; @@ -776,6 +732,51 @@ vips_foreign_save_heif_target_init( VipsForeignSaveHeifTarget *target ) { } +typedef VipsForeignSaveHeifTarget VipsForeignSaveAvifTarget; +typedef VipsForeignSaveHeifTargetClass VipsForeignSaveAvifTargetClass; + +G_DEFINE_TYPE( VipsForeignSaveAvifTarget, vips_foreign_save_avif_target, + vips_foreign_save_heif_target_get_type() ); + +static int +vips_foreign_save_avif_target_build( VipsObject *object ) +{ + if( VIPS_OBJECT_CLASS( vips_foreign_save_avif_target_parent_class )-> + build( object ) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_foreign_save_avif_target_class_init( + VipsForeignSaveAvifTargetClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsForeignClass *foreign_class = (VipsForeignClass *) class; + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + object_class->nickname = "avifsave_target"; + object_class->description = _( "save image in AVIF format" ); + object_class->build = vips_foreign_save_avif_target_build; + + foreign_class->suffs = vips__avif_suffs; + + /* Hide from UI. + */ + object_class->deprecated = TRUE; +} + +static void +vips_foreign_save_avif_target_init( VipsForeignSaveAvifTarget *target ) +{ + VipsForeignSaveHeif *heif = (VipsForeignSaveHeif *) target; + heif->compression = VIPS_FOREIGN_HEIF_COMPRESSION_AV1; +} + #endif /*HAVE_HEIF_ENCODER*/ /* The C API wrappers are defined in foreign.c. diff --git a/libvips/foreign/pforeign.h b/libvips/foreign/pforeign.h index 7ef142c511..04adf82c6a 100644 --- a/libvips/foreign/pforeign.h +++ b/libvips/foreign/pforeign.h @@ -157,7 +157,10 @@ int vips__mat_load( const char *filename, VipsImage *out ); int vips__mat_header( const char *filename, VipsImage *out ); int vips__mat_ismat( const char *filename ); -extern const char *vips__ppm_suffs[]; +extern const char *vips__load_ppm_suffs[]; +extern const char *vips__save_ppm_suffs[]; +extern const char *vips__save_pgm_suffs[]; +extern const char *vips__save_pfm_suffs[]; int vips__ppm_save_target( VipsImage *in, VipsTarget *target, gboolean ascii, gboolean squash ); diff --git a/libvips/foreign/ppmload.c b/libvips/foreign/ppmload.c index ecdef5cc93..6106dc79d9 100644 --- a/libvips/foreign/ppmload.c +++ b/libvips/foreign/ppmload.c @@ -141,7 +141,10 @@ static char *magic_names[] = { /* Shared with ppmsave. */ -const char *vips__ppm_suffs[] = { ".ppm", ".pgm", ".pbm", ".pfm", NULL }; +const char *vips__load_ppm_suffs[] = { ".ppm", ".pgm", ".pbm", ".pfm", NULL }; +const char *vips__save_ppm_suffs[] = { ".ppm", NULL }; +const char *vips__save_pgm_suffs[] = { ".pgm", ".pbm", NULL }; +const char *vips__save_pfm_suffs[] = { ".pfm", NULL }; static gboolean vips_foreign_load_ppm_is_a_source( VipsSource *source ) @@ -743,7 +746,7 @@ vips_foreign_load_ppm_class_init( VipsForeignLoadPpmClass *class ) object_class->description = _( "load ppm base class" ); object_class->build = vips_foreign_load_ppm_build; - foreign_class->suffs = vips__ppm_suffs; + foreign_class->suffs = vips__load_ppm_suffs; /* We are fast at is_a(), so high priority. */ diff --git a/libvips/foreign/ppmsave.c b/libvips/foreign/ppmsave.c index 318d4d4829..b29fe989c1 100644 --- a/libvips/foreign/ppmsave.c +++ b/libvips/foreign/ppmsave.c @@ -70,6 +70,7 @@ struct _VipsForeignSavePpm { VipsForeignSave parent_object; VipsTarget *target; + char *format; gboolean ascii; int bitdepth; @@ -236,20 +237,18 @@ vips_foreign_save_ppm_build( VipsObject *object ) * ppm ... 3 band many bit * pfm ... 1 or 3 bands, 32 bit */ - // FIXME(kleisauke): Subclass ppmsave - /*if( save->format ) { + if( ppm->format ) { VipsBandFormat target_format; VipsInterpretation target_interpretation; target_format = image->BandFmt; target_interpretation = image->Type; - if( g_ascii_strcasecmp( save->format, "pbm" ) == 0 || - g_ascii_strcasecmp( save->format, "pgm" ) == 0 ) + if( g_ascii_strcasecmp( ppm->format, "pgm" ) == 0 ) target_interpretation = VIPS_INTERPRETATION_B_W; - else if( g_ascii_strcasecmp( save->format, "ppm" ) == 0 ) + else if( g_ascii_strcasecmp( ppm->format, "ppm" ) == 0 ) target_interpretation = VIPS_INTERPRETATION_sRGB; - else if( g_ascii_strcasecmp( save->format, "pfm" ) == 0 ) + else if( g_ascii_strcasecmp( ppm->format, "pfm" ) == 0 ) target_format = VIPS_FORMAT_FLOAT; if( target_format == VIPS_FORMAT_USHORT && @@ -269,7 +268,7 @@ vips_foreign_save_ppm_build( VipsObject *object ) return( -1 ); image = t[1]; } - }*/ + } /* Handle the deprecated squash parameter. */ @@ -449,11 +448,18 @@ vips_foreign_save_ppm_class_init( VipsForeignSavePpmClass *class ) object_class->description = _( "save to ppm" ); object_class->build = vips_foreign_save_ppm_build; - foreign_class->suffs = vips__ppm_suffs; + foreign_class->suffs = vips__save_ppm_suffs; save_class->saveable = VIPS_SAVEABLE_RGB; save_class->format_table = bandfmt_ppm; + VIPS_ARG_STRING( class, "format", 2, + _( "Format" ), + _( "Format to save in" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsForeignSavePpm, format ), + NULL ); + VIPS_ARG_BOOL( class, "ascii", 10, _( "ASCII" ), _( "save as ascii" ), @@ -653,6 +659,96 @@ vips_foreign_save_ppm_target_init( VipsForeignSavePpmTarget *target ) { } +typedef VipsForeignSavePpmTarget VipsForeignSavePgmTarget; +typedef VipsForeignSavePpmTargetClass VipsForeignSavePgmTargetClass; + +G_DEFINE_TYPE( VipsForeignSavePgmTarget, vips_foreign_save_pgm_target, + vips_foreign_save_ppm_target_get_type() ); + +static int +vips_foreign_save_pgm_target_build( VipsObject *object ) +{ + if( VIPS_OBJECT_CLASS( vips_foreign_save_pgm_target_parent_class )-> + build( object ) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_foreign_save_pgm_target_class_init( + VipsForeignSavePgmTargetClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsForeignClass *foreign_class = (VipsForeignClass *) class; + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + object_class->nickname = "pgmsave_target"; + object_class->description = _( "save image in pgm format" ); + object_class->build = vips_foreign_save_pgm_target_build; + + foreign_class->suffs = vips__save_pgm_suffs; + + /* Hide from UI. + */ + object_class->deprecated = TRUE; +} + +static void +vips_foreign_save_pgm_target_init( VipsForeignSavePgmTarget *target ) +{ + VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) target; + VIPS_SETSTR( ppm->format, "pgm" ); +} + +typedef VipsForeignSavePpmTarget VipsForeignSavePfmTarget; +typedef VipsForeignSavePpmTargetClass VipsForeignSavePfmTargetClass; + +G_DEFINE_TYPE( VipsForeignSavePfmTarget, vips_foreign_save_pfm_target, + vips_foreign_save_ppm_target_get_type() ); + +static int +vips_foreign_save_pfm_target_build( VipsObject *object ) +{ + if( VIPS_OBJECT_CLASS( vips_foreign_save_pfm_target_parent_class )-> + build( object ) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_foreign_save_pfm_target_class_init( + VipsForeignSavePfmTargetClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsForeignClass *foreign_class = (VipsForeignClass *) class; + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + object_class->nickname = "pfmsave_target"; + object_class->description = _( "save image in pfm format" ); + object_class->build = vips_foreign_save_pfm_target_build; + + foreign_class->suffs = vips__save_pfm_suffs; + + /* Hide from UI. + */ + object_class->deprecated = TRUE; +} + +static void +vips_foreign_save_pfm_target_init( VipsForeignSavePfmTarget *target ) +{ + VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) target; + VIPS_SETSTR( ppm->format, "pfm" ); +} + #endif /*HAVE_PPM*/ /** diff --git a/libvips/foreign/vips2magick.c b/libvips/foreign/vips2magick.c index 79b312ac15..09f9cc55c5 100644 --- a/libvips/foreign/vips2magick.c +++ b/libvips/foreign/vips2magick.c @@ -415,7 +415,8 @@ vips_foreign_save_magick_build( VipsObject *object ) * Instead, just list the commonly-used formats that all libMagicks support and * that libvips does not. */ -static const char *vips__save_magick_suffs[] = { ".bmp", NULL }; +static const char *vips__save_magick_suffs[] = { NULL }; +static const char *vips__save_magick_bmp_suffs[] = { ".bmp", NULL }; /* Save a bit of typing. */ @@ -558,6 +559,50 @@ vips_foreign_save_magick_file_init( VipsForeignSaveMagickFile *file ) { } +typedef VipsForeignSaveMagickFile VipsForeignSaveMagickBmpFile; +typedef VipsForeignSaveMagickFileClass VipsForeignSaveMagickBmpFileClass; + +G_DEFINE_TYPE( VipsForeignSaveMagickBmpFile, vips_foreign_save_magick_bmp_file, + vips_foreign_save_magick_file_get_type() ); + +static int +vips_foreign_save_magick_bmp_file_build( VipsObject *object ) +{ + if( VIPS_OBJECT_CLASS( vips_foreign_save_magick_bmp_file_parent_class )-> + build( object ) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_foreign_save_magick_bmp_file_class_init( VipsForeignSaveMagickBmpFileClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsForeignClass *foreign_class = (VipsForeignClass *) class; + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + object_class->nickname = "magicksave_bmp"; + object_class->description = _( "save bmp image with ImageMagick" ); + object_class->build = vips_foreign_save_magick_bmp_file_build; + + foreign_class->suffs = vips__save_magick_bmp_suffs; + + /* Hide from UI. + */ + object_class->deprecated = TRUE; +} + +static void +vips_foreign_save_magick_bmp_file_init( VipsForeignSaveMagickBmpFile *file ) +{ + VipsForeignSaveMagick *magick = (VipsForeignSaveMagick *) file; + VIPS_SETSTR( magick->format, "bmp" ); +} + typedef struct _VipsForeignSaveMagickBuffer { VipsForeignSaveMagick parent_object; @@ -631,4 +676,49 @@ vips_foreign_save_magick_buffer_init( VipsForeignSaveMagickBuffer *buffer ) { } +typedef VipsForeignSaveMagickBuffer VipsForeignSaveMagickBmpBuffer; +typedef VipsForeignSaveMagickBufferClass VipsForeignSaveMagickBmpBufferClass; + +G_DEFINE_TYPE( VipsForeignSaveMagickBmpBuffer, vips_foreign_save_magick_bmp_buffer, + vips_foreign_save_magick_buffer_get_type() ); + +static int +vips_foreign_save_magick_bmp_buffer_build( VipsObject *object ) +{ + if( VIPS_OBJECT_CLASS( vips_foreign_save_magick_bmp_buffer_parent_class )-> + build( object ) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_foreign_save_magick_bmp_buffer_class_init( + VipsForeignSaveMagickBmpBufferClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsForeignClass *foreign_class = (VipsForeignClass *) class; + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + object_class->nickname = "magicksave_bmp_buffer"; + object_class->description = _( "save bmp image to magick buffer" ); + object_class->build = vips_foreign_save_magick_bmp_buffer_build; + + foreign_class->suffs = vips__save_magick_bmp_suffs; + + /* Hide from UI. + */ + object_class->deprecated = TRUE; +} + +static void +vips_foreign_save_magick_bmp_buffer_init( VipsForeignSaveMagickBmpBuffer *buffer ) +{ + VipsForeignSaveMagick *magick = (VipsForeignSaveMagick *) buffer; + VIPS_SETSTR( magick->format, "bmp" ); +} + #endif /*ENABLE_MAGICKSAVE*/ diff --git a/libvips/module/heif.c b/libvips/module/heif.c index f4bd45a543..4eeb722bd2 100644 --- a/libvips/module/heif.c +++ b/libvips/module/heif.c @@ -62,9 +62,9 @@ g_module_check_init( GModule *module ) extern GType vips_foreign_load_heif_buffer_get_type( void ); extern GType vips_foreign_load_heif_source_get_type( void ); extern GType vips_foreign_save_heif_file_get_type( void ); - extern GType vips_foreign_save_avif_file_get_type( void ); extern GType vips_foreign_save_heif_buffer_get_type( void ); extern GType vips_foreign_save_heif_target_get_type( void ); + extern GType vips_foreign_save_avif_target_get_type( void ); #ifdef HAVE_HEIF_DECODER vips_foreign_load_heif_file_get_type(); @@ -74,9 +74,9 @@ g_module_check_init( GModule *module ) #ifdef HAVE_HEIF_ENCODER vips_foreign_save_heif_file_get_type(); - vips_foreign_save_avif_file_get_type(); vips_foreign_save_heif_buffer_get_type(); vips_foreign_save_heif_target_get_type(); + vips_foreign_save_avif_target_get_type(); #endif /*HAVE_HEIF_ENCODER*/ return( NULL ); diff --git a/libvips/module/magick.c b/libvips/module/magick.c index afd635888b..e601fb8bb4 100644 --- a/libvips/module/magick.c +++ b/libvips/module/magick.c @@ -63,7 +63,9 @@ g_module_check_init( GModule *module ) extern GType vips_foreign_load_magick7_file_get_type( void ); extern GType vips_foreign_load_magick7_buffer_get_type( void ); extern GType vips_foreign_save_magick_file_get_type( void ); + extern GType vips_foreign_save_magick_bmp_file_get_type( void ); extern GType vips_foreign_save_magick_buffer_get_type( void ); + extern GType vips_foreign_save_magick_bmp_buffer_get_type( void ); #ifdef ENABLE_MAGICKLOAD #ifdef HAVE_MAGICK6 @@ -79,7 +81,9 @@ g_module_check_init( GModule *module ) #ifdef ENABLE_MAGICKSAVE vips_foreign_save_magick_file_get_type(); + vips_foreign_save_magick_bmp_file_get_type(); vips_foreign_save_magick_buffer_get_type(); + vips_foreign_save_magick_bmp_buffer_get_type(); #endif /*ENABLE_MAGICKSAVE*/ return( NULL ); From 5f6b13f296a27a46aa6c92af2748ab47bf1fabf7 Mon Sep 17 00:00:00 2001 From: Kleis Auke Wolthuizen Date: Thu, 28 Oct 2021 14:08:01 +0200 Subject: [PATCH 11/20] Set ->flags instead To ensure that these subclasses are also skipped in `cplusplus/gen-operators.py`. --- libvips/foreign/heifsave.c | 3 ++- libvips/foreign/ppmsave.c | 6 ++++-- libvips/foreign/vips2magick.c | 6 ++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/libvips/foreign/heifsave.c b/libvips/foreign/heifsave.c index ecf437dd9f..fb9efee0c3 100644 --- a/libvips/foreign/heifsave.c +++ b/libvips/foreign/heifsave.c @@ -755,6 +755,7 @@ vips_foreign_save_avif_target_class_init( GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; VipsForeignClass *foreign_class = (VipsForeignClass *) class; + VipsOperationClass *operation_class = (VipsOperationClass *) class; gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; @@ -767,7 +768,7 @@ vips_foreign_save_avif_target_class_init( /* Hide from UI. */ - object_class->deprecated = TRUE; + operation_class->flags = VIPS_OPERATION_DEPRECATED; } static void diff --git a/libvips/foreign/ppmsave.c b/libvips/foreign/ppmsave.c index b29fe989c1..ed9fcfcf54 100644 --- a/libvips/foreign/ppmsave.c +++ b/libvips/foreign/ppmsave.c @@ -682,6 +682,7 @@ vips_foreign_save_pgm_target_class_init( GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; VipsForeignClass *foreign_class = (VipsForeignClass *) class; + VipsOperationClass *operation_class = (VipsOperationClass *) class; gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; @@ -694,7 +695,7 @@ vips_foreign_save_pgm_target_class_init( /* Hide from UI. */ - object_class->deprecated = TRUE; + operation_class->flags = VIPS_OPERATION_DEPRECATED; } static void @@ -727,6 +728,7 @@ vips_foreign_save_pfm_target_class_init( GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; VipsForeignClass *foreign_class = (VipsForeignClass *) class; + VipsOperationClass *operation_class = (VipsOperationClass *) class; gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; @@ -739,7 +741,7 @@ vips_foreign_save_pfm_target_class_init( /* Hide from UI. */ - object_class->deprecated = TRUE; + operation_class->flags = VIPS_OPERATION_DEPRECATED; } static void diff --git a/libvips/foreign/vips2magick.c b/libvips/foreign/vips2magick.c index 09f9cc55c5..d2b5d8c4c9 100644 --- a/libvips/foreign/vips2magick.c +++ b/libvips/foreign/vips2magick.c @@ -581,6 +581,7 @@ vips_foreign_save_magick_bmp_file_class_init( VipsForeignSaveMagickBmpFileClass GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; VipsForeignClass *foreign_class = (VipsForeignClass *) class; + VipsOperationClass *operation_class = (VipsOperationClass *) class; gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; @@ -593,7 +594,7 @@ vips_foreign_save_magick_bmp_file_class_init( VipsForeignSaveMagickBmpFileClass /* Hide from UI. */ - object_class->deprecated = TRUE; + operation_class->flags = VIPS_OPERATION_DEPRECATED; } static void @@ -699,6 +700,7 @@ vips_foreign_save_magick_bmp_buffer_class_init( GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; VipsForeignClass *foreign_class = (VipsForeignClass *) class; + VipsOperationClass *operation_class = (VipsOperationClass *) class; gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; @@ -711,7 +713,7 @@ vips_foreign_save_magick_bmp_buffer_class_init( /* Hide from UI. */ - object_class->deprecated = TRUE; + operation_class->flags = VIPS_OPERATION_DEPRECATED; } static void From 850876147f6c05b2908f5bb4de1e8d92fcd4907e Mon Sep 17 00:00:00 2001 From: Kleis Auke Wolthuizen Date: Thu, 28 Oct 2021 14:09:51 +0200 Subject: [PATCH 12/20] Still check for pbm format --- libvips/foreign/ppmsave.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libvips/foreign/ppmsave.c b/libvips/foreign/ppmsave.c index ed9fcfcf54..7188beef76 100644 --- a/libvips/foreign/ppmsave.c +++ b/libvips/foreign/ppmsave.c @@ -244,7 +244,8 @@ vips_foreign_save_ppm_build( VipsObject *object ) target_format = image->BandFmt; target_interpretation = image->Type; - if( g_ascii_strcasecmp( ppm->format, "pgm" ) == 0 ) + if( g_ascii_strcasecmp( ppm->format, "pbm" ) == 0 || + g_ascii_strcasecmp( ppm->format, "pgm" ) == 0 ) target_interpretation = VIPS_INTERPRETATION_B_W; else if( g_ascii_strcasecmp( ppm->format, "ppm" ) == 0 ) target_interpretation = VIPS_INTERPRETATION_sRGB; From 49a7709180e3c114482e2d3ea784696b3dc7ff92 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 28 Oct 2021 13:27:46 +0100 Subject: [PATCH 13/20] remove ppmsave_buffer let's get pyvips etc. to use the target API instead --- ChangeLog | 2 +- libvips/foreign/foreign.c | 2 - libvips/foreign/ppmsave.c | 110 --------------------------------- libvips/include/vips/foreign.h | 2 - 4 files changed, 1 insertion(+), 115 deletions(-) diff --git a/ChangeLog b/ChangeLog index 03e98098eb..0fe89041b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,7 +14,7 @@ - added restart_interval option to jpegsave [manthey] - add IIIF3 support to dzsaave [martimpassos] - add atan2 [indus] -- add vips_ppmsave_buffer() +- improve buffer and target save file format selection 16/8/21 started 8.11.4 - fix off-by-one error in new rank fast path diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index 5111e22f87..e93555577e 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -2783,7 +2783,6 @@ vips_foreign_operation_init( void ) extern GType vips_foreign_load_ppm_file_get_type( void ); extern GType vips_foreign_load_ppm_source_get_type( void ); extern GType vips_foreign_save_ppm_file_get_type( void ); - extern GType vips_foreign_save_ppm_buffer_get_type( void ); extern GType vips_foreign_save_ppm_target_get_type( void ); extern GType vips_foreign_save_pgm_target_get_type( void ); extern GType vips_foreign_save_pfm_target_get_type( void ); @@ -2929,7 +2928,6 @@ vips_foreign_operation_init( void ) vips_foreign_load_ppm_file_get_type(); vips_foreign_load_ppm_source_get_type(); vips_foreign_save_ppm_file_get_type(); - vips_foreign_save_ppm_buffer_get_type(); vips_foreign_save_ppm_target_get_type(); vips_foreign_save_pgm_target_get_type(); vips_foreign_save_pfm_target_get_type(); diff --git a/libvips/foreign/ppmsave.c b/libvips/foreign/ppmsave.c index b29fe989c1..38ec91ac78 100644 --- a/libvips/foreign/ppmsave.c +++ b/libvips/foreign/ppmsave.c @@ -540,70 +540,6 @@ vips_foreign_save_ppm_file_init( VipsForeignSavePpmFile *file ) { } -typedef struct _VipsForeignSavePpmBuffer { - VipsForeignSavePpm parent_object; - - /* Save to a buffer. - */ - VipsArea *buf; - -} VipsForeignSavePpmBuffer; - -typedef VipsForeignSavePpmClass VipsForeignSavePpmBufferClass; - -G_DEFINE_TYPE( VipsForeignSavePpmBuffer, vips_foreign_save_ppm_buffer, - vips_foreign_save_ppm_get_type() ); - -static int -vips_foreign_save_ppm_buffer_build( VipsObject *object ) -{ - VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) object; - VipsForeignSavePpmBuffer *buffer = - (VipsForeignSavePpmBuffer *) object; - - VipsBlob *blob; - - if( !(ppm->target = vips_target_new_to_memory()) ) - return( -1 ); - - if( VIPS_OBJECT_CLASS( vips_foreign_save_ppm_buffer_parent_class )-> - build( object ) ) - return( -1 ); - - g_object_get( ppm->target, "blob", &blob, NULL ); - g_object_set( buffer, "buffer", blob, NULL ); - vips_area_unref( VIPS_AREA( blob ) ); - - return( 0 ); -} - -static void -vips_foreign_save_ppm_buffer_class_init( - VipsForeignSavePpmBufferClass *class ) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS( class ); - VipsObjectClass *object_class = (VipsObjectClass *) class; - - gobject_class->set_property = vips_object_set_property; - gobject_class->get_property = vips_object_get_property; - - object_class->nickname = "ppmsave_buffer"; - object_class->build = vips_foreign_save_ppm_buffer_build; - - VIPS_ARG_BOXED( class, "buffer", 1, - _( "Buffer" ), - _( "Buffer to save to" ), - VIPS_ARGUMENT_REQUIRED_OUTPUT, - G_STRUCT_OFFSET( VipsForeignSavePpmBuffer, buf ), - VIPS_TYPE_BLOB ); - -} - -static void -vips_foreign_save_ppm_buffer_init( VipsForeignSavePpmBuffer *buffer ) -{ -} - typedef struct _VipsForeignSavePpmTarget { VipsForeignSavePpm parent_object; @@ -792,52 +728,6 @@ vips_ppmsave( VipsImage *in, const char *filename, ... ) return( result ); } -/** - * vips_ppmsave_buffer: (method) - * @in: image to save - * @buf: (array length=len) (element-type guint8): return output buffer here - * @len: (type gsize): return output length here - * @...: %NULL-terminated list of optional named arguments - * - * Optional arguments: - * - * * @ascii: %gboolean, save as ASCII rather than binary - * * @bitdepth: %gint, bitdepth to save at - * - * As vips_ppmsave(), but save to a target. - * - * See also: vips_ppmsave(). - * - * Returns: 0 on success, -1 on error. - */ -int -vips_ppmsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) -{ - va_list ap; - VipsArea *area; - int result; - - area = NULL; - - va_start( ap, len ); - result = vips_call_split( "ppmsave_buffer", ap, in, &area ); - va_end( ap ); - - if( !result && - area ) { - if( buf ) { - *buf = area->data; - area->free_fn = NULL; - } - if( len ) - *len = area->length; - - vips_area_unref( area ); - } - - return( result ); -} - /** * vips_ppmsave_target: (method) * @in: image to save diff --git a/libvips/include/vips/foreign.h b/libvips/include/vips/foreign.h index 3e5e5ca4c7..e8d0d1acfd 100644 --- a/libvips/include/vips/foreign.h +++ b/libvips/include/vips/foreign.h @@ -618,8 +618,6 @@ int vips_ppmload_source( VipsSource *source, VipsImage **out, ... ) __attribute__((sentinel)); int vips_ppmsave( VipsImage *in, const char *filename, ... ) __attribute__((sentinel)); -int vips_ppmsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) - __attribute__((sentinel)); int vips_ppmsave_target( VipsImage *in, VipsTarget *target, ... ) __attribute__((sentinel)); From 19c6d25f59b6c1b22a19ef7f7eb06a7e4d79e7da Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 28 Oct 2021 14:35:16 +0100 Subject: [PATCH 14/20] heifsave to file supports all suffixes --- libvips/foreign/heifsave.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libvips/foreign/heifsave.c b/libvips/foreign/heifsave.c index fb9efee0c3..ca861b18db 100644 --- a/libvips/foreign/heifsave.c +++ b/libvips/foreign/heifsave.c @@ -479,7 +479,6 @@ vips_foreign_save_heif_class_init( VipsForeignSaveHeifClass *class ) { GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; - VipsForeignClass *foreign_class = (VipsForeignClass *) class; VipsForeignSaveClass *save_class = (VipsForeignSaveClass *) class; gobject_class->dispose = vips_foreign_save_heif_dispose; @@ -490,8 +489,6 @@ vips_foreign_save_heif_class_init( VipsForeignSaveHeifClass *class ) object_class->description = _( "save image in HEIF format" ); object_class->build = vips_foreign_save_heif_build; - foreign_class->suffs = vips__heic_suffs; - save_class->saveable = VIPS_SAVEABLE_RGBA_ONLY; save_class->format_table = vips_heif_bandfmt; @@ -578,6 +575,9 @@ vips_foreign_save_heif_file_build( VipsObject *object ) if( !(heif->target = vips_target_new_to_file( file->filename )) ) return( -1 ); + if( vips_iscasepostfix( file->filename, ".avif" ) ) + heif->compression = VIPS_FOREIGN_HEIF_COMPRESSION_AV1; + if( VIPS_OBJECT_CLASS( vips_foreign_save_heif_file_parent_class )-> build( object ) ) return( -1 ); @@ -590,6 +590,7 @@ vips_foreign_save_heif_file_class_init( VipsForeignSaveHeifFileClass *class ) { GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsForeignClass *foreign_class = (VipsForeignClass *) class; gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; @@ -597,6 +598,8 @@ vips_foreign_save_heif_file_class_init( VipsForeignSaveHeifFileClass *class ) object_class->nickname = "heifsave"; object_class->build = vips_foreign_save_heif_file_build; + foreign_class->suffs = vips__heif_suffs; + VIPS_ARG_STRING( class, "filename", 1, _( "Filename" ), _( "Filename to save to" ), From 18be2e8f8ab4e335849a879eb0ca224158188e6f Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 28 Oct 2021 14:45:41 +0100 Subject: [PATCH 15/20] ppm/pfm/pgm target save sets the suffs and fix up heif a bit too --- libvips/foreign/heifsave.c | 6 ++++++ libvips/foreign/pforeign.h | 1 + libvips/foreign/ppmload.c | 2 ++ libvips/foreign/ppmsave.c | 9 ++++++--- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/libvips/foreign/heifsave.c b/libvips/foreign/heifsave.c index ca861b18db..7044a2e10c 100644 --- a/libvips/foreign/heifsave.c +++ b/libvips/foreign/heifsave.c @@ -657,6 +657,7 @@ vips_foreign_save_heif_buffer_class_init( { GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsForeignClass *foreign_class = (VipsForeignClass *) class; gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; @@ -664,6 +665,8 @@ vips_foreign_save_heif_buffer_class_init( object_class->nickname = "heifsave_buffer"; object_class->build = vips_foreign_save_heif_buffer_build; + foreign_class->suffs = vips__heic_suffs; + VIPS_ARG_BOXED( class, "buffer", 1, _( "Buffer" ), _( "Buffer to save to" ), @@ -714,6 +717,7 @@ vips_foreign_save_heif_target_class_init( { GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsForeignClass *foreign_class = (VipsForeignClass *) class; gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; @@ -721,6 +725,8 @@ vips_foreign_save_heif_target_class_init( object_class->nickname = "heifsave_target"; object_class->build = vips_foreign_save_heif_target_build; + foreign_class->suffs = vips__heic_suffs; + VIPS_ARG_OBJECT( class, "target", 1, _( "Target" ), _( "Target to save to" ), diff --git a/libvips/foreign/pforeign.h b/libvips/foreign/pforeign.h index 04adf82c6a..2b67038a0a 100644 --- a/libvips/foreign/pforeign.h +++ b/libvips/foreign/pforeign.h @@ -161,6 +161,7 @@ extern const char *vips__load_ppm_suffs[]; extern const char *vips__save_ppm_suffs[]; extern const char *vips__save_pgm_suffs[]; extern const char *vips__save_pfm_suffs[]; +extern const char *vips__save_ppm_all_suffs[]; int vips__ppm_save_target( VipsImage *in, VipsTarget *target, gboolean ascii, gboolean squash ); diff --git a/libvips/foreign/ppmload.c b/libvips/foreign/ppmload.c index 6106dc79d9..b61de9a2d4 100644 --- a/libvips/foreign/ppmload.c +++ b/libvips/foreign/ppmload.c @@ -145,6 +145,8 @@ const char *vips__load_ppm_suffs[] = { ".ppm", ".pgm", ".pbm", ".pfm", NULL }; const char *vips__save_ppm_suffs[] = { ".ppm", NULL }; const char *vips__save_pgm_suffs[] = { ".pgm", ".pbm", NULL }; const char *vips__save_pfm_suffs[] = { ".pfm", NULL }; +const char *vips__save_ppm_all_suffs[] = + { ".ppm", ".pgm", ".pbm", ".pfm", NULL }; static gboolean vips_foreign_load_ppm_is_a_source( VipsSource *source ) diff --git a/libvips/foreign/ppmsave.c b/libvips/foreign/ppmsave.c index aea9a39b18..9ccdad6f5d 100644 --- a/libvips/foreign/ppmsave.c +++ b/libvips/foreign/ppmsave.c @@ -438,7 +438,6 @@ vips_foreign_save_ppm_class_init( VipsForeignSavePpmClass *class ) { GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; - VipsForeignClass *foreign_class = (VipsForeignClass *) class; VipsForeignSaveClass *save_class = (VipsForeignSaveClass *) class; gobject_class->dispose = vips_foreign_save_ppm_dispose; @@ -449,8 +448,6 @@ vips_foreign_save_ppm_class_init( VipsForeignSavePpmClass *class ) object_class->description = _( "save to ppm" ); object_class->build = vips_foreign_save_ppm_build; - foreign_class->suffs = vips__save_ppm_suffs; - save_class->saveable = VIPS_SAVEABLE_RGB; save_class->format_table = bandfmt_ppm; @@ -519,6 +516,7 @@ vips_foreign_save_ppm_file_class_init( VipsForeignSavePpmFileClass *class ) { GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsForeignClass *foreign_class = (VipsForeignClass *) class; gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; @@ -527,6 +525,8 @@ vips_foreign_save_ppm_file_class_init( VipsForeignSavePpmFileClass *class ) object_class->description = _( "save image to ppm file" ); object_class->build = vips_foreign_save_ppm_file_build; + foreign_class->suffs = vips__save_ppm_all_suffs; + VIPS_ARG_STRING( class, "filename", 1, _( "Filename" ), _( "Filename to save to" ), @@ -575,6 +575,7 @@ vips_foreign_save_ppm_target_class_init( { GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsForeignClass *foreign_class = (VipsForeignClass *) class; gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; @@ -582,6 +583,8 @@ vips_foreign_save_ppm_target_class_init( object_class->nickname = "ppmsave_target"; object_class->build = vips_foreign_save_ppm_target_build; + foreign_class->suffs = vips__save_ppm_suffs; + VIPS_ARG_OBJECT( class, "target", 1, _( "Target" ), _( "Target to save to" ), From ef8d8a240cdfee72553fe03a449fc33279115617 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 28 Oct 2021 14:55:12 +0100 Subject: [PATCH 16/20] hide a spurious error in vips_image_write_to_buffer() --- libvips/iofuncs/image.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index c59f28a773..6f93cb8deb 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -2750,7 +2750,11 @@ vips_image_write_to_buffer( VipsImage *in, vips__filename_split8( suffix, filename, option_string ); - if( (operation_name = vips_foreign_find_save_target( filename )) ) { + vips_error_freeze(); + operation_name = vips_foreign_find_save_target( filename ); + vips_error_thaw(); + + if( operation_name ) { VipsTarget *target; if( !(target = vips_target_new_to_memory()) ) From 9b182a053436ae4f93786436217c43f572842afe Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 28 Oct 2021 17:10:57 +0100 Subject: [PATCH 17/20] add an enum for ppm format and add a @format param to ppmsave --- ChangeLog | 1 + libvips/foreign/foreign.c | 6 +- libvips/foreign/pforeign.h | 6 +- libvips/foreign/ppmload.c | 9 +- libvips/foreign/ppmsave.c | 154 ++++++++++++++++++------------- libvips/include/vips/enumtypes.h | 2 + libvips/include/vips/foreign.h | 25 +++++ libvips/iofuncs/enumtypes.c | 20 ++++ 8 files changed, 149 insertions(+), 74 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0fe89041b8..2eb8575bfb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,7 @@ - add IIIF3 support to dzsaave [martimpassos] - add atan2 [indus] - improve buffer and target save file format selection +- added VipsForeignPpmFormat, @format arg to ppm savers 16/8/21 started 8.11.4 - fix off-by-one error in new rank fast path diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index e93555577e..07e2199e65 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -2783,8 +2783,9 @@ vips_foreign_operation_init( void ) extern GType vips_foreign_load_ppm_file_get_type( void ); extern GType vips_foreign_load_ppm_source_get_type( void ); extern GType vips_foreign_save_ppm_file_get_type( void ); - extern GType vips_foreign_save_ppm_target_get_type( void ); + extern GType vips_foreign_save_pbm_target_get_type( void ); extern GType vips_foreign_save_pgm_target_get_type( void ); + extern GType vips_foreign_save_ppm_target_get_type( void ); extern GType vips_foreign_save_pfm_target_get_type( void ); extern GType vips_foreign_load_png_file_get_type( void ); @@ -2928,8 +2929,9 @@ vips_foreign_operation_init( void ) vips_foreign_load_ppm_file_get_type(); vips_foreign_load_ppm_source_get_type(); vips_foreign_save_ppm_file_get_type(); - vips_foreign_save_ppm_target_get_type(); + vips_foreign_save_pbm_target_get_type(); vips_foreign_save_pgm_target_get_type(); + vips_foreign_save_ppm_target_get_type(); vips_foreign_save_pfm_target_get_type(); #endif /*HAVE_PPM*/ diff --git a/libvips/foreign/pforeign.h b/libvips/foreign/pforeign.h index 2b67038a0a..44d955f039 100644 --- a/libvips/foreign/pforeign.h +++ b/libvips/foreign/pforeign.h @@ -157,11 +157,11 @@ int vips__mat_load( const char *filename, VipsImage *out ); int vips__mat_header( const char *filename, VipsImage *out ); int vips__mat_ismat( const char *filename ); -extern const char *vips__load_ppm_suffs[]; -extern const char *vips__save_ppm_suffs[]; +extern const char *vips__ppm_suffs[]; +extern const char *vips__save_pbm_suffs[]; extern const char *vips__save_pgm_suffs[]; +extern const char *vips__save_ppm_suffs[]; extern const char *vips__save_pfm_suffs[]; -extern const char *vips__save_ppm_all_suffs[]; int vips__ppm_save_target( VipsImage *in, VipsTarget *target, gboolean ascii, gboolean squash ); diff --git a/libvips/foreign/ppmload.c b/libvips/foreign/ppmload.c index b61de9a2d4..130e3cda42 100644 --- a/libvips/foreign/ppmload.c +++ b/libvips/foreign/ppmload.c @@ -141,12 +141,11 @@ static char *magic_names[] = { /* Shared with ppmsave. */ -const char *vips__load_ppm_suffs[] = { ".ppm", ".pgm", ".pbm", ".pfm", NULL }; +const char *vips__ppm_suffs[] = { ".pbm", ".pgm", ".ppm", ".pfm", NULL }; +const char *vips__save_pbm_suffs[] = { ".pbm", NULL }; +const char *vips__save_pgm_suffs[] = { ".pgm", NULL }; const char *vips__save_ppm_suffs[] = { ".ppm", NULL }; -const char *vips__save_pgm_suffs[] = { ".pgm", ".pbm", NULL }; const char *vips__save_pfm_suffs[] = { ".pfm", NULL }; -const char *vips__save_ppm_all_suffs[] = - { ".ppm", ".pgm", ".pbm", ".pfm", NULL }; static gboolean vips_foreign_load_ppm_is_a_source( VipsSource *source ) @@ -748,7 +747,7 @@ vips_foreign_load_ppm_class_init( VipsForeignLoadPpmClass *class ) object_class->description = _( "load ppm base class" ); object_class->build = vips_foreign_load_ppm_build; - foreign_class->suffs = vips__load_ppm_suffs; + foreign_class->suffs = vips__ppm_suffs; /* We are fast at is_a(), so high priority. */ diff --git a/libvips/foreign/ppmsave.c b/libvips/foreign/ppmsave.c index 9ccdad6f5d..b3f11847ff 100644 --- a/libvips/foreign/ppmsave.c +++ b/libvips/foreign/ppmsave.c @@ -12,6 +12,8 @@ * - byteswap on save, if necessary [ewelot] * 2/12/20 * - don't add date with @strip [ewelot] + * 28/10/21 + * - add @format, default type by filename */ /* @@ -70,7 +72,7 @@ struct _VipsForeignSavePpm { VipsForeignSave parent_object; VipsTarget *target; - char *format; + VipsForeignPpmFormat format; gboolean ascii; int bitdepth; @@ -222,53 +224,61 @@ vips_foreign_save_ppm_build( VipsObject *object ) VipsImage *image; char *magic; char *date; + VipsBandFormat target_format; + VipsInterpretation target_interpretation; if( VIPS_OBJECT_CLASS( vips_foreign_save_ppm_parent_class )-> build( object ) ) return( -1 ); image = save->ready; + target_format = image->BandFmt; + target_interpretation = image->Type; - /* ppm types. We use the suffix (if avail.) to set the defaults for - * bitdepth etc. + /* ppm types to set the defaults for bitdepth etc. * * pbm ... 1 band 1 bit * pgm ... 1 band many bit * ppm ... 3 band many bit * pfm ... 1 or 3 bands, 32 bit */ - if( ppm->format ) { - VipsBandFormat target_format; - VipsInterpretation target_interpretation; - - target_format = image->BandFmt; - target_interpretation = image->Type; - - if( g_ascii_strcasecmp( ppm->format, "pbm" ) == 0 || - g_ascii_strcasecmp( ppm->format, "pgm" ) == 0 ) + switch( ppm->format ) { + case VIPS_FOREIGN_PPM_FORMAT_PBM: + if( !vips_object_argument_isset( object, "bitdepth" ) ) + ppm->bitdepth = 1; + target_interpretation = VIPS_INTERPRETATION_B_W; + break; + + case VIPS_FOREIGN_PPM_FORMAT_PGM: + if( target_format == VIPS_FORMAT_USHORT ) + target_interpretation = VIPS_INTERPRETATION_GREY16; + else target_interpretation = VIPS_INTERPRETATION_B_W; - else if( g_ascii_strcasecmp( ppm->format, "ppm" ) == 0 ) - target_interpretation = VIPS_INTERPRETATION_sRGB; - else if( g_ascii_strcasecmp( ppm->format, "pfm" ) == 0 ) - target_format = VIPS_FORMAT_FLOAT; + break; - if( target_format == VIPS_FORMAT_USHORT && - target_interpretation == VIPS_INTERPRETATION_B_W ) - target_interpretation = VIPS_INTERPRETATION_GREY16; - if( target_format == VIPS_FORMAT_USHORT && - target_interpretation == VIPS_INTERPRETATION_sRGB ) + case VIPS_FOREIGN_PPM_FORMAT_PPM: + if( target_format == VIPS_FORMAT_USHORT ) target_interpretation = VIPS_INTERPRETATION_RGB16; + else + target_interpretation = VIPS_INTERPRETATION_sRGB; + break; - if( vips_cast( image, &t[0], target_format, NULL ) ) - return( -1 ); - image = t[0]; + case VIPS_FOREIGN_PPM_FORMAT_PFM: + target_format = VIPS_FORMAT_FLOAT; + break; - if( image->Type != target_interpretation ) { - if( vips_colourspace( image, &t[1], - target_interpretation, NULL ) ) - return( -1 ); - image = t[1]; - } + default: + } + + if( vips_cast( image, &t[0], target_format, NULL ) ) + return( -1 ); + image = t[0]; + + if( image->Type != target_interpretation ) { + if( vips_colourspace( image, &t[1], + target_interpretation, NULL ) ) + return( -1 ); + image = t[1]; } /* Handle the deprecated squash parameter. @@ -451,12 +461,13 @@ vips_foreign_save_ppm_class_init( VipsForeignSavePpmClass *class ) save_class->saveable = VIPS_SAVEABLE_RGB; save_class->format_table = bandfmt_ppm; - VIPS_ARG_STRING( class, "format", 2, + VIPS_ARG_ENUM( class, "format", 2, _( "Format" ), _( "Format to save in" ), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET( VipsForeignSavePpm, format ), - NULL ); + VIPS_TYPE_FOREIGN_PPM_FORMAT, + VIPS_FOREIGN_PPM_FORMAT_PPM ); VIPS_ARG_BOOL( class, "ascii", 10, _( "ASCII" ), @@ -484,6 +495,7 @@ vips_foreign_save_ppm_class_init( VipsForeignSavePpmClass *class ) static void vips_foreign_save_ppm_init( VipsForeignSavePpm *ppm ) { + ppm->format = VIPS_FOREIGN_PPM_FORMAT_PPM; } typedef struct _VipsForeignSavePpmFile { @@ -507,6 +519,12 @@ vips_foreign_save_ppm_file_build( VipsObject *object ) !(ppm->target = vips_target_new_to_file( file->filename )) ) return( -1 ); + if( vips_iscasepostfix( file->filename, ".pbm" ) || + vips_iscasepostfix( file->filename, ".pgm" ) ) + ppm->format = VIPS_FOREIGN_PPM_FORMAT_PGM; + else if( vips_iscasepostfix( file->filename, ".pfm" ) ) + ppm->format = VIPS_FOREIGN_PPM_FORMAT_PFM; + return( VIPS_OBJECT_CLASS( vips_foreign_save_ppm_file_parent_class )-> build( object ) ); } @@ -525,7 +543,7 @@ vips_foreign_save_ppm_file_class_init( VipsForeignSavePpmFileClass *class ) object_class->description = _( "save image to ppm file" ); object_class->build = vips_foreign_save_ppm_file_build; - foreign_class->suffs = vips__save_ppm_all_suffs; + foreign_class->suffs = vips__ppm_suffs; VIPS_ARG_STRING( class, "filename", 1, _( "Filename" ), @@ -599,37 +617,54 @@ vips_foreign_save_ppm_target_init( VipsForeignSavePpmTarget *target ) { } -typedef VipsForeignSavePpmTarget VipsForeignSavePgmTarget; -typedef VipsForeignSavePpmTargetClass VipsForeignSavePgmTargetClass; +typedef VipsForeignSavePpmTarget VipsForeignSavePbmTarget; +typedef VipsForeignSavePpmTargetClass VipsForeignSavePbmTargetClass; -G_DEFINE_TYPE( VipsForeignSavePgmTarget, vips_foreign_save_pgm_target, +G_DEFINE_TYPE( VipsForeignSavePbmTarget, vips_foreign_save_pbm_target, vips_foreign_save_ppm_target_get_type() ); -static int -vips_foreign_save_pgm_target_build( VipsObject *object ) +static void +vips_foreign_save_pbm_target_class_init( + VipsForeignSavePbmTargetClass *class ) { - if( VIPS_OBJECT_CLASS( vips_foreign_save_pgm_target_parent_class )-> - build( object ) ) - return( -1 ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsForeignClass *foreign_class = (VipsForeignClass *) class; + VipsOperationClass *operation_class = (VipsOperationClass *) class; - return( 0 ); + object_class->nickname = "pbmsave_target"; + object_class->description = _( "save image in pbm format" ); + + foreign_class->suffs = vips__save_pbm_suffs; + + /* Hide from UI. + */ + operation_class->flags = VIPS_OPERATION_DEPRECATED; } +static void +vips_foreign_save_pbm_target_init( VipsForeignSavePbmTarget *target ) +{ + VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) target; + + ppm->format = VIPS_FOREIGN_PPM_FORMAT_PBM; +} + +typedef VipsForeignSavePpmTarget VipsForeignSavePgmTarget; +typedef VipsForeignSavePpmTargetClass VipsForeignSavePgmTargetClass; + +G_DEFINE_TYPE( VipsForeignSavePgmTarget, vips_foreign_save_pgm_target, + vips_foreign_save_ppm_target_get_type() ); + static void vips_foreign_save_pgm_target_class_init( VipsForeignSavePgmTargetClass *class ) { - GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; VipsForeignClass *foreign_class = (VipsForeignClass *) class; VipsOperationClass *operation_class = (VipsOperationClass *) class; - gobject_class->set_property = vips_object_set_property; - gobject_class->get_property = vips_object_get_property; - object_class->nickname = "pgmsave_target"; object_class->description = _( "save image in pgm format" ); - object_class->build = vips_foreign_save_pgm_target_build; foreign_class->suffs = vips__save_pgm_suffs; @@ -642,7 +677,8 @@ static void vips_foreign_save_pgm_target_init( VipsForeignSavePgmTarget *target ) { VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) target; - VIPS_SETSTR( ppm->format, "pgm" ); + + ppm->format = VIPS_FOREIGN_PPM_FORMAT_PGM; } typedef VipsForeignSavePpmTarget VipsForeignSavePfmTarget; @@ -651,31 +687,16 @@ typedef VipsForeignSavePpmTargetClass VipsForeignSavePfmTargetClass; G_DEFINE_TYPE( VipsForeignSavePfmTarget, vips_foreign_save_pfm_target, vips_foreign_save_ppm_target_get_type() ); -static int -vips_foreign_save_pfm_target_build( VipsObject *object ) -{ - if( VIPS_OBJECT_CLASS( vips_foreign_save_pfm_target_parent_class )-> - build( object ) ) - return( -1 ); - - return( 0 ); -} - static void vips_foreign_save_pfm_target_class_init( VipsForeignSavePfmTargetClass *class ) { - GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; VipsForeignClass *foreign_class = (VipsForeignClass *) class; VipsOperationClass *operation_class = (VipsOperationClass *) class; - gobject_class->set_property = vips_object_set_property; - gobject_class->get_property = vips_object_get_property; - object_class->nickname = "pfmsave_target"; object_class->description = _( "save image in pfm format" ); - object_class->build = vips_foreign_save_pfm_target_build; foreign_class->suffs = vips__save_pfm_suffs; @@ -688,7 +709,8 @@ static void vips_foreign_save_pfm_target_init( VipsForeignSavePfmTarget *target ) { VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) target; - VIPS_SETSTR( ppm->format, "pfm" ); + + ppm->format = VIPS_FOREIGN_PPM_FORMAT_PFM; } #endif /*HAVE_PPM*/ @@ -701,6 +723,7 @@ vips_foreign_save_pfm_target_init( VipsForeignSavePfmTarget *target ) * * Optional arguments: * + * * @format: #VipsForeignPpmFormat, format to save in * * @ascii: %gboolean, save as ASCII rather than binary * * @bitdepth: %gint, bitdepth to save at * @@ -717,6 +740,8 @@ vips_foreign_save_pfm_target_init( VipsForeignSavePfmTarget *target ) * * Set @bitdepth to 1 to write a one-bit image. * + * @format defaults to the sub-type for this filename suffix. + * * See also: vips_image_write_to_file(). * * Returns: 0 on success, -1 on error. @@ -742,6 +767,7 @@ vips_ppmsave( VipsImage *in, const char *filename, ... ) * * Optional arguments: * + * * @format: #VipsForeignPpmFormat, format to save in * * @ascii: %gboolean, save as ASCII rather than binary * * @bitdepth: %gint, bitdepth to save at * diff --git a/libvips/include/vips/enumtypes.h b/libvips/include/vips/enumtypes.h index 8cb85a9edf..772e14a179 100644 --- a/libvips/include/vips/enumtypes.h +++ b/libvips/include/vips/enumtypes.h @@ -72,6 +72,8 @@ GType vips_foreign_tiff_resunit_get_type (void) G_GNUC_CONST; #define VIPS_TYPE_FOREIGN_TIFF_RESUNIT (vips_foreign_tiff_resunit_get_type()) GType vips_foreign_png_filter_get_type (void) G_GNUC_CONST; #define VIPS_TYPE_FOREIGN_PNG_FILTER (vips_foreign_png_filter_get_type()) +GType vips_foreign_ppm_format_get_type (void) G_GNUC_CONST; +#define VIPS_TYPE_FOREIGN_PPM_FORMAT (vips_foreign_ppm_format_get_type()) GType vips_foreign_dz_layout_get_type (void) G_GNUC_CONST; #define VIPS_TYPE_FOREIGN_DZ_LAYOUT (vips_foreign_dz_layout_get_type()) GType vips_foreign_dz_depth_get_type (void) G_GNUC_CONST; diff --git a/libvips/include/vips/foreign.h b/libvips/include/vips/foreign.h index e8d0d1acfd..ac58f946ae 100644 --- a/libvips/include/vips/foreign.h +++ b/libvips/include/vips/foreign.h @@ -612,6 +612,31 @@ int vips_pngsave( VipsImage *in, const char *filename, ... ) int vips_pngsave_buffer( VipsImage *in, void **buf, size_t *len, ... ) __attribute__((sentinel)); +/** + * VipsForeignPpmFormat: + * @VIPS_FOREIGN_PPM_PBM: portable bitmap + * @VIPS_FOREIGN_PPM_PGM: portable greymap + * @VIPS_FOREIGN_PPM_PPM: portable pixmap + * @VIPS_FOREIGN_PPM_PFM: portable float map + * + * The netpbm file format to save as. + * + * #VIPS_FOREIGN_PPM_PBM images are single bit. + * + * #VIPS_FOREIGN_PPM_PGB images are 8, 16, or 32-bits, one band. + * + * #VIPS_FOREIGN_PPM_PPM images are 8, 16, or 32-bits, three bands. + * + * #VIPS_FOREIGN_PPM_PFM images are 32-bit float pixels. + */ +typedef enum { + VIPS_FOREIGN_PPM_FORMAT_PBM, + VIPS_FOREIGN_PPM_FORMAT_PGM, + VIPS_FOREIGN_PPM_FORMAT_PPM, + VIPS_FOREIGN_PPM_FORMAT_PFM, + VIPS_FOREIGN_PPM_FORMAT_LAST +} VipsForeignPpmFormat; + int vips_ppmload( const char *filename, VipsImage **out, ... ) __attribute__((sentinel)); int vips_ppmload_source( VipsSource *source, VipsImage **out, ... ) diff --git a/libvips/iofuncs/enumtypes.c b/libvips/iofuncs/enumtypes.c index a752ae414f..0109ed3013 100644 --- a/libvips/iofuncs/enumtypes.c +++ b/libvips/iofuncs/enumtypes.c @@ -644,6 +644,26 @@ vips_foreign_png_filter_get_type( void ) return( etype ); } GType +vips_foreign_ppm_format_get_type( void ) +{ + static GType etype = 0; + + if( etype == 0 ) { + static const GEnumValue values[] = { + {VIPS_FOREIGN_PPM_FORMAT_PBM, "VIPS_FOREIGN_PPM_FORMAT_PBM", "pbm"}, + {VIPS_FOREIGN_PPM_FORMAT_PGM, "VIPS_FOREIGN_PPM_FORMAT_PGM", "pgm"}, + {VIPS_FOREIGN_PPM_FORMAT_PPM, "VIPS_FOREIGN_PPM_FORMAT_PPM", "ppm"}, + {VIPS_FOREIGN_PPM_FORMAT_PFM, "VIPS_FOREIGN_PPM_FORMAT_PFM", "pfm"}, + {VIPS_FOREIGN_PPM_FORMAT_LAST, "VIPS_FOREIGN_PPM_FORMAT_LAST", "last"}, + {0, NULL, NULL} + }; + + etype = g_enum_register_static( "VipsForeignPpmFormat", values ); + } + + return( etype ); +} +GType vips_foreign_dz_layout_get_type( void ) { static GType etype = 0; From 7273232476f0f0905b6317e41e0ae729cbc88722 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 28 Oct 2021 17:19:45 +0100 Subject: [PATCH 18/20] fix compiler warning --- libvips/foreign/heifsave.c | 16 +--------------- libvips/foreign/ppmsave.c | 3 +++ 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/libvips/foreign/heifsave.c b/libvips/foreign/heifsave.c index 7044a2e10c..3256a8a312 100644 --- a/libvips/foreign/heifsave.c +++ b/libvips/foreign/heifsave.c @@ -747,31 +747,16 @@ typedef VipsForeignSaveHeifTargetClass VipsForeignSaveAvifTargetClass; G_DEFINE_TYPE( VipsForeignSaveAvifTarget, vips_foreign_save_avif_target, vips_foreign_save_heif_target_get_type() ); -static int -vips_foreign_save_avif_target_build( VipsObject *object ) -{ - if( VIPS_OBJECT_CLASS( vips_foreign_save_avif_target_parent_class )-> - build( object ) ) - return( -1 ); - - return( 0 ); -} - static void vips_foreign_save_avif_target_class_init( VipsForeignSaveAvifTargetClass *class ) { - GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; VipsForeignClass *foreign_class = (VipsForeignClass *) class; VipsOperationClass *operation_class = (VipsOperationClass *) class; - gobject_class->set_property = vips_object_set_property; - gobject_class->get_property = vips_object_get_property; - object_class->nickname = "avifsave_target"; object_class->description = _( "save image in AVIF format" ); - object_class->build = vips_foreign_save_avif_target_build; foreign_class->suffs = vips__avif_suffs; @@ -784,6 +769,7 @@ static void vips_foreign_save_avif_target_init( VipsForeignSaveAvifTarget *target ) { VipsForeignSaveHeif *heif = (VipsForeignSaveHeif *) target; + heif->compression = VIPS_FOREIGN_HEIF_COMPRESSION_AV1; } diff --git a/libvips/foreign/ppmsave.c b/libvips/foreign/ppmsave.c index b3f11847ff..a1a6f3ab85 100644 --- a/libvips/foreign/ppmsave.c +++ b/libvips/foreign/ppmsave.c @@ -268,6 +268,9 @@ vips_foreign_save_ppm_build( VipsObject *object ) break; default: + /* Harmless. + */ + break; } if( vips_cast( image, &t[0], target_format, NULL ) ) From 94ed22e7f4aaad007756a67ded304a8aae8f209d Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 28 Oct 2021 18:33:54 +0100 Subject: [PATCH 19/20] Update libvips/foreign/ppmsave.c Co-authored-by: Kleis Auke Wolthuizen --- libvips/foreign/ppmsave.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libvips/foreign/ppmsave.c b/libvips/foreign/ppmsave.c index a1a6f3ab85..1ac29303f9 100644 --- a/libvips/foreign/ppmsave.c +++ b/libvips/foreign/ppmsave.c @@ -522,8 +522,9 @@ vips_foreign_save_ppm_file_build( VipsObject *object ) !(ppm->target = vips_target_new_to_file( file->filename )) ) return( -1 ); - if( vips_iscasepostfix( file->filename, ".pbm" ) || - vips_iscasepostfix( file->filename, ".pgm" ) ) + if( vips_iscasepostfix( file->filename, ".pbm" ) ) + ppm->format = VIPS_FOREIGN_PPM_FORMAT_PBM; + else if( vips_iscasepostfix( file->filename, ".pgm" ) ) ppm->format = VIPS_FOREIGN_PPM_FORMAT_PGM; else if( vips_iscasepostfix( file->filename, ".pfm" ) ) ppm->format = VIPS_FOREIGN_PPM_FORMAT_PFM; From 7c33d20b526bffa2e5353ff1c4b1cf76f3739d97 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 28 Oct 2021 18:40:00 +0100 Subject: [PATCH 20/20] remove some unneeded code in magick --- libvips/foreign/vips2magick.c | 41 +++++++---------------------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/libvips/foreign/vips2magick.c b/libvips/foreign/vips2magick.c index d2b5d8c4c9..c2b3c30508 100644 --- a/libvips/foreign/vips2magick.c +++ b/libvips/foreign/vips2magick.c @@ -565,30 +565,16 @@ typedef VipsForeignSaveMagickFileClass VipsForeignSaveMagickBmpFileClass; G_DEFINE_TYPE( VipsForeignSaveMagickBmpFile, vips_foreign_save_magick_bmp_file, vips_foreign_save_magick_file_get_type() ); -static int -vips_foreign_save_magick_bmp_file_build( VipsObject *object ) -{ - if( VIPS_OBJECT_CLASS( vips_foreign_save_magick_bmp_file_parent_class )-> - build( object ) ) - return( -1 ); - - return( 0 ); -} - static void -vips_foreign_save_magick_bmp_file_class_init( VipsForeignSaveMagickBmpFileClass *class ) +vips_foreign_save_magick_bmp_file_class_init( + VipsForeignSaveMagickBmpFileClass *class ) { - GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; VipsForeignClass *foreign_class = (VipsForeignClass *) class; VipsOperationClass *operation_class = (VipsOperationClass *) class; - gobject_class->set_property = vips_object_set_property; - gobject_class->get_property = vips_object_get_property; - object_class->nickname = "magicksave_bmp"; object_class->description = _( "save bmp image with ImageMagick" ); - object_class->build = vips_foreign_save_magick_bmp_file_build; foreign_class->suffs = vips__save_magick_bmp_suffs; @@ -601,6 +587,7 @@ static void vips_foreign_save_magick_bmp_file_init( VipsForeignSaveMagickBmpFile *file ) { VipsForeignSaveMagick *magick = (VipsForeignSaveMagick *) file; + VIPS_SETSTR( magick->format, "bmp" ); } @@ -680,34 +667,20 @@ vips_foreign_save_magick_buffer_init( VipsForeignSaveMagickBuffer *buffer ) typedef VipsForeignSaveMagickBuffer VipsForeignSaveMagickBmpBuffer; typedef VipsForeignSaveMagickBufferClass VipsForeignSaveMagickBmpBufferClass; -G_DEFINE_TYPE( VipsForeignSaveMagickBmpBuffer, vips_foreign_save_magick_bmp_buffer, +G_DEFINE_TYPE( VipsForeignSaveMagickBmpBuffer, + vips_foreign_save_magick_bmp_buffer, vips_foreign_save_magick_buffer_get_type() ); -static int -vips_foreign_save_magick_bmp_buffer_build( VipsObject *object ) -{ - if( VIPS_OBJECT_CLASS( vips_foreign_save_magick_bmp_buffer_parent_class )-> - build( object ) ) - return( -1 ); - - return( 0 ); -} - static void vips_foreign_save_magick_bmp_buffer_class_init( VipsForeignSaveMagickBmpBufferClass *class ) { - GObjectClass *gobject_class = G_OBJECT_CLASS( class ); VipsObjectClass *object_class = (VipsObjectClass *) class; VipsForeignClass *foreign_class = (VipsForeignClass *) class; VipsOperationClass *operation_class = (VipsOperationClass *) class; - gobject_class->set_property = vips_object_set_property; - gobject_class->get_property = vips_object_get_property; - object_class->nickname = "magicksave_bmp_buffer"; object_class->description = _( "save bmp image to magick buffer" ); - object_class->build = vips_foreign_save_magick_bmp_buffer_build; foreign_class->suffs = vips__save_magick_bmp_suffs; @@ -717,9 +690,11 @@ vips_foreign_save_magick_bmp_buffer_class_init( } static void -vips_foreign_save_magick_bmp_buffer_init( VipsForeignSaveMagickBmpBuffer *buffer ) +vips_foreign_save_magick_bmp_buffer_init( + VipsForeignSaveMagickBmpBuffer *buffer ) { VipsForeignSaveMagick *magick = (VipsForeignSaveMagick *) buffer; + VIPS_SETSTR( magick->format, "bmp" ); }