clean up options in image filenames
allow new-style options everywhere with the addition and use of vips_foreign_write_options() and friends everywhere
This commit is contained in:
parent
968c84e478
commit
5bc26b0b65
@ -58,6 +58,8 @@
|
||||
- "header" is terse by default
|
||||
- "header" outputs filenames if working on many files
|
||||
- added openslide support (Benjamin Gilbert)
|
||||
- allow new-style load/save options in filenames to
|
||||
vips_image_new_from_file() etc.
|
||||
|
||||
12/10/11 started 7.26.6
|
||||
- NOCACHE was not being set correctly on OS X causing performance
|
||||
|
32
TODO
32
TODO
@ -1,35 +1,3 @@
|
||||
- we suffs on load as well for nip2's file-open dialog
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- what should we do?
|
||||
|
||||
vips_image_new_from_file( "x.tif[page=12]" );
|
||||
|
||||
or maybe:
|
||||
|
||||
vips_image_new_from_file( "x.tif", "page", 12, NULL );
|
||||
|
||||
or maybe neither? we'd like this to work though:
|
||||
|
||||
header x.tif[page=12]
|
||||
|
||||
object_new_from_string()?
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- "header fred.png" does not work, since header uses im_open() which uses
|
||||
VipsForeign
|
||||
|
||||
|
@ -645,7 +645,7 @@ vips_foreign_save_print_class( VipsObjectClass *object_class, VipsBuf *buf )
|
||||
/* Can we write this filename with this file?
|
||||
*/
|
||||
static void *
|
||||
vips_foreign_save_new_from_foreignname_sub( VipsForeignSaveClass *save_class,
|
||||
vips_foreign_find_save_sub( VipsForeignSaveClass *save_class,
|
||||
const char *filename )
|
||||
{
|
||||
VipsForeignClass *class = VIPS_FOREIGN_CLASS( save_class );
|
||||
@ -674,7 +674,7 @@ vips_foreign_find_save( const char *filename )
|
||||
|
||||
if( !(save_class = (VipsForeignSaveClass *) vips_foreign_map(
|
||||
"VipsForeignSave",
|
||||
(VipsSListMap2Fn) vips_foreign_save_new_from_foreignname_sub,
|
||||
(VipsSListMap2Fn) vips_foreign_find_save_sub,
|
||||
(void *) filename, NULL )) ) {
|
||||
vips_error( "VipsForeignSave",
|
||||
_( "\"%s\" is not a supported image file." ),
|
||||
@ -954,7 +954,7 @@ vips_foreign_save_init( VipsForeignSave *object )
|
||||
* Loads @filename into @out using the loader recommended by
|
||||
* vips_foreign_find_load().
|
||||
*
|
||||
* See also: vips_foreign_write().
|
||||
* See also: vips_foreign_write(), vips_foreign_read_options().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
@ -979,6 +979,7 @@ vips_foreign_read( const char *filename, VipsImage **out, ... )
|
||||
* vips_foreign_write:
|
||||
* @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().
|
||||
@ -1004,6 +1005,95 @@ vips_foreign_write( VipsImage *in, const char *filename, ... )
|
||||
return( result );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_foreign_read_options:
|
||||
* @filename: file to load
|
||||
* @out: output image
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* See also: vips_foreign_read().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
vips_foreign_read_options( const char *filename, VipsImage **out )
|
||||
{
|
||||
VipsObjectClass *oclass = g_type_class_ref( VIPS_TYPE_FOREIGN_LOAD );
|
||||
|
||||
VipsObject *object;
|
||||
|
||||
/* This will use vips_foreign_load_new_from_string() to pick a loader,
|
||||
* then set options from the remains of the string.
|
||||
*/
|
||||
if( !(object = vips_object_new_from_string( oclass, filename )) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_cache_operation_build( (VipsOperation **) &object ) ) {
|
||||
/* The build may have made some output objects before
|
||||
* failing.
|
||||
*/
|
||||
vips_object_unref_outputs( object );
|
||||
g_object_unref( object );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
g_object_get( object, "out", out, NULL );
|
||||
|
||||
/* Getting @out will have upped its count so it'll be safe.
|
||||
* We can junk all other outputs,
|
||||
*/
|
||||
vips_object_unref_outputs( object );
|
||||
|
||||
/* @out holds a ref to new_object, we can drop ours.
|
||||
*/
|
||||
g_object_unref( object );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_foreign_write_options:
|
||||
* @in: image to write
|
||||
* @filename: file to write to
|
||||
*
|
||||
* Saves @in to @filename using the saver recommended by
|
||||
* vips_foreign_find_save().
|
||||
*
|
||||
* See also: vips_foreign_write().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
vips_foreign_write_options( VipsImage *in, const char *filename )
|
||||
{
|
||||
VipsObjectClass *oclass = g_type_class_ref( VIPS_TYPE_FOREIGN_SAVE );
|
||||
VipsObject *object;
|
||||
|
||||
/* This will use vips_foreign_save_new_from_string() to pick a saver,
|
||||
* then set options from the tail of the filename.
|
||||
*/
|
||||
if( !(object = vips_object_new_from_string( oclass, filename )) )
|
||||
return( -1 );
|
||||
|
||||
g_object_set( object, "in", in, NULL );
|
||||
|
||||
/* ... and running _build() should save it.
|
||||
*/
|
||||
if( vips_cache_operation_build( (VipsOperation **) &object ) ) {
|
||||
g_object_unref( object );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
g_object_unref( object );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* Called from iofuncs to init all operations in this dir. Use a plugin system
|
||||
* instead?
|
||||
*/
|
||||
|
@ -233,6 +233,9 @@ int vips_foreign_read( const char *filename, VipsImage **out, ... )
|
||||
int vips_foreign_write( VipsImage *in, const char *filename, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
int vips_foreign_read_options( const char *filename, VipsImage **out );
|
||||
int vips_foreign_write_options( VipsImage *in, const char *filename );
|
||||
|
||||
void vips_foreign_operation_init( void );
|
||||
|
||||
int vips_openslideload( const char *filename, VipsImage **out, ... )
|
||||
|
@ -466,23 +466,13 @@ vips_image_rewind( VipsObject *object )
|
||||
* to a "p" and on "written" do im_vips2tiff() or whatever.
|
||||
*/
|
||||
|
||||
/* From "written" callback: invoke a delayed save.
|
||||
/* From "written" callback: invoke a delayed save by building the write object..
|
||||
*/
|
||||
static void
|
||||
vips_image_save_cb( VipsImage *image, int *result, char *filename )
|
||||
vips_image_save_cb( VipsImage *image, int *result, VipsObject *write )
|
||||
{
|
||||
if( vips_foreign_write( image, filename, NULL ) )
|
||||
if( vips_object_build( write ) )
|
||||
*result = -1;
|
||||
|
||||
g_free( filename );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_attach_save( VipsImage *image, const char *filename )
|
||||
{
|
||||
g_signal_connect( image, "written",
|
||||
G_CALLBACK( vips_image_save_cb ),
|
||||
g_strdup( filename ) );
|
||||
}
|
||||
|
||||
/* Progress feedback.
|
||||
@ -627,7 +617,7 @@ vips_image_build( VipsObject *object )
|
||||
else {
|
||||
VipsImage *t;
|
||||
|
||||
if( vips_foreign_read( filename, &t, NULL ) )
|
||||
if( vips_foreign_read_options( filename, &t ) )
|
||||
return( -1 );
|
||||
|
||||
image->dtype = VIPS_IMAGE_PARTIAL;
|
||||
@ -642,21 +632,36 @@ vips_image_build( VipsObject *object )
|
||||
|
||||
case 'w':
|
||||
{
|
||||
const char *file_op;
|
||||
VipsObjectClass *oclass =
|
||||
g_type_class_ref( VIPS_TYPE_FOREIGN_SAVE );
|
||||
VipsObject *object;
|
||||
|
||||
if( !(file_op = vips_foreign_find_save( filename )) )
|
||||
/* This will use vips_foreign_save_new_from_string() to pick a
|
||||
* saver, then set options from the tail of the filename.
|
||||
*/
|
||||
if( !(object = vips_object_new_from_string( oclass,
|
||||
filename )) )
|
||||
return( -1 );
|
||||
vips_object_local( image, object );
|
||||
|
||||
/* Make sure the vips saver is there ... strange things will
|
||||
* happen if that type is renamed or removed.
|
||||
*/
|
||||
g_assert( g_type_from_name( "VipsForeignSaveVips" ) );
|
||||
|
||||
if( strcmp( file_op, "VipsForeignSaveVips" ) == 0 )
|
||||
/* If this ia the vips saver, just save directly ourselves.
|
||||
* Otherwise trigger a _build() and save when the image has
|
||||
* been written to.
|
||||
*/
|
||||
if( G_TYPE_CHECK_INSTANCE_TYPE( object,
|
||||
g_type_from_name( "VipsForeignSaveVips" ) ) ) {
|
||||
image->dtype = VIPS_IMAGE_OPENOUT;
|
||||
}
|
||||
else {
|
||||
image->dtype = VIPS_IMAGE_PARTIAL;
|
||||
vips_attach_save( image, filename );
|
||||
g_signal_connect( image, "written",
|
||||
G_CALLBACK( vips_image_save_cb ),
|
||||
object );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1250,8 +1250,8 @@ vips_object_set_argument_from_string( VipsObject *object,
|
||||
GParamSpec *pspec;
|
||||
VipsArgumentClass *argument_class;
|
||||
VipsArgumentInstance *argument_instance;
|
||||
GType otype;
|
||||
VipsObjectClass *oclass;
|
||||
GType otype;
|
||||
|
||||
GValue gvalue = { 0 };
|
||||
|
||||
@ -1266,39 +1266,15 @@ vips_object_set_argument_from_string( VipsObject *object,
|
||||
|
||||
g_assert( argument_class->flags & VIPS_ARGUMENT_INPUT );
|
||||
|
||||
if( g_type_is_a( otype, VIPS_TYPE_IMAGE ) &&
|
||||
(oclass = g_type_class_ref( VIPS_TYPE_FOREIGN_LOAD )) ) {
|
||||
VipsObject *new_object;
|
||||
if( g_type_is_a( otype, VIPS_TYPE_IMAGE ) ) {
|
||||
VipsImage *out;
|
||||
|
||||
/* Use VipsForeign to build images, then pull @out from it and
|
||||
* use that to set the value.
|
||||
/* Read the filename. vips_foreign_read_options()
|
||||
* handles embedded options.
|
||||
*/
|
||||
if( !(new_object =
|
||||
vips_object_new_from_string( oclass, value )) )
|
||||
if( vips_foreign_read_options( value, &out ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_cache_operation_build(
|
||||
(VipsOperation **) &new_object ) ) {
|
||||
/* The build may have made some output objects before
|
||||
* failing.
|
||||
*/
|
||||
vips_object_unref_outputs( new_object );
|
||||
g_object_unref( new_object );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
g_object_get( new_object, "out", &out, NULL );
|
||||
|
||||
/* Getting @out will have upped its count so it'll be safe.
|
||||
* We can junk all other outputs,
|
||||
*/
|
||||
vips_object_unref_outputs( new_object );
|
||||
|
||||
/* @out holds a ref to new_object, we can drop ours.
|
||||
*/
|
||||
g_object_unref( new_object );
|
||||
|
||||
g_value_init( &gvalue, VIPS_TYPE_IMAGE );
|
||||
g_value_set_object( &gvalue, out );
|
||||
|
||||
@ -1460,29 +1436,18 @@ vips_object_get_argument_to_string( VipsObject *object,
|
||||
|
||||
g_assert( argument_class->flags & VIPS_ARGUMENT_OUTPUT );
|
||||
|
||||
if( g_type_is_a( otype, VIPS_TYPE_IMAGE ) &&
|
||||
(oclass = g_type_class_ref( VIPS_TYPE_FOREIGN_SAVE )) ) {
|
||||
VipsObject *new_object;
|
||||
if( g_type_is_a( otype, VIPS_TYPE_IMAGE ) ) {
|
||||
VipsImage *in;
|
||||
|
||||
/* Use VipsForeign to make a saver, set 'in' on that and run
|
||||
* build to make it write.
|
||||
/* Pull out the image and write it.
|
||||
* vips_foreign_write_options() handles embedded options.
|
||||
*/
|
||||
if( !(new_object =
|
||||
vips_object_new_from_string( oclass, arg )) )
|
||||
return( -1 );
|
||||
|
||||
g_object_get( object, name, &in, NULL );
|
||||
g_object_set( new_object, "in", in, NULL );
|
||||
g_object_unref( in );
|
||||
|
||||
if( vips_cache_operation_build(
|
||||
(VipsOperation **) &new_object ) ) {
|
||||
g_object_unref( new_object );
|
||||
if( vips_foreign_write_options( in, arg ) ) {
|
||||
g_object_unref( in );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
g_object_unref( new_object );
|
||||
g_object_unref( in );
|
||||
}
|
||||
else if( g_type_is_a( otype, VIPS_TYPE_OBJECT ) &&
|
||||
(oclass = g_type_class_ref( otype )) &&
|
||||
|
Loading…
Reference in New Issue
Block a user