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 - add :seq support to im_tiff2vips(), im_jpeg2vips() ... helps ruby-vips
- better thread safety for vips8 operation dispatch - better thread safety for vips8 operation dispatch
- better thread safety for upstream / downstream image linking - better thread safety for upstream / downstream image linking
- added "rs" open mode, removed "rd"
18/6/12 started 7.28.9 18/6/12 started 7.28.9
- slightly more memory debugging output - 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" - need a flag on operations for "is sequential"
should be on the object, not the class, since it can change with params 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: * vips_foreign_load_options:
* @filename: file to load * @filename: file to load
* @out: output image * @out: output image
* @...: %NULL-terminated list of optional named arguments
* *
* Loads @filename into @out using the loader recommended by * Loads @filename into @out using the loader recommended by
* vips_foreign_find_load(). * vips_foreign_find_load().
* *
* Arguments to the loader may be embedded in the filename using the usual * 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(). * See also: vips_foreign_load().
* *
* Returns: 0 on success, -1 on error * Returns: 0 on success, -1 on error
*/ */
int 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 ); VipsObjectClass *oclass = g_type_class_ref( VIPS_TYPE_FOREIGN_LOAD );
VipsObject *object; VipsObject *object;
va_list ap;
int result;
/* This will use vips_foreign_load_new_from_string() to pick a loader, /* This will use vips_foreign_load_new_from_string() to pick a loader,
* then set options from the remains of the string. * 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 )) ) if( !(object = vips_object_new_from_string( oclass, filename )) )
return( -1 ); 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 ) ) { if( vips_cache_operation_buildp( (VipsOperation **) &object ) ) {
/* The build may have made some output objects before /* The build may have made some output objects before
* failing. * failing.
@ -1540,22 +1552,27 @@ vips_foreign_load_options( const char *filename, VipsImage **out )
* vips_foreign_save_options: * vips_foreign_save_options:
* @in: image to write * @in: image to write
* @filename: file to write to * @filename: file to write to
* @...: %NULL-terminated list of optional named arguments
* *
* Saves @in to @filename using the saver recommended by * Saves @in to @filename using the saver recommended by
* vips_foreign_find_save(). * vips_foreign_find_save().
* *
* Arguments to the saver may be embedded in the filename using the usual * 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(). * See also: vips_foreign_save().
* *
* Returns: 0 on success, -1 on error * Returns: 0 on success, -1 on error
*/ */
int 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 ); VipsObjectClass *oclass = g_type_class_ref( VIPS_TYPE_FOREIGN_SAVE );
VipsObject *object; VipsObject *object;
va_list ap;
int result;
/* This will use vips_foreign_save_new_from_string() to pick a saver, /* This will use vips_foreign_save_new_from_string() to pick a saver,
* then set options from the tail of the filename. * 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 ); 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. /* ... and running _build() should save it.
*/ */
if( vips_cache_operation_buildp( (VipsOperation **) &object ) ) { 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, ... ) int vips_foreign_save( VipsImage *in, const char *filename, ... )
__attribute__((sentinel)); __attribute__((sentinel));
int vips_foreign_load_options( const char *filename, VipsImage **out ); int vips_foreign_load_options( const char *filename, VipsImage **out, ... )
int vips_foreign_save_options( VipsImage *in, const char *filename ); __attribute__((sentinel));
int vips_foreign_save_options( VipsImage *in, const char *filename, ... )
__attribute__((sentinel));
int vips_openslideload( const char *filename, VipsImage **out, ... ) int vips_openslideload( const char *filename, VipsImage **out, ... )
__attribute__((sentinel)); __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 ) ); image = VIPS_IMAGE( g_object_new( VIPS_TYPE_IMAGE, NULL ) );
g_object_set( image, g_object_set( image,
"filename", string, "filename", string,
"mode", "rd", "mode", "r",
NULL ); NULL );
return( VIPS_OBJECT( image ) ); return( VIPS_OBJECT( image ) );
@ -508,7 +508,7 @@ vips_image_rewind( VipsObject *object )
static void static void
vips_image_save_cb( VipsImage *image, int *result ) 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; *result = -1;
} }
@ -655,8 +655,17 @@ vips_image_build( VipsObject *object )
else { else {
VipsImage *t; VipsImage *t;
if( vips_foreign_load_options( filename, &t ) ) if( mode[1] == 's' ) {
return( -1 ); 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; image->dtype = VIPS_IMAGE_PARTIAL;
if( vips_image_write( t, image ) ) { if( vips_image_write( t, image ) ) {
@ -1370,28 +1379,20 @@ vips_image_new( void )
* VIPS format for your machine, vips_image_new_mode() * VIPS format for your machine, vips_image_new_mode()
* automatically converts the file for you. * automatically converts the file for you.
* *
* For some large files (eg. TIFF) this may * Some formats (eg. tiled tiff) are read directly.
* 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. 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 * API and control the loading process yourself. See
* #VipsForeign. * #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 * See im_system_image() for an explanation of how VIPS selects a
* location for the temporary file. * 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 * will copy via disc if "fred.tif" is more than 500 Mbytes
* uncompressed. The default threshold is 100 MB. * 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> * </para>
* </listitem> * </listitem>
* <listitem> * <listitem>
@ -1479,7 +1494,7 @@ vips_image_new_buffer( void )
* vips_image_new_from_file: * vips_image_new_from_file:
* @filename: file to open * @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. * vips_image_new_mode() for details.
* *
* See also: vips_image_new_mode(). * See also: vips_image_new_mode().
@ -1489,7 +1504,7 @@ vips_image_new_buffer( void )
VipsImage * VipsImage *
vips_image_new_from_file( const char *filename ) 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() /* Read the filename. vips_foreign_load_options()
* handles embedded options. * handles embedded options.
*/ */
if( vips_foreign_load_options( value, &out ) ) if( vips_foreign_load_options( value, &out, NULL ) )
return( -1 ); return( -1 );
g_value_init( &gvalue, VIPS_TYPE_IMAGE ); 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. * vips_foreign_save_options() handles embedded options.
*/ */
g_object_get( object, name, &in, NULL ); 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 ); g_object_unref( in );
return( -1 ); return( -1 );
} }
@ -1772,6 +1772,15 @@ vips_object_new( GType type, VipsObjectSetArguments set, void *a, void *b )
return( object ); 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 int
vips_object_set_valist( VipsObject *object, va_list ap ) vips_object_set_valist( VipsObject *object, va_list ap )
{ {
@ -1807,6 +1816,27 @@ vips_object_set_valist( VipsObject *object, va_list ap )
return( 0 ); 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 int
vips_object_set( VipsObject *object, ... ) vips_object_set( VipsObject *object, ... )
{ {

View File

@ -471,7 +471,7 @@ vips_call_required_optional( VipsOperation **operation,
va_copy( a, required ); va_copy( a, required );
va_copy( b, optional ); va_copy( b, optional );
result = vips_operation_set_valist_required( *operation, a ) || 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( a );
va_end( b ); va_end( b );