sync
This commit is contained in:
parent
9ea6fc6653
commit
210668edc2
24
TODO
24
TODO
@ -1,25 +1,11 @@
|
|||||||
- we have VIPS_ARG_ARRAY, but really we need to say it's an array of double
|
- what should the member of VipsInsert be? what does get_member do for boxed?
|
||||||
|
just the pointer I guess
|
||||||
|
|
||||||
can we derive from G_TYPE_ARRAY and make G_TYPE_ARRAY_DOUBLE?
|
does that mean VipsInsert sees an Area?
|
||||||
|
|
||||||
no, we have to make a fresh boxed type
|
yes, vips_object_set_property() writes g_value_dup_boxed() to the member
|
||||||
|
|
||||||
maybe make a boxed type which is a GArray plus a GType for array members?
|
argh do we have to expose Area now?
|
||||||
then we could have array of double
|
|
||||||
|
|
||||||
insert.c needs to have a member like this
|
|
||||||
|
|
||||||
GArray *background;
|
|
||||||
|
|
||||||
and declare it as an array of double, and be guaranteed that background is
|
|
||||||
all double
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
make a new boxed type for typed array which is a GArray plus a GType
|
|
||||||
|
|
||||||
specialise this into array_double, cf. the way we make a refstring out of a
|
|
||||||
VipsArea
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -418,13 +418,12 @@ vips_insert_class_init( VipsInsertClass *class )
|
|||||||
G_STRUCT_OFFSET( VipsInsert, expand ),
|
G_STRUCT_OFFSET( VipsInsert, expand ),
|
||||||
FALSE );
|
FALSE );
|
||||||
|
|
||||||
VIPS_ARG_ARRAY( class, "background", 5,
|
VIPS_ARG_BOXED( class, "background", 5,
|
||||||
_( "Background" ),
|
_( "Background" ),
|
||||||
_( "Colour for new pixels" ),
|
_( "Colour for new pixels" ),
|
||||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
G_STRUCT_OFFSET( VipsInsert, background ),
|
G_STRUCT_OFFSET( VipsInsert, background ),
|
||||||
FALSE );
|
VIPS_TYPE_ARRAY_DOUBLE );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -163,7 +163,7 @@ int vips_blob_set( GValue *value, VipsCallbackFn free_fn,
|
|||||||
/**
|
/**
|
||||||
* VIPS_TYPE_ARRAY_DOUBLE:
|
* VIPS_TYPE_ARRAY_DOUBLE:
|
||||||
*
|
*
|
||||||
* The #GType for an #vips_blob.
|
* The #GType for an #vips_array_double.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define VIPS_TYPE_ARRAY_DOUBLE (vips_array_double_get_type())
|
#define VIPS_TYPE_ARRAY_DOUBLE (vips_array_double_get_type())
|
||||||
|
@ -120,8 +120,8 @@ extern int _vips__argument_id;
|
|||||||
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \
|
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VIPS_ARG_BOOL( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, \
|
#define VIPS_ARG_BOOL( CLASS, NAME, PRIORITY, LONG, DESC, \
|
||||||
VALUE ) { \
|
FLAGS, OFFSET, VALUE ) { \
|
||||||
GParamSpec *pspec; \
|
GParamSpec *pspec; \
|
||||||
\
|
\
|
||||||
pspec = g_param_spec_boolean( (NAME), (LONG), (DESC), \
|
pspec = g_param_spec_boolean( (NAME), (LONG), (DESC), \
|
||||||
@ -133,8 +133,8 @@ extern int _vips__argument_id;
|
|||||||
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \
|
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VIPS_ARG_DOUBLE( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, \
|
#define VIPS_ARG_DOUBLE( CLASS, NAME, PRIORITY, LONG, DESC, \
|
||||||
MIN, MAX, VALUE ) { \
|
FLAGS, OFFSET, MIN, MAX, VALUE ) { \
|
||||||
GParamSpec *pspec; \
|
GParamSpec *pspec; \
|
||||||
\
|
\
|
||||||
pspec = g_param_spec_double( (NAME), (LONG), (DESC), \
|
pspec = g_param_spec_double( (NAME), (LONG), (DESC), \
|
||||||
@ -146,12 +146,12 @@ extern int _vips__argument_id;
|
|||||||
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \
|
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VIPS_ARG_ARRAY( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, \
|
#define VIPS_ARG_BOXED( CLASS, NAME, PRIORITY, LONG, DESC, \
|
||||||
MIN, MAX, VALUE ) { \
|
FLAGS, OFFSET, TYPE ) \
|
||||||
GParamSpec *pspec; \
|
GParamSpec *pspec; \
|
||||||
\
|
\
|
||||||
pspec = g_param_spec_boxed( (NAME), (LONG), (DESC), \
|
pspec = g_param_spec_boxed( (NAME), (LONG), (DESC), \
|
||||||
G_TYPE_ARRAY, \
|
(TYPE), \
|
||||||
G_PARAM_READWRITE );\
|
G_PARAM_READWRITE );\
|
||||||
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
|
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
|
||||||
_vips__argument_id++, pspec ); \
|
_vips__argument_id++, pspec ); \
|
||||||
@ -159,8 +159,8 @@ extern int _vips__argument_id;
|
|||||||
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \
|
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VIPS_ARG_INT( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, \
|
#define VIPS_ARG_INT( CLASS, NAME, PRIORITY, LONG, DESC, \
|
||||||
MIN, MAX, VALUE ) { \
|
FLAGS, OFFSET, MIN, MAX, VALUE ) { \
|
||||||
GParamSpec *pspec; \
|
GParamSpec *pspec; \
|
||||||
\
|
\
|
||||||
pspec = g_param_spec_int( (NAME), (LONG), (DESC), \
|
pspec = g_param_spec_int( (NAME), (LONG), (DESC), \
|
||||||
@ -172,8 +172,8 @@ extern int _vips__argument_id;
|
|||||||
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \
|
pspec, (FLAGS), (PRIORITY), (OFFSET) ); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VIPS_ARG_ENUM( CLASS, NAME, PRIORITY, LONG, DESC, FLAGS, OFFSET, \
|
#define VIPS_ARG_ENUM( CLASS, NAME, PRIORITY, LONG, DESC, \
|
||||||
TYPE, VALUE ) { \
|
FLAGS, OFFSET, TYPE, VALUE ) { \
|
||||||
GParamSpec *pspec; \
|
GParamSpec *pspec; \
|
||||||
\
|
\
|
||||||
pspec = g_param_spec_enum( (NAME), (LONG), (DESC), \
|
pspec = g_param_spec_enum( (NAME), (LONG), (DESC), \
|
||||||
|
@ -991,7 +991,8 @@ transform_int_save_string( const GValue *src_value, GValue *dest_value )
|
|||||||
static void
|
static void
|
||||||
transform_save_string_int( const GValue *src_value, GValue *dest_value )
|
transform_save_string_int( const GValue *src_value, GValue *dest_value )
|
||||||
{
|
{
|
||||||
g_value_set_int( dest_value, atoi( vips_save_string_get( src_value ) ) );
|
g_value_set_int( dest_value,
|
||||||
|
atoi( vips_save_string_get( src_value ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1017,9 +1018,18 @@ transform_save_string_double( const GValue *src_value, GValue *dest_value )
|
|||||||
*/
|
*/
|
||||||
typedef struct _Area {
|
typedef struct _Area {
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
size_t length; /* 0 if not known */
|
size_t length; /* 0 if not known */
|
||||||
void *data;
|
void *data;
|
||||||
|
|
||||||
VipsCallbackFn free_fn;
|
VipsCallbackFn free_fn;
|
||||||
|
|
||||||
|
/* If we are holding an array (for exmaple, an array of double), the
|
||||||
|
* GType of elements and their size. Calculate the number of elements
|
||||||
|
* in the array from this.
|
||||||
|
*/
|
||||||
|
GType type;
|
||||||
|
size_t sizeof_type;
|
||||||
} Area;
|
} Area;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -1040,6 +1050,8 @@ area_new( VipsCallbackFn free_fn, void *data )
|
|||||||
area->length = 0;
|
area->length = 0;
|
||||||
area->data = data;
|
area->data = data;
|
||||||
area->free_fn = free_fn;
|
area->free_fn = free_fn;
|
||||||
|
area->type = 0;
|
||||||
|
area->sizeof_type = 0;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
area_number += 1;
|
area_number += 1;
|
||||||
@ -1328,7 +1340,8 @@ transform_g_string_ref_string( const GValue *src_value, GValue *dest_value )
|
|||||||
static void
|
static void
|
||||||
transform_ref_string_save_string( const GValue *src_value, GValue *dest_value )
|
transform_ref_string_save_string( const GValue *src_value, GValue *dest_value )
|
||||||
{
|
{
|
||||||
vips_save_string_setf( dest_value, "%s", vips_ref_string_get( src_value ) );
|
vips_save_string_setf( dest_value,
|
||||||
|
"%s", vips_ref_string_get( src_value ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1487,102 +1500,107 @@ vips_blob_set( GValue *value,
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
double *
|
/* An area which holds a copy of an array of GType.
|
||||||
vips_array_double_get( const GValue *value, int *length )
|
*/
|
||||||
|
static Area *
|
||||||
|
area_new_array( GType type, size_t sizeof_type, int n )
|
||||||
{
|
{
|
||||||
GArray *garray;
|
Area *area;
|
||||||
|
void *array;
|
||||||
|
|
||||||
if( !(garray = g_value_get_boxed( value )) ) {
|
array = g_malloc( n * sizeof_type );
|
||||||
garray = g_array_sized_new( FALSE, FALSE, sizeof( double ), 0 );
|
if( !(area = area_new( g_free, array )) )
|
||||||
g_value_set_boxed( value, garray );
|
return( NULL );
|
||||||
}
|
area->length = n * sizeof_type;
|
||||||
|
area->type = G_TYPE_DOUBLE;
|
||||||
|
area->sizeof_type = sizeof_type;
|
||||||
|
|
||||||
if( length )
|
return( area );
|
||||||
*length = garray->len;
|
|
||||||
|
|
||||||
return( (double *) garray->data );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
/* Set value to be an array of things. Don't initialise the contents: get the
|
||||||
vips_array_double_set( GValue *value, double *array, int length )
|
* pointer and write instead.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
vips_array_set( GValue *value, GType type, size_t sizeof_type, int n )
|
||||||
{
|
{
|
||||||
GArray *garray;
|
Area *area;
|
||||||
|
|
||||||
if( !(garray = g_value_get_boxed( value )) ) {
|
g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_ARRAY );
|
||||||
garray = g_array_sized_new( FALSE, FALSE, sizeof( double ),
|
|
||||||
length );
|
|
||||||
g_value_set_boxed( value, garray );
|
|
||||||
}
|
|
||||||
|
|
||||||
g_array_remove_range( garray, 0, garray->len );
|
if( !(area = area_new_array( type, sizeof_type, n )) )
|
||||||
g_array_append_vals( garray, array, length );
|
return( -1 );
|
||||||
|
g_value_set_boxed( value, area );
|
||||||
|
area_unref( area );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void *
|
||||||
transform_array_double_g_string( const GValue *src_value, GValue *dest_value )
|
vips_array_get( const GValue *value,
|
||||||
|
int *length, GType *type, size_t *sizeof_type )
|
||||||
{
|
{
|
||||||
double *array;
|
Area *area;
|
||||||
|
|
||||||
|
/* Can't check value type, because we may get called from
|
||||||
|
* vips_*_get_type().
|
||||||
|
*/
|
||||||
|
|
||||||
|
area = g_value_get_boxed( value );
|
||||||
|
if( length )
|
||||||
|
*length = area->length;
|
||||||
|
if( type )
|
||||||
|
*type = area->type;
|
||||||
|
if( sizeof_type )
|
||||||
|
*sizeof_type = area->sizeof_type;
|
||||||
|
|
||||||
|
return( area->data );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
transform_array_g_string( const GValue *src_value, GValue *dest_value )
|
||||||
|
{
|
||||||
|
char *array;
|
||||||
int length;
|
int length;
|
||||||
|
GType type;
|
||||||
|
size_t sizeof_type;
|
||||||
|
int n;
|
||||||
char txt[1024];
|
char txt[1024];
|
||||||
VipsBuf buf = VIPS_BUF_STATIC( txt );
|
VipsBuf buf = VIPS_BUF_STATIC( txt );
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
array = vips_array_double_get( src_value, &length );
|
array = (char *) vips_array_get( src_value,
|
||||||
|
&length, &type, &sizeof_type );
|
||||||
|
n = length / sizeof_type;
|
||||||
|
|
||||||
|
for( i = 0; i < n; i++ ) {
|
||||||
|
GValue value = { 0, };
|
||||||
|
|
||||||
for( i = 0; i < length; i++ ) {
|
|
||||||
if( i > 0 )
|
if( i > 0 )
|
||||||
vips_buf_appends( &buf, ", " );
|
vips_buf_appends( &buf, ", " );
|
||||||
vips_buf_appendf( &buf, "%g", array[i] );
|
|
||||||
|
g_value_init( &value, type );
|
||||||
|
g_value_set_instance( &value, array );
|
||||||
|
|
||||||
|
str = g_strdup_value_contents( &value );
|
||||||
|
vips_buf_appends( &buf, str );
|
||||||
|
g_free( str );
|
||||||
|
|
||||||
|
g_value_unset( &value );
|
||||||
|
|
||||||
|
array += sizeof_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_value_set_string( dest_value, vips_buf_all( &buf ) );
|
g_value_set_string( dest_value, vips_buf_all( &buf ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/* We don't have functions to save arrays to save_str and back. We'd need to
|
||||||
transform_array_double_save_string( const GValue *src_value,
|
* save the type as well as the members and number of members, something like:
|
||||||
GValue *dest_value )
|
*
|
||||||
{
|
* double { 12.3, 13.7 }
|
||||||
double *array;
|
*
|
||||||
int length;
|
* Anyway, no call for this yet.
|
||||||
GString *string;
|
*/
|
||||||
int i;
|
|
||||||
|
|
||||||
array = vips_array_double_get( src_value, &length );
|
|
||||||
|
|
||||||
string = g_string_new( "" );
|
|
||||||
for( i = 0; i < length; i++ ) {
|
|
||||||
char buf[G_ASCII_DTOSTR_BUF_SIZE];
|
|
||||||
|
|
||||||
if( i > 0 )
|
|
||||||
g_string_append_printf( string, "," );
|
|
||||||
g_ascii_dtostr( buf, G_ASCII_DTOSTR_BUF_SIZE, array[i] );
|
|
||||||
g_string_append( string, buf );
|
|
||||||
}
|
|
||||||
|
|
||||||
g_value_set_string( dest_value, string->str );
|
|
||||||
|
|
||||||
g_string_free( string, TRUE );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
transform_save_string_array_double( const GValue *src_value,
|
|
||||||
GValue *dest_value )
|
|
||||||
{
|
|
||||||
GArray *garray;
|
|
||||||
|
|
||||||
if( !(garray = g_value_get_boxed( dest_value )) )
|
|
||||||
garray = g_array_sized_new( FALSE, FALSE, sizeof( double ), 0 );
|
|
||||||
else
|
|
||||||
g_array_remove_range( garray, 0, garray->len );
|
|
||||||
|
|
||||||
|
|
||||||
parse to ,
|
|
||||||
g_ascii_strtod to garray
|
|
||||||
|
|
||||||
will this repeatedly realloc?
|
|
||||||
}
|
|
||||||
|
|
||||||
GType
|
GType
|
||||||
vips_array_double_get_type( void )
|
vips_array_double_get_type( void )
|
||||||
@ -1591,23 +1609,65 @@ vips_array_double_get_type( void )
|
|||||||
|
|
||||||
if( !type ) {
|
if( !type ) {
|
||||||
type = g_boxed_type_register_static( "vips_array_double",
|
type = g_boxed_type_register_static( "vips_array_double",
|
||||||
(GBoxedCopyFunc) g_array_ref,
|
(GBoxedCopyFunc) area_ref,
|
||||||
(GBoxedFreeFunc) g_array_copy );
|
(GBoxedFreeFunc) area_copy );
|
||||||
g_value_register_transform_func( type, G_TYPE_STRING,
|
g_value_register_transform_func( type, G_TYPE_STRING,
|
||||||
transform_array_double_g_string );
|
transform_array_g_string );
|
||||||
g_value_register_transform_func( type, VIPS_TYPE_SAVE_STRING,
|
|
||||||
transform_array_double_save_string );
|
|
||||||
g_value_register_transform_func( VIPS_TYPE_SAVE_STRING, type,
|
|
||||||
transform_save_string_array_double );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return( type );
|
return( type );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vips_array_double_get:
|
||||||
|
* @value: #GValue to get from
|
||||||
|
* @n: return the number of elements here, optionally
|
||||||
|
*
|
||||||
|
* Return the start of the array of doubles held by @value.
|
||||||
|
* optionally return the number of elements in @n.
|
||||||
|
*
|
||||||
|
* See also: vips_array_double_set().
|
||||||
|
*
|
||||||
|
* Returns: The array address.
|
||||||
|
*/
|
||||||
|
double *
|
||||||
|
vips_array_double_get( const GValue *value, int *n )
|
||||||
|
{
|
||||||
|
double *array;
|
||||||
|
size_t &length;
|
||||||
|
|
||||||
|
array = vips_array_get( value, &length, NULL, NULL );
|
||||||
|
|
||||||
|
if( n )
|
||||||
|
*n = length / sizeof( double );
|
||||||
|
|
||||||
|
return( array );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vips_array_double_set:
|
||||||
|
* @value: #GValue to get from
|
||||||
|
* @array: array of doubles
|
||||||
|
* @n: the number of elements
|
||||||
|
*
|
||||||
|
* Set @value to hold a copy of @array. Pass in the array length in @n.
|
||||||
|
*
|
||||||
|
* See also: vips_array_double_get().
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, -1 otherwise.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vips_array_double_set( const GValue *value, double *array, int n )
|
||||||
|
{
|
||||||
|
double *array_copy;
|
||||||
|
|
||||||
|
vips_array_set( value,
|
||||||
|
G_TYPE_DOUBLE, sizeof( double ), n * sizeof( double ) );
|
||||||
|
array_copy = vips_array_double_get( value, NULL );
|
||||||
|
memcpy( array_copy, array, n * sizeof( double ) );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vips_image_set_blob:
|
* vips_image_set_blob:
|
||||||
|
Loading…
Reference in New Issue
Block a user