VipsCopy can change props
VipsCopy has a set of optional input args that you can use to change header fields
This commit is contained in:
parent
45b2a9a525
commit
1c65d74325
2
TODO
2
TODO
@ -14,6 +14,8 @@
|
||||
|
||||
copy_swap needs doing too, a separate class I guess
|
||||
|
||||
or add a "swap" prop and an enum like VIPS_SWAP8, VIPS_SWAP2 etc.?
|
||||
|
||||
|
||||
|
||||
- do clip/embed etc. in new style, good to get everything that VipsAdd uses in
|
||||
|
@ -73,6 +73,10 @@
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
#define VIPS_DEBUG
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
@ -84,6 +88,7 @@
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
#include <vips/debug.h>
|
||||
|
||||
#include "conversion.h"
|
||||
|
||||
@ -95,14 +100,20 @@
|
||||
* Copy an image, optionally modifying the header. VIPS copies images by
|
||||
* copying pointers, so this operation is fast, even for very large images.
|
||||
*
|
||||
* You can optionally set any or all header fields during the copy. Some
|
||||
* header fields, such as "xres", the horizontal resolution, are safe to
|
||||
* change in any way, others, such as "width" will cause immediate crashes if
|
||||
* they are not set carefully.
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
*/
|
||||
|
||||
/* Properties.
|
||||
*
|
||||
* Order important! Keep in sync with vips_copy_names[] below.
|
||||
*/
|
||||
enum {
|
||||
PROP_INPUT = 1,
|
||||
|
||||
PROP_INTERPRETATION,
|
||||
PROP_XRES,
|
||||
PROP_YRES,
|
||||
@ -164,12 +175,31 @@ vips_copy_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* The props we copy, if set, from the operation to the image.
|
||||
*/
|
||||
static const char *vips_copy_names[] = {
|
||||
NULL, /* unused */
|
||||
NULL, /* PROP_INPUT = 1 */
|
||||
"interpretation", /* PROP_INTERPRETATION, */
|
||||
"xres", /* PROP_XRES, */
|
||||
"yres", /* PROP_YRES, */
|
||||
"xoffset", /* PROP_XOFFSET, */
|
||||
"xoffset", /* PROP_YOFFSET, */
|
||||
"bands", /* PROP_BANDS, */
|
||||
"format", /* PROP_FORMAT, */
|
||||
"coding", /* PROP_CODING, */
|
||||
"width", /* PROP_WIDTH, */
|
||||
"height" /* PROP_HEIGHT, */
|
||||
};
|
||||
|
||||
static int
|
||||
vips_copy_build( VipsObject *object )
|
||||
{
|
||||
VipsConversion *conversion = VIPS_CONVERSION( object );
|
||||
VipsCopy *copy = (VipsCopy *) object;
|
||||
|
||||
int i;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_copy_parent_class )->build( object ) )
|
||||
return( -1 );
|
||||
|
||||
@ -177,12 +207,40 @@ vips_copy_build( VipsObject *object )
|
||||
vips_image_pio_output( conversion->output ) )
|
||||
return( -1 );
|
||||
|
||||
/* Use props to adjust header fields.
|
||||
*/
|
||||
|
||||
if( vips_image_copy_fields( conversion->output, copy->input ) )
|
||||
return( -1 );
|
||||
vips_demand_hint( conversion->output,
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, copy->input, NULL );
|
||||
|
||||
/* Use props to adjust header fields.
|
||||
*/
|
||||
for( i = 2; i < PROP_LAST; i++ ) {
|
||||
const char *name = vips_copy_names[i];
|
||||
|
||||
GParamSpec *pspec;
|
||||
VipsArgumentClass *argument_class;
|
||||
VipsArgumentInstance *argument_instance;
|
||||
|
||||
if( vips_object_get_argument( object, name,
|
||||
&pspec, &argument_class, &argument_instance ) )
|
||||
return( -1 );
|
||||
|
||||
if( argument_instance->assigned ) {
|
||||
GType type = G_PARAM_SPEC_VALUE_TYPE( pspec );
|
||||
GValue value = { 0, };
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_copy_build: assigning %s\n",
|
||||
name );
|
||||
|
||||
g_value_init( &value, type );
|
||||
g_object_get_property( G_OBJECT( object ),
|
||||
name, &value );
|
||||
g_object_set_property( G_OBJECT( conversion->output ),
|
||||
name, &value );
|
||||
g_value_unset( &value );
|
||||
}
|
||||
}
|
||||
|
||||
if( vips_image_generate( conversion->output,
|
||||
vips_start_one, vips_copy_gen, vips_stop_one,
|
||||
copy->input, copy ) )
|
||||
|
@ -1260,27 +1260,21 @@ vips_object_set_argument_from_string( VipsObject *object,
|
||||
gboolean
|
||||
vips_object_get_argument_needs_string( VipsObject *object, const char *name )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
|
||||
GParamSpec *pspec;
|
||||
GType otype;
|
||||
VipsArgumentClass *argument_class;
|
||||
VipsArgumentInstance *argument_instance;
|
||||
VipsObjectClass *oclass;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf( "vips_object_get_argument_needs_string: %s\n", name );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
pspec = g_object_class_find_property( G_OBJECT_CLASS( class ), name );
|
||||
if( !pspec ) {
|
||||
vips_error( "VipsObject", _( "%s.%s does not exist" ),
|
||||
G_OBJECT_TYPE_NAME( object ), name );
|
||||
if( vips_object_get_argument( object, name,
|
||||
&pspec, &argument_class, &argument_instance ) )
|
||||
return( -1 );
|
||||
}
|
||||
otype = G_PARAM_SPEC_VALUE_TYPE( pspec );
|
||||
|
||||
argument_class = (VipsArgumentClass *)
|
||||
vips__argument_table_lookup( class->argument_table, pspec );
|
||||
otype = G_PARAM_SPEC_VALUE_TYPE( pspec );
|
||||
|
||||
g_assert( argument_class->flags & VIPS_ARGUMENT_OUTPUT );
|
||||
|
||||
@ -1316,11 +1310,10 @@ int
|
||||
vips_object_get_argument_to_string( VipsObject *object,
|
||||
const char *name, const char *arg )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||
|
||||
GParamSpec *pspec;
|
||||
GType otype;
|
||||
VipsArgumentClass *argument_class;
|
||||
VipsArgumentInstance *argument_instance;
|
||||
VipsObjectClass *oclass;
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -1328,16 +1321,11 @@ vips_object_get_argument_to_string( VipsObject *object,
|
||||
name, arg );
|
||||
#endif /*DEBUG*/
|
||||
|
||||
pspec = g_object_class_find_property( G_OBJECT_CLASS( class ), name );
|
||||
if( !pspec ) {
|
||||
vips_error( "VipsObject", _( "%s.%s does not exist" ),
|
||||
G_OBJECT_TYPE_NAME( object ), name );
|
||||
if( vips_object_get_argument( object, name,
|
||||
&pspec, &argument_class, &argument_instance ) )
|
||||
return( -1 );
|
||||
}
|
||||
otype = G_PARAM_SPEC_VALUE_TYPE( pspec );
|
||||
|
||||
argument_class = (VipsArgumentClass *)
|
||||
vips__argument_table_lookup( class->argument_table, pspec );
|
||||
otype = G_PARAM_SPEC_VALUE_TYPE( pspec );
|
||||
|
||||
g_assert( argument_class->flags & VIPS_ARGUMENT_OUTPUT );
|
||||
|
||||
|
@ -311,11 +311,6 @@ vips_operation_set_valist_required( VipsOperation *operation, va_list ap )
|
||||
static int
|
||||
vips_operation_set_valist_optional( VipsOperation *operation, va_list ap )
|
||||
{
|
||||
VipsOperationClass *class =
|
||||
VIPS_OPERATION_GET_CLASS( operation );
|
||||
VipsArgumentTable *argument_table =
|
||||
VIPS_OBJECT_CLASS( class )->argument_table;
|
||||
|
||||
char *name;
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_operation_set_valist_optional:\n" );
|
||||
@ -325,29 +320,22 @@ vips_operation_set_valist_optional( VipsOperation *operation, va_list ap )
|
||||
while( name ) {
|
||||
GParamSpec *pspec;
|
||||
VipsArgumentClass *argument_class;
|
||||
VipsArgumentInstance *argument_instance;
|
||||
|
||||
VIPS_DEBUG_MSG( "\tname = '%s' (%p)\n", name, name );
|
||||
|
||||
if( !(pspec = g_object_class_find_property(
|
||||
G_OBJECT_CLASS( class ), name )) ) {
|
||||
vips_error( VIPS_OBJECT_CLASS( class )->description,
|
||||
_( "class `%s' has no property named `%s'\n" ),
|
||||
G_OBJECT_TYPE_NAME( operation ), name );
|
||||
if( vips_object_get_argument( VIPS_OBJECT( operation ), name,
|
||||
&pspec, &argument_class, &argument_instance ) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
argument_class = (VipsArgumentClass *)
|
||||
vips__argument_table_lookup( argument_table, pspec );
|
||||
if( argument_class ) {
|
||||
VIPS_OPERATION_COLLECT_SET( pspec, argument_class, ap );
|
||||
VIPS_OPERATION_COLLECT_SET( pspec, argument_class, ap );
|
||||
|
||||
g_object_set_property( G_OBJECT( operation ),
|
||||
name, &value );
|
||||
g_object_set_property( G_OBJECT( operation ),
|
||||
name, &value );
|
||||
|
||||
VIPS_OPERATION_COLLECT_GET( pspec, argument_class, ap );
|
||||
VIPS_OPERATION_COLLECT_GET( pspec, argument_class, ap );
|
||||
|
||||
VIPS_OPERATION_COLLECT_END
|
||||
}
|
||||
VIPS_OPERATION_COLLECT_END
|
||||
|
||||
name = va_arg( ap, char * );
|
||||
}
|
||||
@ -402,11 +390,6 @@ vips_operation_get_valist_required( VipsOperation *operation, va_list ap )
|
||||
static int
|
||||
vips_operation_get_valist_optional( VipsOperation *operation, va_list ap )
|
||||
{
|
||||
VipsOperationClass *class =
|
||||
VIPS_OPERATION_GET_CLASS( operation );
|
||||
VipsArgumentTable *argument_table =
|
||||
VIPS_OBJECT_CLASS( class )->argument_table;
|
||||
|
||||
char *name;
|
||||
|
||||
VIPS_DEBUG_MSG( "vips_operation_get_valist_optional:\n" );
|
||||
@ -416,54 +399,47 @@ vips_operation_get_valist_optional( VipsOperation *operation, va_list ap )
|
||||
while( name ) {
|
||||
GParamSpec *pspec;
|
||||
VipsArgumentClass *argument_class;
|
||||
VipsArgumentInstance *argument_instance;
|
||||
|
||||
VIPS_DEBUG_MSG( "\tname = '%s' (%p)\n", name, name );
|
||||
|
||||
if( !(pspec = g_object_class_find_property(
|
||||
G_OBJECT_CLASS( class ), name )) ) {
|
||||
vips_error( VIPS_OBJECT_CLASS( class )->description,
|
||||
_( "class `%s' has no property named `%s'\n" ),
|
||||
G_OBJECT_TYPE_NAME( operation ), name );
|
||||
if( vips_object_get_argument( VIPS_OBJECT( operation ), name,
|
||||
&pspec, &argument_class, &argument_instance ) )
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
argument_class = (VipsArgumentClass *)
|
||||
vips__argument_table_lookup( argument_table, pspec );
|
||||
if( argument_class ) {
|
||||
VIPS_OPERATION_COLLECT_SET( pspec, argument_class, ap );
|
||||
VIPS_OPERATION_COLLECT_SET( pspec, argument_class, ap );
|
||||
|
||||
g_object_set_property( G_OBJECT( operation ),
|
||||
name, &value );
|
||||
g_object_set_property( G_OBJECT( operation ),
|
||||
name, &value );
|
||||
|
||||
VIPS_OPERATION_COLLECT_GET( pspec, argument_class, ap );
|
||||
VIPS_OPERATION_COLLECT_GET( pspec, argument_class, ap );
|
||||
|
||||
#ifdef VIPS_DEBUG
|
||||
printf( "\twriting %s to %p\n",
|
||||
g_param_spec_get_name( pspec ), arg );
|
||||
printf( "\twriting %s to %p\n",
|
||||
g_param_spec_get_name( pspec ), arg );
|
||||
#endif /*VIPS_DEBUG */
|
||||
|
||||
/* If the dest pointer is NULL, skip the read.
|
||||
/* If the dest pointer is NULL, skip the read.
|
||||
*/
|
||||
if( arg ) {
|
||||
g_object_get( G_OBJECT( operation ),
|
||||
g_param_spec_get_name( pspec ), arg,
|
||||
NULL );
|
||||
|
||||
/* If the pspec is an object, that will up
|
||||
* the ref count. We want to hand over the
|
||||
* ref, so we have to knock it down again.
|
||||
*/
|
||||
if( arg ) {
|
||||
g_object_get( G_OBJECT( operation ),
|
||||
g_param_spec_get_name( pspec ), arg,
|
||||
NULL );
|
||||
if( G_IS_PARAM_SPEC_OBJECT( pspec ) ) {
|
||||
GObject *object;
|
||||
|
||||
/* If the pspec is an object, that will up
|
||||
* the ref count. We want to hand over the
|
||||
* ref, so we have to knock it down again.
|
||||
*/
|
||||
if( G_IS_PARAM_SPEC_OBJECT( pspec ) ) {
|
||||
GObject *object;
|
||||
|
||||
object = *((GObject **) arg);
|
||||
g_object_unref( object );
|
||||
}
|
||||
object = *((GObject **) arg);
|
||||
g_object_unref( object );
|
||||
}
|
||||
|
||||
VIPS_OPERATION_COLLECT_END
|
||||
}
|
||||
|
||||
VIPS_OPERATION_COLLECT_END
|
||||
|
||||
name = va_arg( ap, char * );
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user