tell buffer and target savers the file format (#2499)

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 adds stub subclasses so that the savers know the exact format. It also improves PPM save.
This commit is contained in:
John Cupitt 2021-10-28 18:57:24 +01:00 committed by GitHub
parent 1f321d366b
commit 47383b5bfc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 402 additions and 27 deletions

View File

@ -14,6 +14,8 @@
- added restart_interval option to jpegsave [manthey]
- 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

View File

@ -1795,6 +1795,7 @@ vips_foreign_save_class_init( VipsForeignSaveClass *class )
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSave, page_height ),
0, VIPS_MAX_COORD, 0 );
}
static void
@ -2782,7 +2783,10 @@ 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_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 );
extern GType vips_foreign_load_png_buffer_get_type( void );
@ -2841,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,6 +2887,7 @@ vips_foreign_operation_init( void )
extern GType vips_foreign_save_heif_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 );
@ -2922,7 +2929,10 @@ 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_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*/
#ifdef HAVE_RADIANCE
@ -3052,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
@ -3081,6 +3093,7 @@ vips_foreign_operation_init( void )
vips_foreign_save_heif_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 =

View File

@ -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",

View File

@ -335,7 +335,6 @@ vips_foreign_save_heif_build( VipsObject *object )
VipsForeignSave *save = (VipsForeignSave *) object;
VipsForeignSaveHeif *heif = (VipsForeignSaveHeif *) object;
const char *filename;
struct heif_error error;
struct heif_writer writer;
char *chroma;
@ -357,15 +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.
*/
filename = vips_connection_filename( VIPS_CONNECTION( heif->target ) );
if( !vips_object_argument_isset( object, "compression" ) &&
filename &&
vips_iscasepostfix( filename, ".avif" ) )
heif->compression = VIPS_FOREIGN_HEIF_COMPRESSION_AV1;
error = heif_context_get_encoder_for_format( heif->ctx,
(enum heif_compression_format) heif->compression,
&heif->encoder );
@ -489,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;
@ -500,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__heif_suffs;
save_class->saveable = VIPS_SAVEABLE_RGBA_ONLY;
save_class->format_table = vips_heif_bandfmt;
@ -588,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 );
@ -600,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;
@ -607,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" ),
@ -664,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;
@ -671,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" ),
@ -721,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;
@ -728,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" ),
@ -742,6 +741,38 @@ 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 void
vips_foreign_save_avif_target_class_init(
VipsForeignSaveAvifTargetClass *class )
{
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
VipsOperationClass *operation_class = (VipsOperationClass *) class;
object_class->nickname = "avifsave_target";
object_class->description = _( "save image in AVIF format" );
foreign_class->suffs = vips__avif_suffs;
/* Hide from UI.
*/
operation_class->flags = VIPS_OPERATION_DEPRECATED;
}
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.

View File

@ -158,6 +158,10 @@ 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__save_pbm_suffs[];
extern const char *vips__save_pgm_suffs[];
extern const char *vips__save_ppm_suffs[];
extern const char *vips__save_pfm_suffs[];
int vips__ppm_save_target( VipsImage *in, VipsTarget *target,
gboolean ascii, gboolean squash );
@ -235,6 +239,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[];

View File

@ -141,7 +141,11 @@ static char *magic_names[] = {
/* Shared with ppmsave.
*/
const char *vips__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_pfm_suffs[] = { ".pfm", NULL };
static gboolean
vips_foreign_load_ppm_is_a_source( VipsSource *source )

View File

@ -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,6 +72,7 @@ struct _VipsForeignSavePpm {
VipsForeignSave parent_object;
VipsTarget *target;
VipsForeignPpmFormat format;
gboolean ascii;
int bitdepth;
@ -216,16 +219,70 @@ 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;
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 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
*/
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;
break;
case VIPS_FOREIGN_PPM_FORMAT_PPM:
if( target_format == VIPS_FORMAT_USHORT )
target_interpretation = VIPS_INTERPRETATION_RGB16;
else
target_interpretation = VIPS_INTERPRETATION_sRGB;
break;
case VIPS_FOREIGN_PPM_FORMAT_PFM:
target_format = VIPS_FORMAT_FLOAT;
break;
default:
/* Harmless.
*/
break;
}
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.
*/
@ -318,9 +375,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.
@ -391,7 +451,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;
@ -402,11 +461,17 @@ 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;
save_class->saveable = VIPS_SAVEABLE_RGB;
save_class->format_table = bandfmt_ppm;
VIPS_ARG_ENUM( class, "format", 2,
_( "Format" ),
_( "Format to save in" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSavePpm, format ),
VIPS_TYPE_FOREIGN_PPM_FORMAT,
VIPS_FOREIGN_PPM_FORMAT_PPM );
VIPS_ARG_BOOL( class, "ascii", 10,
_( "ASCII" ),
_( "save as ascii" ),
@ -433,6 +498,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 {
@ -456,6 +522,13 @@ 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" ) )
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;
return( VIPS_OBJECT_CLASS( vips_foreign_save_ppm_file_parent_class )->
build( object ) );
}
@ -465,6 +538,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;
@ -473,6 +547,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__ppm_suffs;
VIPS_ARG_STRING( class, "filename", 1,
_( "Filename" ),
_( "Filename to save to" ),
@ -521,6 +597,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;
@ -528,6 +605,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" ),
@ -542,6 +621,102 @@ vips_foreign_save_ppm_target_init( VipsForeignSavePpmTarget *target )
{
}
typedef VipsForeignSavePpmTarget VipsForeignSavePbmTarget;
typedef VipsForeignSavePpmTargetClass VipsForeignSavePbmTargetClass;
G_DEFINE_TYPE( VipsForeignSavePbmTarget, vips_foreign_save_pbm_target,
vips_foreign_save_ppm_target_get_type() );
static void
vips_foreign_save_pbm_target_class_init(
VipsForeignSavePbmTargetClass *class )
{
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
VipsOperationClass *operation_class = (VipsOperationClass *) class;
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 )
{
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
VipsOperationClass *operation_class = (VipsOperationClass *) class;
object_class->nickname = "pgmsave_target";
object_class->description = _( "save image in pgm format" );
foreign_class->suffs = vips__save_pgm_suffs;
/* Hide from UI.
*/
operation_class->flags = VIPS_OPERATION_DEPRECATED;
}
static void
vips_foreign_save_pgm_target_init( VipsForeignSavePgmTarget *target )
{
VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) target;
ppm->format = VIPS_FOREIGN_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 void
vips_foreign_save_pfm_target_class_init(
VipsForeignSavePfmTargetClass *class )
{
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
VipsOperationClass *operation_class = (VipsOperationClass *) class;
object_class->nickname = "pfmsave_target";
object_class->description = _( "save image in pfm format" );
foreign_class->suffs = vips__save_pfm_suffs;
/* Hide from UI.
*/
operation_class->flags = VIPS_OPERATION_DEPRECATED;
}
static void
vips_foreign_save_pfm_target_init( VipsForeignSavePfmTarget *target )
{
VipsForeignSavePpm *ppm = (VipsForeignSavePpm *) target;
ppm->format = VIPS_FOREIGN_PPM_FORMAT_PFM;
}
#endif /*HAVE_PPM*/
/**
@ -552,8 +727,9 @@ 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
* * @format: #VipsForeignPpmFormat, format to save in
* * @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,
@ -566,8 +742,9 @@ 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.
*
* @format defaults to the sub-type for this filename suffix.
*
* See also: vips_image_write_to_file().
*
@ -592,6 +769,12 @@ vips_ppmsave( VipsImage *in, const char *filename, ... )
* @target: save image to this target
* @...: %NULL-terminated list of optional named arguments
*
* Optional arguments:
*
* * @format: #VipsForeignPpmFormat, format to save in
* * @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().

View File

@ -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 );
@ -414,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[] = { ".gif", ".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.
*/
@ -512,7 +514,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 ) )
@ -557,6 +559,38 @@ 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 void
vips_foreign_save_magick_bmp_file_class_init(
VipsForeignSaveMagickBmpFileClass *class )
{
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
VipsOperationClass *operation_class = (VipsOperationClass *) class;
object_class->nickname = "magicksave_bmp";
object_class->description = _( "save bmp image with ImageMagick" );
foreign_class->suffs = vips__save_magick_bmp_suffs;
/* Hide from UI.
*/
operation_class->flags = VIPS_OPERATION_DEPRECATED;
}
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;
@ -630,4 +664,38 @@ 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 void
vips_foreign_save_magick_bmp_buffer_class_init(
VipsForeignSaveMagickBmpBufferClass *class )
{
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsForeignClass *foreign_class = (VipsForeignClass *) class;
VipsOperationClass *operation_class = (VipsOperationClass *) class;
object_class->nickname = "magicksave_bmp_buffer";
object_class->description = _( "save bmp image to magick buffer" );
foreign_class->suffs = vips__save_magick_bmp_suffs;
/* Hide from UI.
*/
operation_class->flags = VIPS_OPERATION_DEPRECATED;
}
static void
vips_foreign_save_magick_bmp_buffer_init(
VipsForeignSaveMagickBmpBuffer *buffer )
{
VipsForeignSaveMagick *magick = (VipsForeignSaveMagick *) buffer;
VIPS_SETSTR( magick->format, "bmp" );
}
#endif /*ENABLE_MAGICKSAVE*/

View File

@ -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;

View File

@ -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, ... )

View File

@ -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;

View File

@ -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()) )

View File

@ -64,6 +64,7 @@ g_module_check_init( GModule *module )
extern GType vips_foreign_save_heif_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();
@ -75,6 +76,7 @@ g_module_check_init( GModule *module )
vips_foreign_save_heif_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 );

View File

@ -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 );