new-style CLI save working
This commit is contained in:
parent
d6240ac11a
commit
b9db7249f4
12
TODO
12
TODO
@ -1,12 +1,6 @@
|
||||
- test ref counting in vips_object_set_argument_from_string() VipsFile stuff
|
||||
- make compat wrappers for old im_jpeg2vips() and im_vips2jpeg()
|
||||
|
||||
add path for output images, see vips_object_get_argument_to_string()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
make compat wrappers for old im_jpeg2vips() and im_vips2jpeg()
|
||||
make sure we are using the operation cache for jpegload
|
||||
|
||||
move format/* to deprecated
|
||||
|
||||
@ -15,7 +9,7 @@
|
||||
|
||||
|
||||
|
||||
- return missing just after read_xmp() in master?
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -876,6 +876,10 @@ input_interpolate_init( im_object *obj, char *str )
|
||||
interpolate_class = vips_class_find( "VipsInterpolate", "interpolate" );
|
||||
if( !(object = vips_object_new_from_string( interpolate_class, str )) )
|
||||
return( -1 );
|
||||
if( vips_object_build( object ) ) {
|
||||
g_object_unref( object );
|
||||
return( -1 );
|
||||
}
|
||||
*obj = object;
|
||||
|
||||
return( 0 );
|
||||
|
@ -547,24 +547,34 @@ vips_file_load_build( VipsObject *object )
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
/* Read header fields to init the return image. THINSTRIP since this is
|
||||
* probably a disc file. We can't tell yet whether we will be opening
|
||||
* to memory, sadly, so we can't suggest ANY.
|
||||
/* Read the header into @out.
|
||||
*/
|
||||
if( class->header &&
|
||||
class->header( load ) )
|
||||
return( -1 );
|
||||
vips_demand_hint( load->out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
|
||||
/* Then 'start' creates the real image and 'gen' fetches pixels for
|
||||
* 'out' from real on demand.
|
||||
/* If there's no ->load() method then the header read has done
|
||||
* everything. Otherwise, it's just set fields and we now must
|
||||
* convert pixels on demand.
|
||||
*/
|
||||
if( vips_image_generate( load->out,
|
||||
vips_file_load_start_cb,
|
||||
vips_file_load_generate_cb,
|
||||
vips_stop_one,
|
||||
load, NULL ) )
|
||||
return( -1 );
|
||||
if( class->load ) {
|
||||
/* THINSTRIP since this is probably a disc file.
|
||||
* We can't tell yet whether we will be opening
|
||||
* to memory, sadly, so we can't suggest ANY.
|
||||
*/
|
||||
vips_demand_hint( load->out,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, NULL );
|
||||
|
||||
/* Then 'start' creates the real image and 'gen' fetches
|
||||
* pixels for @out from @real on demand.
|
||||
*/
|
||||
if( vips_image_generate( load->out,
|
||||
vips_file_load_start_cb,
|
||||
vips_file_load_generate_cb,
|
||||
vips_stop_one,
|
||||
load, NULL ) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -640,6 +650,69 @@ vips_file_save_print_class( VipsObjectClass *object_class, VipsBuf *buf )
|
||||
VIPS_ENUM_NICK( VIPS_TYPE_SAVEABLE, class->saveable ) );
|
||||
}
|
||||
|
||||
/* Can we write this filename with this file?
|
||||
*/
|
||||
static void *
|
||||
vips_file_save_new_from_filename_sub( VipsFileSaveClass *save_class,
|
||||
const char *filename )
|
||||
{
|
||||
VipsFileClass *class = VIPS_FILE_CLASS( save_class );
|
||||
|
||||
if( vips_filename_suffix_match( filename, class->suffs ) )
|
||||
return( save_class );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_file_find_save:
|
||||
* @filename: name to find a file for
|
||||
*
|
||||
* Searches for an operation you could use to save a file.
|
||||
*
|
||||
* See also: vips_file_write().
|
||||
*
|
||||
* Returns: the name of an operation on success, %NULL on error
|
||||
*/
|
||||
const char *
|
||||
vips_file_find_save( const char *filename )
|
||||
{
|
||||
VipsFileSaveClass *save_class;
|
||||
|
||||
if( !(save_class = (VipsFileSaveClass *) vips_file_map(
|
||||
"VipsFileSave",
|
||||
(VipsSListMap2Fn) vips_file_save_new_from_filename_sub,
|
||||
(void *) filename, NULL )) ) {
|
||||
vips_error( "VipsFileSave",
|
||||
_( "\"%s\" is not a supported image file." ),
|
||||
filename );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
return( G_OBJECT_CLASS_NAME( save_class ) );
|
||||
}
|
||||
|
||||
static VipsObject *
|
||||
vips_file_save_new_from_string( const char *string )
|
||||
{
|
||||
const char *file_op;
|
||||
GType type;
|
||||
VipsFileSave *save;
|
||||
|
||||
if( !(file_op = vips_file_find_save( string )) )
|
||||
return( NULL );
|
||||
type = g_type_from_name( file_op );
|
||||
g_assert( type );
|
||||
|
||||
save = VIPS_FILE_SAVE( g_object_new( type, NULL ) );
|
||||
g_object_set( save,
|
||||
"filename", string,
|
||||
NULL );
|
||||
|
||||
return( VIPS_OBJECT( save ) );
|
||||
}
|
||||
|
||||
/* Generate the saveable image.
|
||||
*/
|
||||
static int
|
||||
@ -864,10 +937,11 @@ vips_file_save_class_init( VipsFileSaveClass *class )
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
object_class->build = vips_file_save_build;
|
||||
object_class->print_class = vips_file_save_print_class;
|
||||
object_class->new_from_string = vips_file_save_new_from_string;
|
||||
object_class->nickname = "filesave";
|
||||
object_class->description = _( "file savers" );
|
||||
object_class->print_class = vips_file_save_print_class;
|
||||
object_class->build = vips_file_save_build;
|
||||
|
||||
VIPS_ARG_IMAGE( class, "in", 0,
|
||||
_( "Input" ),
|
||||
@ -881,49 +955,6 @@ vips_file_save_init( VipsFileSave *object )
|
||||
{
|
||||
}
|
||||
|
||||
/* Can we write this filename with this file?
|
||||
*/
|
||||
static void *
|
||||
vips_file_save_new_from_filename_sub( VipsFileSaveClass *save_class,
|
||||
const char *filename )
|
||||
{
|
||||
VipsFileClass *class = VIPS_FILE_CLASS( save_class );
|
||||
|
||||
if( vips_filename_suffix_match( filename, class->suffs ) )
|
||||
return( save_class );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_file_find_save:
|
||||
* @filename: name to find a file for
|
||||
*
|
||||
* Searches for an operation you could use to save a file.
|
||||
*
|
||||
* See also: vips_file_write().
|
||||
*
|
||||
* Returns: the name of an operation on success, %NULL on error
|
||||
*/
|
||||
const char *
|
||||
vips_file_find_save( const char *filename )
|
||||
{
|
||||
VipsFileSaveClass *save_class;
|
||||
|
||||
if( !(save_class = (VipsFileSaveClass *) vips_file_map(
|
||||
"VipsFileSave",
|
||||
(VipsSListMap2Fn) vips_file_save_new_from_filename_sub,
|
||||
(void *) filename, NULL )) ) {
|
||||
vips_error( "VipsFileSave",
|
||||
_( "\"%s\" is not a supported image file." ),
|
||||
filename );
|
||||
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
return( G_OBJECT_CLASS_NAME( save_class ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_file_read:
|
||||
* @filename: file to load
|
||||
|
@ -49,16 +49,6 @@ typedef VipsFileLoadClass VipsFileLoadVipsClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsFileLoadVips, vips_file_load_vips, VIPS_TYPE_FILE_LOAD );
|
||||
|
||||
static int
|
||||
vips_file_load_vips_build( VipsObject *object )
|
||||
{
|
||||
if( VIPS_OBJECT_CLASS( vips_file_load_vips_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static gboolean
|
||||
vips_file_load_vips_is_a( const char *filename )
|
||||
{
|
||||
@ -86,20 +76,19 @@ static int
|
||||
vips_file_load_vips_header( VipsFileLoad *load )
|
||||
{
|
||||
VipsFile *file = VIPS_FILE( load );
|
||||
VipsImage *out;
|
||||
VipsImage *out2;
|
||||
|
||||
if( !(load->out = vips_image_new_from_file( file->filename )) )
|
||||
if( !(out2 = vips_image_new_from_file( file->filename )) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
/* Unref the @out that's there now.
|
||||
*/
|
||||
g_object_get( load, "out", &out, NULL );
|
||||
g_object_unref( out );
|
||||
g_object_unref( out );
|
||||
|
||||
static int
|
||||
vips_file_load_vips_load( VipsFileLoad *load )
|
||||
{
|
||||
VipsFile *file = VIPS_FILE( load );
|
||||
|
||||
if( !(load->real = vips_image_new_from_file( file->filename )) )
|
||||
return( -1 );
|
||||
g_object_set( load, "out", out2, NULL );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -115,14 +104,13 @@ vips_file_load_vips_class_init( VipsFileLoadVipsClass *class )
|
||||
|
||||
object_class->nickname = "vipsload";
|
||||
object_class->description = _( "load vips from file" );
|
||||
object_class->build = vips_file_load_vips_build;
|
||||
|
||||
file_class->suffs = vips_suffs;
|
||||
|
||||
load_class->is_a = vips_file_load_vips_is_a;
|
||||
load_class->get_flags = vips_file_load_vips_get_flags;
|
||||
load_class->header = vips_file_load_vips_header;
|
||||
load_class->load = vips_file_load_vips_load;
|
||||
load_class->load = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -145,11 +145,13 @@ typedef struct _VipsFileLoadClass {
|
||||
*/
|
||||
int (*get_flags)( VipsFileLoad * );
|
||||
|
||||
/* Read the header into @out.
|
||||
/* Set the header fields in @out from @filename. If you can read the
|
||||
* whole image as well with no performance cost (as with vipsload),
|
||||
* leave ->load() NULL.
|
||||
*/
|
||||
int (*header)( VipsFileLoad * );
|
||||
|
||||
/* Read the whole image into real. It gets copied to out later.
|
||||
/* Read the whole image into @real. It gets copied to @out later.
|
||||
*/
|
||||
int (*load)( VipsFileLoad * );
|
||||
|
||||
|
@ -682,7 +682,7 @@ vips_image_generate( VipsImage *image,
|
||||
*/
|
||||
vips_error( "VipsImage",
|
||||
_( "unable to output to a %s image" ),
|
||||
VIPS_ENUM_NICK( VIPS_TYPE_DEMAND_STYLE,
|
||||
VIPS_ENUM_NICK( VIPS_TYPE_IMAGE_TYPE,
|
||||
image->dtype ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
@ -1796,7 +1796,7 @@ vips_image_write_line( VipsImage *image, int ypos, PEL *linebuffer )
|
||||
default:
|
||||
vips_error( "VipsImage",
|
||||
_( "unable to output to a %s image" ),
|
||||
VIPS_ENUM_STRING( VIPS_TYPE_DEMAND_STYLE,
|
||||
VIPS_ENUM_STRING( VIPS_TYPE_IMAGE_TYPE,
|
||||
image->dtype ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
@ -1236,28 +1236,33 @@ vips_object_set_argument_from_string( VipsObject *object,
|
||||
VipsObject *new_object;
|
||||
VipsImage *out;
|
||||
|
||||
/* Use VipsFile to build images, then pull 'out' from it and
|
||||
* set that to set the value.
|
||||
/* Use VipsFile to build images, then pull @out from it and
|
||||
* use that to set the value.
|
||||
*/
|
||||
if( !(new_object =
|
||||
vips_object_new_from_string( oclass, value )) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_object_build( new_object ) ) {
|
||||
g_object_unref( new_object );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
g_object_get( new_object, "out", &out, NULL );
|
||||
|
||||
/* Getting 'out' will have upped it's count and we want to
|
||||
/* Getting @out will have upped it's count and we want to
|
||||
* hold the only ref to it.
|
||||
*/
|
||||
g_object_unref( out );
|
||||
|
||||
/* 'out' holds a ref to new_object, we can drop ours.
|
||||
/* @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 );
|
||||
|
||||
/* Setting gvalue will have upped out's count again,
|
||||
/* Setting gvalue will have upped @out's count again,
|
||||
* go back to 1 so that gvalue has the only ref.
|
||||
*/
|
||||
g_object_unref( out );
|
||||
@ -1270,6 +1275,11 @@ vips_object_set_argument_from_string( VipsObject *object,
|
||||
vips_object_new_from_string( oclass, value )) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_object_build( new_object ) ) {
|
||||
g_object_unref( new_object );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
g_value_init( &gvalue, G_TYPE_OBJECT );
|
||||
g_value_set_object( &gvalue, new_object );
|
||||
|
||||
@ -1407,7 +1417,30 @@ vips_object_get_argument_to_string( VipsObject *object,
|
||||
|
||||
g_assert( argument_class->flags & VIPS_ARGUMENT_OUTPUT );
|
||||
|
||||
if( g_type_is_a( otype, VIPS_TYPE_OBJECT ) &&
|
||||
if( g_type_is_a( otype, VIPS_TYPE_IMAGE ) &&
|
||||
(oclass = g_type_class_ref( VIPS_TYPE_FILE_SAVE )) ) {
|
||||
VipsObject *new_object;
|
||||
VipsImage *in;
|
||||
|
||||
/* Use VipsFile to make a saver, set 'in' on that and run
|
||||
* build to make it write.
|
||||
*/
|
||||
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_object_build( new_object ) ) {
|
||||
g_object_unref( new_object );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
g_object_unref( new_object );
|
||||
}
|
||||
else if( g_type_is_a( otype, VIPS_TYPE_OBJECT ) &&
|
||||
(oclass = g_type_class_ref( otype )) &&
|
||||
oclass->output_to_arg ) {
|
||||
VipsObject *value;
|
||||
@ -1570,11 +1603,6 @@ vips_object_new_from_string( VipsObjectClass *object_class, const char *p )
|
||||
}
|
||||
}
|
||||
|
||||
if( vips_object_build( object ) ) {
|
||||
g_object_unref( object );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
return( object );
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user