finish reviding the fixed-up image load/save API

This commit is contained in:
John Cupitt 2014-06-08 11:16:58 +01:00
parent d426abdcd8
commit 35533a54cf
17 changed files with 236 additions and 291 deletions

View File

@ -25,7 +25,7 @@
- dzsave can directly write a ZIP file
- add ".vips" as an alternative suffix for vips files
- added vips_tiffload_buffer()
- added vips_foreign_load_buffer(), vips_foreign_save_buffer()
- added vips_image_new_from_buffer(), vips_image_write_to_buffer()
- added vips_object_set_from_string()
- added @container option to dzsave
- support 1/2/4 bit palette tiff images with alpha
@ -36,6 +36,7 @@
- im_*merge(), im_*mosaic(), im_match*(), im_global_balance*(), im_remosaic(),
im_*mosaic1(), im_*merge1() redone as classes
- better filename tracking for globalbalance
- revised vips8 image load/save API, now simpler and more logical
6/3/14 started 7.38.6
- grey ramp minimum was wrong

23
TODO
View File

@ -1,25 +1,10 @@
- vips_image_new_from_file() should take a set of options
- need something to write an image to an area of memory
implement it using vips_foreign_load()?
eg.:
foreign/vipsload.c uses vips_image_new_from_file() ... instead it should use
the _mode thing
int vips_image_write_to_memory( VipsImage *x, void **buf, size_t *len )
- likewise, vips_image_write_to_file() should take options. Implement in terms
of vips_foreign_save()?
- also new_from_memory() (new from buffer?)
see vips_foreign_load_buffer() for API
- can get rid of vips_foreign_load() / vips_foreign_save()
also vips_foreign_load_from_buffer() or whatever it's called, and save too.
- do we still need all the vips_image_build() machinery? can't we just use
the foreign system?
only need a couple of basic modes:wq
maybe?

View File

@ -53,7 +53,7 @@ vips_hough_new_accumulator( VipsHough *hough )
VipsImage *accumulator;
accumulator = vips_image_new_buffer();
accumulator = vips_image_new_memory();
vips_image_pipelinev( accumulator,
VIPS_DEMAND_STYLE_ANY, statistic->ready, NULL );

View File

@ -249,7 +249,7 @@ vips__vector_to_ink( const char *domain,
/* And now recode the vec to match the original im.
*/
if( vips_image_encode( t[3], &t[4], im->Coding ) ||
!(t[5] = vips_image_new_buffer()) ||
!(t[5] = vips_image_new_memory()) ||
vips_image_write( t[4], t[5] ) ) {
g_object_unref( context );
return( NULL );
@ -322,7 +322,7 @@ vips__ink_to_vector( const char *domain, VipsImage *im, VipsPel *ink, int *n )
/* To a mem buffer, then copy to out.
*/
if( !(t[4] = vips_image_new_buffer()) ||
if( !(t[4] = vips_image_new_memory()) ||
vips_image_write( t[3], t[4] ) )
return( NULL );

View File

@ -200,7 +200,7 @@ vips_rot45_build( VipsObject *object )
if( vips_image_wio_input( rot45->in ) )
return( -1 );
t[0] = vips_image_new_buffer();
t[0] = vips_image_new_memory();
if( vips_image_pipelinev( t[0],
VIPS_DEMAND_STYLE_ANY, rot45->in, NULL ) )
return( -1 );

View File

@ -1052,7 +1052,7 @@ strip_work( VipsThreadState *state, void *a )
printf( "strip_work: writing to %s\n", buf );
#endif /*DEBUG_VERBOSE*/
if( vips_foreign_save_buffer( x, dz->suffix, &buf, &len, NULL ) ) {
if( vips_image_write_to_buffer( x, dz->suffix, &buf, &len, NULL ) ) {
g_object_unref( x );
return( -1 );
}

View File

@ -540,22 +540,10 @@ vips_foreign_find_load( const char *name )
return( G_OBJECT_CLASS_NAME( load_class ) );
}
/**
* vips_foreign_load:
* @filename: file to load
* @out: output image
* @...: %NULL-terminated list of optional named arguments
*
* Loads @filename into @out using the loader recommended by
* vips_foreign_find_load().
*
* Load options may be appended to @filename as "[name=value,...]" or given as
* a NULL-terminated list of name-value pairs at the end of the arguments.
*
* See also: vips_foreign_save().
*
* Returns: 0 on success, -1 on error
/* Kept for compat with earlier version of the vip8 API. Use
* vips_image_new_from_file() now.
*/
int
vips_foreign_load( const char *name, VipsImage **out, ... )
{
@ -597,7 +585,7 @@ vips_foreign_find_load_buffer_sub( VipsForeignLoadClass *load_class,
*
* Searches for an operation you could use to load a memory buffer.
*
* See also: vips_foreign_load_buffer().
* See also: vips_image_new_from_buffer().
*
* Returns: the name of an operation on success, %NULL on error
*/
@ -618,48 +606,6 @@ vips_foreign_find_load_buffer( void *buf, size_t len )
return( G_OBJECT_CLASS_NAME( load_class ) );
}
/**
* vips_foreign_load_buffer:
* @buf: start of memory buffer
* @len: length of memory buffer
* @option_string: set of extra options as a string
* @out: output image
* @...: %NULL-terminated list of optional named arguments
*
* Loads @buf, @len into @out using the loader recommended by
* vips_foreign_find_load_buffer(). @option_string can be used to give an
* extra set of load options.
*
* See also: vips_foreign_save().
*
* Returns: 0 on success, -1 on error
*/
int
vips_foreign_load_buffer( void *buf, size_t len, const char *option_string,
VipsImage **out, ... )
{
const char *operation_name;
VipsArea *area;
va_list ap;
int result;
if( !(operation_name = vips_foreign_find_load_buffer( buf, len )) )
return( -1 );
/* We don't take a copy of the data or free it.
*/
area = vips_area_new_blob( NULL, buf, len );
va_start( ap, out );
result = vips_call_split_option_string( operation_name,
option_string, ap, area, out );
va_end( ap );
vips_area_unref( area );
return( result );
}
/**
* vips_foreign_is_a:
* @loader: name of loader to use for test
@ -812,7 +758,7 @@ vips_foreign_load_temp( VipsForeignLoad *load )
/* Otherwise, fall back to a memory buffer.
*/
return( vips_image_new_buffer() );
return( vips_image_new_memory() );
}
/* Check two images for compatibility: their geometries need to match.
@ -1506,22 +1452,9 @@ vips_foreign_find_save( const char *name )
return( G_OBJECT_CLASS_NAME( save_class ) );
}
/**
* vips_foreign_save:
* @in: image to write
* @filename: file to write to
* @...: %NULL-terminated list of optional named arguments
*
* Saves @in to @filename using the saver recommended by
* vips_foreign_find_save().
*
* Save options may be appended to @filename as "[name=value,...]" or given as
* a NULL-terminated list of name-value pairs at the end of the arguments.
*
* See also: vips_foreign_load().
*
* Returns: 0 on success, -1 on error
/* Kept for early vips8 API compat.
*/
int
vips_foreign_save( VipsImage *in, const char *name, ... )
{
@ -1568,7 +1501,7 @@ vips_foreign_find_save_buffer_sub( VipsForeignSaveClass *save_class,
* Searches for an operation you could use to write to a buffer in @suffix
* format.
*
* See also: vips_foreign_save_buffer().
* See also: vips_image_write_to_buffer().
*
* Returns: the name of an operation on success, %NULL on error
*/
@ -1594,59 +1527,6 @@ vips_foreign_find_save_buffer( const char *name )
return( G_OBJECT_CLASS_NAME( save_class ) );
}
/**
* vips_foreign_save_buffer:
* @in: image to write
* @suffix: format to write
* @buf: return buffer start here
* @len: return buffer length here
* @...: %NULL-terminated list of optional named arguments
*
* Saves @in to a memory buffer selected from @suffix. @suffix may also set
* save options, for example it could be ".jpg[Q=80]".
* Save options may also be given
* as a NULL-terminated list of name-value pairs.
*
* See also: vips_foreign_load_buffer().
*
* Returns: 0 on success, -1 on error
*/
int
vips_foreign_save_buffer( VipsImage *in,
const char *name, void **buf, size_t *len,
... )
{
char suffix[VIPS_PATH_MAX];
char option_string[VIPS_PATH_MAX];
const char *operation_name;
VipsArea *area;
va_list ap;
int result;
vips__filename_split8( name, suffix, option_string );
if( !(operation_name = vips_foreign_find_save_buffer( suffix )) )
return( -1 );
va_start( ap, len );
result = vips_call_split_option_string( operation_name, option_string,
ap, in, &area );
va_end( ap );
if( area ) {
if( buf ) {
*buf = area->data;
area->free_fn = NULL;
}
if( len )
*len = area->length;
vips_area_unref( area );
}
return( result );
}
/* Called from iofuncs to init all operations in this dir. Use a plugin system
* instead?
*/

View File

@ -444,7 +444,7 @@ vips__openslide_read_associated( const char *filename, VipsImage *out,
/* Memory buffer. Get associated directly to this, then copy to out.
*/
raw = vips_image_new_buffer();
raw = vips_image_new_memory();
vips_object_local( out, raw );
if( !(rslide = readslide_new( filename, raw, 0, associated )) ||

View File

@ -516,7 +516,7 @@ png2vips_image( Read *read, VipsImage *out )
/* Arg awful interlaced image. We have to load to a huge mem
* buffer, then copy to out.
*/
t[0] = vips_image_new_buffer();
t[0] = vips_image_new_memory();
if( png2vips_header( read, t[0] ) ||
png2vips_interlace( read, t[0] ) ||
vips_image_write( t[0], out ) )

View File

@ -220,7 +220,7 @@ read_image( Read *read, VipsImage *out )
vips_object_local_array( VIPS_OBJECT( out ), 3 );
webp_decoder decoder;
t[0] = vips_image_new_buffer();
t[0] = vips_image_new_memory();
if( read_header( read, t[0] ) )
return( -1 );
if( vips_image_write_prepare( t[0] ) )

View File

@ -96,7 +96,7 @@ vips_freqmult_build( VipsObject *object )
* FIXME does this actually work now we're a class? test
* perhaps we need a temporary object
*/
t[4] = vips_image_new_buffer();
t[4] = vips_image_new_memory();
if( vips_fwfft( in, &t[0], NULL ) ||
vips_multiply( t[0], freqmult->mask, &t[1], NULL ) ||

View File

@ -115,7 +115,7 @@ rfwfft1( VipsObject *object, VipsImage *in, VipsImage **out )
/* Convert input to a real double membuffer.
*/
t[1] = vips_image_new_buffer();
t[1] = vips_image_new_memory();
if( vips_cast_double( in, &t[0], NULL ) ||
vips_image_write( t[0], t[1] ) )
return( -1 );
@ -145,7 +145,7 @@ rfwfft1( VipsObject *object, VipsImage *in, VipsImage **out )
/* Write to out as another memory buffer.
*/
*out = vips_image_new_buffer();
*out = vips_image_new_memory();
if( vips_image_pipelinev( *out, VIPS_DEMAND_STYLE_ANY, in, NULL ) )
return( -1 );
(*out)->BandFmt = VIPS_FORMAT_DPCOMPLEX;
@ -230,7 +230,7 @@ cfwfft1( VipsObject *object, VipsImage *in, VipsImage **out )
/* Convert input to a complex double membuffer.
*/
t[1] = vips_image_new_buffer();
t[1] = vips_image_new_memory();
if( vips_cast_dpcomplex( in, &t[0], NULL ) ||
vips_image_write( t[0], t[1] ) )
return( -1 );
@ -260,7 +260,7 @@ cfwfft1( VipsObject *object, VipsImage *in, VipsImage **out )
/* Write to out as another memory buffer.
*/
*out = vips_image_new_buffer();
*out = vips_image_new_memory();
if( vips_image_pipelinev( *out, VIPS_DEMAND_STYLE_ANY, in, NULL ) )
return( -1 );
(*out)->BandFmt = VIPS_FORMAT_DPCOMPLEX;

View File

@ -100,7 +100,7 @@ cinvfft1( VipsObject *object, VipsImage *in, VipsImage **out )
/* Convert input to a complex double membuffer.
*/
*out = vips_image_new_buffer();
*out = vips_image_new_memory();
if( vips_cast_dpcomplex( in, &t[0], NULL ) ||
vips_image_write( t[0], *out ) )
return( -1 );
@ -149,7 +149,7 @@ rinvfft1( VipsObject *object, VipsImage *in, VipsImage **out )
/* Convert input to a complex double membuffer.
*/
t[1] = vips_image_new_buffer();
t[1] = vips_image_new_memory();
if( vips_cast_dpcomplex( in, &t[0], NULL ) ||
vips_image_write( t[0], t[1] ) )
return( -1 );
@ -173,7 +173,7 @@ rinvfft1( VipsObject *object, VipsImage *in, VipsImage **out )
/* Make mem buffer real image for output.
*/
*out = vips_image_new_buffer();
*out = vips_image_new_memory();
if( vips_image_pipelinev( *out, VIPS_DEMAND_STYLE_ANY, t[1], NULL ) )
return( -1 );
(*out)->BandFmt = VIPS_FORMAT_DOUBLE;

View File

@ -307,21 +307,7 @@ typedef struct _VipsForeignSaveClass {
GType vips_foreign_save_get_type( void );
const char *vips_foreign_find_save( const char *filename );
const char * vips_foreign_find_save_buffer( const char *suffix );
/* Read/write an image convenience functions.
*/
int vips_foreign_load( const char *filename, VipsImage **out, ... )
__attribute__((sentinel));
int vips_foreign_save( VipsImage *in, const char *filename, ... )
__attribute__((sentinel));
int vips_foreign_load_buffer( void *buf, size_t len, const char *option_string,
VipsImage **out, ... )
__attribute__((sentinel));
int vips_foreign_save_buffer( VipsImage *in,
const char *suffix, void **buf, size_t *len, ... )
__attribute__((sentinel));
const char *vips_foreign_find_save_buffer( const char *suffix );
int vips_openslideload( const char *filename, VipsImage **out, ... )
__attribute__((sentinel));

View File

@ -416,21 +416,29 @@ void vips_image_set_kill( VipsImage *image, gboolean kill );
VipsImage *vips_image_new( void );
VipsImage *vips_image_new_mode( const char *filename, const char *mode );
VipsImage *vips_image_new_buffer( void );
VipsImage *vips_image_new_memory( void );
VipsImage *vips_image_new_from_file( const char *filename, ... )
__attribute__((sentinel));
VipsImage *vips_image_new_from_file_RW( const char *filename );
VipsImage *vips_image_new_from_file_raw( const char *filename,
int xsize, int ysize, int bands, guint64 offset );
VipsImage *vips_image_new_from_memory( void *buffer,
int xsize, int ysize, int bands, VipsBandFormat bandfmt );
VipsImage *vips_image_new_from_buffer( void *buf, size_t len,
const char *option_string, ... )
__attribute__((sentinel));
VipsImage *vips_image_new_matrix( int width, int height );
VipsImage *vips_image_new_matrixv( int width, int height, ... );
void vips_image_set_delete_on_close( VipsImage *image,
gboolean delete_on_close );
VipsImage *vips_image_new_temp_file( const char *format );
int vips_image_write( VipsImage *image, VipsImage *out );
int vips_image_write_to_file( VipsImage *image, const char *filename, ... )
__attribute__((sentinel));
int vips_image_write_to_buffer( VipsImage *in,
const char *name, void **buf, size_t *len, ... )
__attribute__((sentinel));
int vips_image_decode_predict( VipsImage *im,
int *bands, VipsBandFormat *format );

View File

@ -315,6 +315,11 @@ IMAGE *vips__deprecated_open_write( const char *filename );
int vips__input_interpolate_init( im_object *obj, char *str );
int vips_foreign_load( const char *filename, VipsImage **out, ... )
__attribute__((sentinel));
int vips_foreign_save( VipsImage *in, const char *filename, ... )
__attribute__((sentinel));
#ifdef __cplusplus
}
#endif /*__cplusplus*/

View File

@ -1538,109 +1538,6 @@ vips_image_new( void )
return( image );
}
/**
* vips_image_new_mode:
* @filename: file to open
* @mode: mode to open with
*
* vips_image_new_mode() examines the mode string and creates an
* appropriate #VipsImage.
*
* This function (mostly) exists to support the vips7 compatibility layer.
* vips8 programs should use vips_image_new_from_file() and friends.
*
* <itemizedlist>
* <listitem>
* <para>
* <emphasis>"t"</emphasis>
* creates a temporary memory buffer image.
* </para>
* </listitem>
* <listitem>
* <para>
* <emphasis>"p"</emphasis>
* creates a "glue" descriptor you can use to join operations, see also
* vips_image_new().
* </para>
* </listitem>
* <listitem>
* <para>
* <emphasis>"r"</emphasis>
* opens the named file for reading. If the file is not in the native
* VIPS format for your machine, vips_image_new_mode()
* automatically converts the file for you.
*
* Some formats (eg. tiled tiff) are read directly.
*
* Some formats (eg. strip tiff) do not support random access and can't
* be processed directly. Small images are decompressed to memory and
* loaded from there, large images are decompressed to a disc file and
* processed from that.
*
* If the operations you intend to perform are sequential, that is, they
* operate in a strict top-to-bottom manner, you can use sequential mode
* instead, see "rs" below,
* or you can use the lower-level
* API and control the loading process yourself. See
* #VipsForeign.
*
* See vips_image_new_temp_file() for an explanation of how VIPS selects a
* location for the temporary file.
*
* The disc threshold can be set with the "--vips-disc-threshold"
* command-line argument, or the VIPS_DISC_THRESHOLD environment variable.
* The value is a simple integer, but can take a unit postfix of "k",
* "m" or "g" to indicate kilobytes, megabytes or gigabytes.
*
* For example:
*
* |[
* vips --vips-disc-threshold 500m copy fred.tif fred.v
* ]|
*
* will copy via disc if "fred.tif" is more than 500 Mbytes
* uncompressed. The default threshold is 100 MB.
*
* Note that <emphasis>"r"</emphasis> mode works in at least two stages.
* It should return quickly and let you check header fields. It will
* only actually read in pixels when you first access them.
* </para>
* </listitem>
* <listitem>
* <para>
* <emphasis>"rs"</emphasis>
* opens the named file for reading sequentially. It reads the source
* image top-to-bottom and serves up pixels to the pipeline as required.
* Provided the operations that connect to the image all demand pixels
* only top-to-bottom as well, everything is fine and you avoid the
* separate decompress stage.
* </para>
* </listitem>
* <listitem>
* <para>
* <emphasis>"w"</emphasis>
* opens the named file for writing. It looks at the file name
* suffix to determine the type to write -- for example:
*
* |[
* vips_image_new_mode( "fred.tif", "w" )
* ]|
*
* will write in TIFF format.
* </para>
* </listitem>
* <listitem>
* <para>
* <emphasis>"rw"</emphasis>
* opens the named file for reading and writing. This will only work for
* VIPS files in a format native to your machine. It is only for
* paintbox-type applications.
* </para>
* </listitem>
* </itemizedlist>
*
* Returns: the new #VipsImage, or %NULL on error.
*/
VipsImage *
vips_image_new_mode( const char *filename, const char *mode )
{
@ -1665,10 +1562,10 @@ vips_image_new_mode( const char *filename, const char *mode )
}
/**
* vips_image_new_buffer:
* vips_image_new_memory:
*
* vips_image_new_buffer() creates a new VipsImage which when written to will
* create a memory buffer. It is a convenience function for
* vips_image_new_memory() creates a new #VipsImage which, when written to, will
* create a memory image. It is a convenience function for
* vips_image_new_mode(vips_image_temp_name(), "t").
*
* See also: vips_image_new().
@ -1676,7 +1573,7 @@ vips_image_new_mode( const char *filename, const char *mode )
* Returns: the new #VipsImage, or %NULL on error.
*/
VipsImage *
vips_image_new_buffer( void )
vips_image_new_memory( void )
{
return( vips_image_new_mode( vips_image_temp_name(), "t" ) );
}
@ -1686,6 +1583,12 @@ vips_image_new_buffer( void )
* @name: file to open
* @...: %NULL-terminated list of optional named arguments
*
* Optional arguments:
*
* @access: hint #VipsAccess mode to loader
* @disc: load via a temporary disc file
* @...: other arguments depend on the loader
*
* vips_image_new_from_file() opens @name for reading. It can load files
* in many image formats, including VIPS, TIFF, PNG, JPEG, FITS, Matlab,
* OpenEXR, CSV, WebP, Radiance, RAW, PPM and others.
@ -1694,7 +1597,48 @@ vips_image_new_buffer( void )
* a NULL-terminated list of name-value pairs at the end of the arguments.
* Options given in the function call override options given in the filename.
*
* See also: vips_foreign_load(), vips_image_write_to_file().
* vips_image_new_from_file() always returns immediately with the header
* fields filled in. No pixels are actually read until you first access them.
*
* @access lets you hint the expected access pattern for this file.
* #VIPS_ACCESS_RANDOM means you can fetch pixels randomly from the image.
* This is the default mode. #VIPS_ACCESS_SEQUENTIAL means you will read the
* whole image exactly once, top-to-bottom. In this mode, vips can avoid
* converting the whole image in one go, for a large memory saving. You are
* allowed to make small non-local references, so area operations like
* convolution will work. #VIPS_ACCESS_SEQUENTIAL_UNBUFFERED does not allow
* non-local references, so will only work for very strict top-to-bottom
* operations, but does have very low memory needs.
*
* In #VIPS_ACCESS_RANDOM mode, small images are decompressed to memory and
* then processed from there. Large images are decompressed to temporary
* random-access files on disc and then processed from there. Set @disc to
* %TRUE to force loading via disc. See vips_image_new_temp_file() for an
* explanation of how VIPS selects a location for the temporary file.
*
* The disc threshold can be set with the "--vips-disc-threshold"
* command-line argument, or the VIPS_DISC_THRESHOLD environment variable.
* The value is a simple integer, but can take a unit postfix of "k",
* "m" or "g" to indicate kilobytes, megabytes or gigabytes.
* The default threshold is 100 MB.
*
* For example:
*
* |[
* VipsImage *image = vips_image_new_from_file ("fred.tif",
* "page", 12,
* NULL);
* ]|
*
* Will open "fred.tif", reading page 12.
*
* Use vips_foreign_find_load() or vips_foreign_is_a() to see what format a
* file is in and therefore what options are available. If you need more
* control over the loading process, you can call loaders directly, see
* vips_jpegload(), for example.
*
* See also: vips_foreign_find_load(), vips_foreign_is_a(),
* vips_image_write_to_file().
*
* Returns: the new #VipsImage, or %NULL on error.
*/
@ -1723,6 +1667,24 @@ vips_image_new_from_file( const char *name, ... )
return( out );
}
/**
* vips_image_new_from_file_RW:
* @filename: filename to open
*
* Opens the named file for reading and writing. This will only work for
* VIPS files in a format native to your machine. It is only for
* paintbox-type applications.
*
* See also: vips_draw_circle().
*
* Returns: the new #VipsImage, or %NULL on error.
*/
VipsImage *
vips_image_new_from_file_RW( const char *filename )
{
return( vips_image_new_mode( filename, "rw" ) );
}
/**
* vips_image_new_from_file_raw:
* @filename: filename to open
@ -1774,11 +1736,18 @@ vips_image_new_from_file_raw( const char *filename,
* @bands: image bands (or bytes per pixel)
* @bandfmt: image format
*
* This function wraps an #IMAGE around a memory buffer. VIPS does not take
* This function wraps a #VipsImage around a memory area. The memory area
* must be a simple array, for example RGBRGBRGB, left-to-right,
* top-to-bottom. Use vips_image_new_from_buffer() to load an area of memory
* containing an image in a format.
*
* VIPS does not take
* responsibility for the area of memory, it's up to you to make sure it's
* freed when the image is closed. See for example #VipsObject::close.
*
* See also: im_binfile(), im_raw2vips(), vips_image_new().
* Use vips_copy_morph() to set other image properties.
*
* See also: vips_image_new().
*
* Returns: the new #VipsImage, or %NULL on error.
*/
@ -1808,6 +1777,60 @@ vips_image_new_from_memory( void *buffer,
return( image );
}
/**
* vips_image_new_from_buffer:
* @buf: start of memory buffer
* @len: length of memory buffer
* @option_string: set of extra options as a string
* @...: %NULL-terminated list of optional named arguments
*
* Loads an image from the formatted area of memory @buf, @len using the
* loader recommended by vips_foreign_find_load_buffer(). Only TIFF, PNG and
* JPEG formats are supported. To load an unformatted area of memory, use
* vips_image_new_from_memory().
*
* VIPS does not take
* responsibility for the area of memory, it's up to you to make sure it's
* freed when the image is closed. See for example #VipsObject::close.
*
* Load options may be given in @option_string as "[name=value,...]" or given as
* a NULL-terminated list of name-value pairs at the end of the arguments.
* Options given in the function call override options given in the filename.
*
* See also: vips_image_write_to_buffer().
*
* Returns: 0 on success, -1 on error
*/
VipsImage *
vips_image_new_from_buffer( void *buf, size_t len,
const char *option_string, ... )
{
const char *operation_name;
VipsArea *area;
va_list ap;
int result;
VipsImage *out;
if( !(operation_name = vips_foreign_find_load_buffer( buf, len )) )
return( NULL );
/* We don't take a copy of the data or free it.
*/
area = vips_area_new_blob( NULL, buf, len );
va_start( ap, option_string );
result = vips_call_split_option_string( operation_name,
option_string, ap, area, &out );
va_end( ap );
vips_area_unref( area );
if( result )
return( NULL );
return( out );
}
/**
* vips_image_new_matrix:
* @width: image width
@ -2042,6 +2065,63 @@ vips_image_write_to_file( VipsImage *image, const char *name, ... )
return( result );
}
/**
* vips_image_write_to_buffer:
* @in: image to write
* @suffix: format to write
* @buf: return buffer start here
* @len: return buffer length here
* @...: %NULL-terminated list of optional named arguments
*
* Writes @in to a memory buffer selected from @suffix. @suffix may also set
* save options, for example it could be ".jpg[Q=80]".
* Save options may also be given
* as a NULL-terminated list of name-value pairs.
*
* Currently only TIFF, JPEG and PNG formats are supported.
*
* You can call the various save operations directly if you wish, see
* vips_jpegsave_buffer(), for example.
*
* See also: vips_image_new_from_buffer().
*
* Returns: 0 on success, -1 on error
*/
int
vips_image_write_to_buffer( VipsImage *in,
const char *name, void **buf, size_t *len,
... )
{
char suffix[VIPS_PATH_MAX];
char option_string[VIPS_PATH_MAX];
const char *operation_name;
VipsArea *area;
va_list ap;
int result;
vips__filename_split8( name, suffix, option_string );
if( !(operation_name = vips_foreign_find_save_buffer( suffix )) )
return( -1 );
va_start( ap, len );
result = vips_call_split_option_string( operation_name, option_string,
ap, in, &area );
va_end( ap );
if( area ) {
if( buf ) {
*buf = area->data;
area->free_fn = NULL;
}
if( len )
*len = area->length;
vips_area_unref( area );
}
return( result );
}
/**
* vips_image_decode:
* @in: image to decode
@ -2464,7 +2544,7 @@ vips_image_wio_input( VipsImage *image )
/* Change to VIPS_IMAGE_SETBUF. First, make a memory
* buffer and copy into that.
*/
t1 = vips_image_new_buffer();
t1 = vips_image_new_memory();
if( vips_image_write( image, t1 ) ) {
g_object_unref( t1 );
return( -1 );