diff --git a/ChangeLog b/ChangeLog index 4adacb75..8f0b3c80 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 diff --git a/TODO b/TODO index d9b65a94..915a1944 100644 --- a/TODO +++ b/TODO @@ -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? diff --git a/libvips/arithmetic/hough.c b/libvips/arithmetic/hough.c index 5b71280c..7c8838d0 100644 --- a/libvips/arithmetic/hough.c +++ b/libvips/arithmetic/hough.c @@ -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 ); diff --git a/libvips/conversion/insert.c b/libvips/conversion/insert.c index 2c8cdbf9..636f35cf 100644 --- a/libvips/conversion/insert.c +++ b/libvips/conversion/insert.c @@ -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 ); diff --git a/libvips/conversion/rot45.c b/libvips/conversion/rot45.c index 283a4ec5..2ac312f6 100644 --- a/libvips/conversion/rot45.c +++ b/libvips/conversion/rot45.c @@ -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 ); diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index 58f24e19..94e8510e 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -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 ); } diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index dc2ea250..aa3c02f2 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -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? */ diff --git a/libvips/foreign/openslide2vips.c b/libvips/foreign/openslide2vips.c index e68c6da8..7732791f 100644 --- a/libvips/foreign/openslide2vips.c +++ b/libvips/foreign/openslide2vips.c @@ -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 )) || diff --git a/libvips/foreign/vipspng.c b/libvips/foreign/vipspng.c index c462e225..960bf4c5 100644 --- a/libvips/foreign/vipspng.c +++ b/libvips/foreign/vipspng.c @@ -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 ) ) diff --git a/libvips/foreign/webp2vips.c b/libvips/foreign/webp2vips.c index 2bd93736..51710c15 100644 --- a/libvips/foreign/webp2vips.c +++ b/libvips/foreign/webp2vips.c @@ -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] ) ) diff --git a/libvips/freqfilt/freqmult.c b/libvips/freqfilt/freqmult.c index 01d61bbe..20b0682f 100644 --- a/libvips/freqfilt/freqmult.c +++ b/libvips/freqfilt/freqmult.c @@ -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 ) || diff --git a/libvips/freqfilt/fwfft.c b/libvips/freqfilt/fwfft.c index 8d2880d6..cddcc3ca 100644 --- a/libvips/freqfilt/fwfft.c +++ b/libvips/freqfilt/fwfft.c @@ -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; diff --git a/libvips/freqfilt/invfft.c b/libvips/freqfilt/invfft.c index 9b87b9d0..3aa24881 100644 --- a/libvips/freqfilt/invfft.c +++ b/libvips/freqfilt/invfft.c @@ -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; diff --git a/libvips/include/vips/foreign.h b/libvips/include/vips/foreign.h index 118396ee..473c4e5e 100644 --- a/libvips/include/vips/foreign.h +++ b/libvips/include/vips/foreign.h @@ -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)); diff --git a/libvips/include/vips/image.h b/libvips/include/vips/image.h index d80f2881..019aeb8c 100644 --- a/libvips/include/vips/image.h +++ b/libvips/include/vips/image.h @@ -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 ); diff --git a/libvips/include/vips/internal.h b/libvips/include/vips/internal.h index edc8ddf5..1c3f44c4 100644 --- a/libvips/include/vips/internal.h +++ b/libvips/include/vips/internal.h @@ -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*/ diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index a49febc0..bf6042f0 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -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. - * - * - * - * - * "t" - * creates a temporary memory buffer image. - * - * - * - * - * "p" - * creates a "glue" descriptor you can use to join operations, see also - * vips_image_new(). - * - * - * - * - * "r" - * 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 "r" 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. - * - * - * - * - * "rs" - * 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. - * - * - * - * - * "w" - * 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. - * - * - * - * - * "rw" - * 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. - * - * - * - * - * 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 );