add "rs" image open mode

This commit is contained in:
John Cupitt 2012-07-09 21:35:53 +01:00
parent 701ff1ae8d
commit af1f2b47c1
7 changed files with 111 additions and 52 deletions

View File

@ -11,6 +11,7 @@
- add :seq support to im_tiff2vips(), im_jpeg2vips() ... helps ruby-vips
- better thread safety for vips8 operation dispatch
- better thread safety for upstream / downstream image linking
- added "rs" open mode, removed "rd"
18/6/12 started 7.28.9
- slightly more memory debugging output

22
TODO
View File

@ -1,26 +1,12 @@
- have made vips_operation_set_valist_optional into a general thing on
vipsobject
vips_object_setv( VipsObject, va_list list );
- test "rs" mode
needs docs
can't see the code for "rd" mode?
or "rw" mode either?
- should
vips_image_new_mode ()
have "rs" mode? ie. open for sequential read?
it's a property of in VipsForeignLoad
vips_foreign_load_options() needs to take a va_list of optional extra args,
use that to set seq
look for analogues to vips_foreign_load_options() which need to be va_list'd
as well
- need a flag on operations for "is sequential"
should be on the object, not the class, since it can change with params

View File

@ -1489,23 +1489,27 @@ vips_foreign_save( VipsImage *in, const char *filename, ... )
* vips_foreign_load_options:
* @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().
*
* Arguments to the loader may be embedded in the filename using the usual
* syntax.
* syntax. They may also be given as a set of NULL-terminated optional
* arguments.
*
* See also: vips_foreign_load().
*
* Returns: 0 on success, -1 on error
*/
int
vips_foreign_load_options( const char *filename, VipsImage **out )
vips_foreign_load_options( const char *filename, VipsImage **out, ... )
{
VipsObjectClass *oclass = g_type_class_ref( VIPS_TYPE_FOREIGN_LOAD );
VipsObject *object;
va_list ap;
int result;
/* This will use vips_foreign_load_new_from_string() to pick a loader,
* then set options from the remains of the string.
@ -1513,6 +1517,14 @@ vips_foreign_load_options( const char *filename, VipsImage **out )
if( !(object = vips_object_new_from_string( oclass, filename )) )
return( -1 );
/* Also set options from args.
*/
va_start( ap, out );
result = vips_object_set_valist( object, ap );
va_end( ap );
if( result )
return( -1 );
if( vips_cache_operation_buildp( (VipsOperation **) &object ) ) {
/* The build may have made some output objects before
* failing.
@ -1540,22 +1552,27 @@ vips_foreign_load_options( const char *filename, VipsImage **out )
* vips_foreign_save_options:
* @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().
*
* Arguments to the saver may be embedded in the filename using the usual
* syntax.
* syntax. They may also be given as a set of NULL-terminated optional
* arguments.
*
* See also: vips_foreign_save().
*
* Returns: 0 on success, -1 on error
*/
int
vips_foreign_save_options( VipsImage *in, const char *filename )
vips_foreign_save_options( VipsImage *in, const char *filename, ... )
{
VipsObjectClass *oclass = g_type_class_ref( VIPS_TYPE_FOREIGN_SAVE );
VipsObject *object;
va_list ap;
int result;
/* This will use vips_foreign_save_new_from_string() to pick a saver,
* then set options from the tail of the filename.
@ -1565,6 +1582,14 @@ vips_foreign_save_options( VipsImage *in, const char *filename )
g_object_set( object, "in", in, NULL );
/* Also set options from args.
*/
va_start( ap, filename );
result = vips_object_set_valist( object, ap );
va_end( ap );
if( result )
return( -1 );
/* ... and running _build() should save it.
*/
if( vips_cache_operation_buildp( (VipsOperation **) &object ) ) {

View File

@ -294,8 +294,10 @@ int vips_foreign_load( const char *filename, VipsImage **out, ... )
int vips_foreign_save( VipsImage *in, const char *filename, ... )
__attribute__((sentinel));
int vips_foreign_load_options( const char *filename, VipsImage **out );
int vips_foreign_save_options( VipsImage *in, const char *filename );
int vips_foreign_load_options( const char *filename, VipsImage **out, ... )
__attribute__((sentinel));
int vips_foreign_save_options( VipsImage *in, const char *filename, ... )
__attribute__((sentinel));
int vips_openslideload( const char *filename, VipsImage **out, ... )
__attribute__((sentinel));

View File

@ -308,7 +308,7 @@ vips_image_new_from_file_object( const char *string )
image = VIPS_IMAGE( g_object_new( VIPS_TYPE_IMAGE, NULL ) );
g_object_set( image,
"filename", string,
"mode", "rd",
"mode", "r",
NULL );
return( VIPS_OBJECT( image ) );
@ -508,7 +508,7 @@ vips_image_rewind( VipsObject *object )
static void
vips_image_save_cb( VipsImage *image, int *result )
{
if( vips_foreign_save_options( image, image->filename ) )
if( vips_foreign_save_options( image, image->filename, NULL ) )
*result = -1;
}
@ -655,8 +655,17 @@ vips_image_build( VipsObject *object )
else {
VipsImage *t;
if( vips_foreign_load_options( filename, &t ) )
return( -1 );
if( mode[1] == 's' ) {
if( vips_foreign_load_options( filename, &t,
"sequential", TRUE,
NULL ) )
return( -1 );
}
else {
if( vips_foreign_load_options( filename, &t,
NULL ) )
return( -1 );
}
image->dtype = VIPS_IMAGE_PARTIAL;
if( vips_image_write( t, image ) ) {
@ -1370,28 +1379,20 @@ vips_image_new( void )
* VIPS format for your machine, vips_image_new_mode()
* automatically converts the file for you.
*
* For some large files (eg. TIFF) this may
* not be what you want, it can fill memory very quickly. Instead, you
* can either use "rd" mode (see below), or you can use the lower-level
* 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.
*
* vips_image_new_mode() can read files in most formats.
*
* 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>"rd"</emphasis>
* opens the named file for reading. If the uncompressed image is larger
* than a threshold and the file format does not support random access,
* rather than uncompressing to memory, vips_image_new_mode() will
* uncompress to a temporary disc file. This file will be automatically
* deleted when the VipsImage is closed.
*
* See im_system_image() for an explanation of how VIPS selects a
* location for the temporary file.
*
@ -1408,6 +1409,20 @@ vips_image_new( void )
*
* 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>
@ -1479,7 +1494,7 @@ vips_image_new_buffer( void )
* vips_image_new_from_file:
* @filename: file to open
*
* vips_image_new_from_file() opens @filename for reading in mode "rd". See
* vips_image_new_from_file() opens @filename for reading in mode "r". See
* vips_image_new_mode() for details.
*
* See also: vips_image_new_mode().
@ -1489,7 +1504,7 @@ vips_image_new_buffer( void )
VipsImage *
vips_image_new_from_file( const char *filename )
{
return( vips_image_new_mode( filename, "rd" ) );
return( vips_image_new_mode( filename, "r" ) );
}
/**

View File

@ -1470,7 +1470,7 @@ vips_object_set_argument_from_string( VipsObject *object,
/* Read the filename. vips_foreign_load_options()
* handles embedded options.
*/
if( vips_foreign_load_options( value, &out ) )
if( vips_foreign_load_options( value, &out, NULL ) )
return( -1 );
g_value_init( &gvalue, VIPS_TYPE_IMAGE );
@ -1684,7 +1684,7 @@ vips_object_get_argument_to_string( VipsObject *object,
* vips_foreign_save_options() handles embedded options.
*/
g_object_get( object, name, &in, NULL );
if( vips_foreign_save_options( in, arg ) ) {
if( vips_foreign_save_options( in, arg, NULL ) ) {
g_object_unref( in );
return( -1 );
}
@ -1772,6 +1772,15 @@ vips_object_new( GType type, VipsObjectSetArguments set, void *a, void *b )
return( object );
}
/**
* vips_object_set_valist:
* @object: object to set arguments on
* @ap: %NULL-terminated list of argument/value pairs
*
* See vips_object_set().
*
* Returns: 0 on success, -1 on error
*/
int
vips_object_set_valist( VipsObject *object, va_list ap )
{
@ -1807,6 +1816,27 @@ vips_object_set_valist( VipsObject *object, va_list ap )
return( 0 );
}
/**
* vips_object_set:
* @object: object to set arguments on
* @...: %NULL-terminated list of argument/value pairs
*
* Set a list of vips object arguments. For example:
*
* |[
* vips_object_set (operation,
* "input", in,
* "output", &out,
* NULL);
* ]|
*
* Input arguments are given in-line, output arguments are given as pointers
* to where the output value should be written.
*
* See also: vips_object_set_valist().
*
* Returns: 0 on success, -1 on error
*/
int
vips_object_set( VipsObject *object, ... )
{

View File

@ -471,7 +471,7 @@ vips_call_required_optional( VipsOperation **operation,
va_copy( a, required );
va_copy( b, optional );
result = vips_operation_set_valist_required( *operation, a ) ||
vips_object_set_valist( *operation, b );
vips_object_set_valist( VIPS_OBJECT( *operation ), b );
va_end( a );
va_end( b );