vips array types are more binding-friendly

this all works now:

```python
from gi.repository import Vips

a = Vips.ArrayDouble.new([1,2,3])
a.get()

a = Vips.ArrayInt.new([1,2,3])
a.get()

a = Vips.ArrayImage.new([c, d, e])
a.get()
```
This commit is contained in:
John Cupitt 2014-08-31 10:41:53 +01:00
parent 42dac9209a
commit a370e5003e
16 changed files with 279 additions and 146 deletions

View File

@ -3,6 +3,7 @@
- fix pngload with libpng >1.6.1
- add vips_resize()
- return of vips_init(), but just for bindings
- revised type.c to make it more binding-friendly
21/8/14 started 7.40.7
- width and height were swapped in matlab load

42
TODO
View File

@ -2,24 +2,50 @@
- add more constructors
- could import like this:
from gi.repository import Vips
import vips_additions
ie. make it a module, not a package, and make it clear that it
modifies Vips rather than adding anything itself
- need the filename splitter
- need more writers
- need GBoxed
- GBoxed
seems to be almost there!
can we write generic array index?
we have:
vips_area_index_array( VipsArea *area, int i, GValue *value )
a = Vips.array_double_new([1,2,3])
ie. get element i from array out as a GValue? do we need a
switch for all possible types?
but no VipsArrayDouble type, strangely
from gi.repository import GLib
from gi.repository import GObject
VipsThing is there? odd
seems be have spotted that it's just an alias for VipsArea and
elided the type
gint_type = GObject.GType.from_name('gint')
a = GObject.Value(gint_type)
a.set_value(12)
a.get_value()
12
a.unset()
>>> a
<Value (invalid) None>
a.init(gint_type)
a = GObject.Value(None)
>>> a
<Value (invalid) None>
b = Vips.ArrayDouble.new([1,2,3])
b.area.index_array(1)
segv
- can we pick the vipsthumbnail int shrink factor more intelligently?

View File

@ -57,6 +57,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <vips/vips.h>
@ -192,8 +193,8 @@ vips_getpoint( VipsImage *in, double **vector, int *n, int x, int y, ... )
{
va_list ap;
VipsArrayDouble *out_array;
VipsArea *area;
int result;
int i;
va_start( ap, y );
result = vips_call_split( "getpoint", ap, in, &out_array, x, y );
@ -202,13 +203,14 @@ vips_getpoint( VipsImage *in, double **vector, int *n, int x, int y, ... )
if( !result )
return( -1 );
if( !(*vector = VIPS_ARRAY( NULL, out_array->n, double )) ) {
vips_area_unref( (VipsArea *) out_array );
area = VIPS_AREA( out_array );
*vector = VIPS_ARRAY( NULL, area->n, double );
if( !*vector ) {
vips_area_unref( area );
return( -1 );
}
for( i = 0; i < out_array->n; i++ )
(*vector)[i] = ((double *) out_array->data)[i];
*n = out_array->n;
memcpy( *vector, area->data, area->n * area->sizeof_type );
*n = area->n;
return( 0 );
}

View File

@ -130,8 +130,8 @@ vips_bandjoin_build( VipsObject *object )
VipsBandjoin *bandjoin = (VipsBandjoin *) object;
if( bandjoin->in ) {
bandary->in = bandjoin->in->data;
bandary->n = bandjoin->in->n;
bandary->in = VIPS_AREA( bandjoin->in )->data;
bandary->n = VIPS_AREA( bandjoin->in )->n;
if( bandary->n == 1 )
return( vips_bandary_copy( bandary ) );

View File

@ -422,7 +422,8 @@ vips_insert_build( VipsObject *object )
if( !(insert->ink = vips__vector_to_ink(
class->nickname, conversion->out,
insert->background->data, NULL, insert->background->n )) )
(double *) VIPS_ARRAY_ADDR( insert->background, 0 ), NULL,
VIPS_AREA( insert->background )->n )) )
return( -1 );
if( vips_image_generate( conversion->out,
@ -503,9 +504,7 @@ vips_insert_init( VipsInsert *insert )
{
/* Init our instance fields.
*/
insert->background =
vips_area_new_array( G_TYPE_DOUBLE, sizeof( double ), 1 );
((double *) (insert->background->data))[0] = 0.0;
insert->background = vips_array_double_newv( 1, 0.0 );
}
/**

View File

@ -3963,19 +3963,13 @@ im_maxpos_vec( VipsImage *im, int *xpos, int *ypos, double *maxima, int n )
NULL ) )
return( -1 );
memcpy( xpos,
vips_area_get_data( x_array, NULL, NULL, NULL, NULL ),
n * sizeof( int ) );
memcpy( ypos,
vips_area_get_data( y_array, NULL, NULL, NULL, NULL ),
n * sizeof( int ) );
memcpy( maxima,
vips_area_get_data( out_array, NULL, NULL, NULL, NULL ),
n * sizeof( double ) );
memcpy( xpos, VIPS_ARRAY_ADDR( x_array, 0 ), n * sizeof( int ) );
memcpy( ypos, VIPS_ARRAY_ADDR( y_array, 0 ), n * sizeof( int ) );
memcpy( maxima, VIPS_ARRAY_ADDR( out_array, 0 ), n * sizeof( double ) );
vips_area_unref( (VipsArea *) out_array );
vips_area_unref( (VipsArea *) x_array );
vips_area_unref( (VipsArea *) y_array );
vips_area_unref( VIPS_AREA( out_array ) );
vips_area_unref( VIPS_AREA( x_array ) );
vips_area_unref( VIPS_AREA( y_array ) );
return( 0 );
}
@ -3996,19 +3990,13 @@ im_minpos_vec( VipsImage *im, int *xpos, int *ypos, double *minima, int n )
NULL ) )
return( -1 );
memcpy( xpos,
vips_area_get_data( x_array, NULL, NULL, NULL, NULL ),
n * sizeof( int ) );
memcpy( ypos,
vips_area_get_data( y_array, NULL, NULL, NULL, NULL ),
n * sizeof( int ) );
memcpy( minima,
vips_area_get_data( out_array, NULL, NULL, NULL, NULL ),
n * sizeof( double ) );
memcpy( xpos, VIPS_ARRAY_ADDR( x_array, 0 ), n * sizeof( int ) );
memcpy( ypos, VIPS_ARRAY_ADDR( y_array, 0 ), n * sizeof( int ) );
memcpy( minima, VIPS_ARRAY_ADDR( out_array, 0 ), n * sizeof( double ) );
vips_area_unref( (VipsArea *) out_array );
vips_area_unref( (VipsArea *) x_array );
vips_area_unref( (VipsArea *) y_array );
vips_area_unref( VIPS_AREA( out_array ) );
vips_area_unref( VIPS_AREA( x_array ) );
vips_area_unref( VIPS_AREA( y_array ) );
return( 0 );
}

View File

@ -519,7 +519,8 @@ vips_draw_flood_build( VipsObject *object )
*/
if( !(flood.edge = vips__vector_to_ink( class->nickname,
flood.test,
drawink->ink->data, NULL, drawink->ink->n )) )
VIPS_ARRAY_ADDR( drawink->ink, 0 ), NULL,
VIPS_AREA( drawink->ink )->n )) )
return( -1 );
flood_all( &flood, drawflood->x, drawflood->y );

View File

@ -87,6 +87,7 @@ vips_draw_rect_build( VipsObject *object )
{
VipsDraw *draw = VIPS_DRAW( object );
VipsDrawink *drawink = VIPS_DRAWINK( object );
VipsArea *ink = VIPS_AREA( drawink->ink );
VipsDrawRect *draw_rect = (VipsDrawRect *) object;
int left = draw_rect->left;
int top = draw_rect->top;
@ -106,16 +107,16 @@ vips_draw_rect_build( VipsObject *object )
width > 2 &&
height > 2 )
return( vips_draw_rect( draw->image,
drawink->ink->data, drawink->ink->n,
ink->data, ink->n,
left, top, width, 1, NULL ) ||
vips_draw_rect( draw->image,
drawink->ink->data, drawink->ink->n,
ink->data, ink->n,
left + width - 1, top, 1, height, NULL ) ||
vips_draw_rect( draw->image,
drawink->ink->data, drawink->ink->n,
ink->data, ink->n,
left, top + height - 1, width, 1, NULL ) ||
vips_draw_rect( draw->image,
drawink->ink->data, drawink->ink->n,
ink->data, ink->n,
left, top, 1, height, NULL ) );
image.left = 0;

View File

@ -66,7 +66,8 @@ vips_drawink_build( VipsObject *object )
if( drawink->ink &&
!(drawink->pixel_ink = vips__vector_to_ink( class->nickname,
draw->image,
drawink->ink->data, NULL, drawink->ink->n )) )
VIPS_ARRAY_ADDR( drawink->ink, 0 ), NULL,
VIPS_AREA( drawink->ink )->n )) )
return( -1 );
return( 0 );
@ -97,9 +98,7 @@ vips_drawink_class_init( VipsDrawinkClass *class )
static void
vips_drawink_init( VipsDrawink *drawink )
{
drawink->ink =
vips_area_new_array( G_TYPE_DOUBLE, sizeof( double ), 1 );
((double *) (drawink->ink->data))[0] = 0;
drawink->ink = vips_array_double_newv( 1, 0.0 );
}
/* Fill a scanline between points x1 and x2 inclusive. x1 < x2.

View File

@ -1588,7 +1588,7 @@ vips_foreign_save_dz_build( VipsObject *object )
background = vips_array_double_newv( 1, 255.0 );
g_object_set( object, "background", background, NULL );
vips_area_unref( background );
vips_area_unref( VIPS_AREA( background ) );
}
if( dz->overlap >= dz->tile_size ) {

View File

@ -461,6 +461,8 @@ int vips_system( const char *cmd_format, ... )
/* Defined in type.c, but declared here since they use VipsImage.
*/
VipsArrayImage *vips_array_image_new( const VipsImage **array, int n );
VipsImage **vips_array_image_get( VipsArrayImage *array, int *n );
VipsImage **vips_value_get_array_image( const GValue *value, int *n );
int vips_value_set_array_image( GValue *value, VipsImage **array, int n );

View File

@ -52,7 +52,6 @@ typedef struct _VipsThing {
#define VIPS_TYPE_THING (vips_thing_get_type())
GType vips_thing_get_type( void );
VipsThing *vips_thing_new( int i );
int vips_thing_get_i( VipsThing *thing );
/* A ref-counted area of memory. Can hold arrays of things as well.
*/
@ -97,16 +96,31 @@ VipsArea *vips_area_new_blob( VipsCallbackFn free_fn,
void *data, size_t length );
VipsArea *vips_area_new_array( GType type, size_t sizeof_type, int n );
VipsArea *vips_area_new_array_object( int n );
void *vips_area_get_data( VipsArea *area,
size_t *length, int *n, GType *type, size_t *sizeof_type );
#ifdef VIPS_DEBUG
#define VIPS_ARRAY_ADDR( X, I ) \
(((I) >= 0 && (I) < VIPS_AREA( X )->n) ? \
(VIPS_AREA( X )->data + VIPS_AREA( X )->sizeof_type * (I)) : \
(fprintf( stderr, \
"VIPS_ARRAY_ADDR: index out of bounds, " \
"file \"%s\", line %d\n" \
"(index %d should have been within [0,%d])\n", \
__FILE__, __LINE__, \
(I), VIPS_AREA( X )->n ), NULL ))
#else /*!VIPS_DEBUG*/
#define VIPS_ARRAY_ADDR( X, I ) \
(VIPS_AREA( X )->data + VIPS_AREA( X )->sizeof_type * (I))
#endif /*VIPS_DEBUG*/
/**
* VIPS_TYPE_AREA:
*
* The #GType for a #VipsArea.
*/
#define VIPS_TYPE_AREA (vips_area_get_type())
#define VIPS_AREA( X ) ((VipsArea *) (X))
GType vips_area_get_type( void );
/**
@ -139,9 +153,14 @@ GType vips_blob_get_type( void );
* The #GType for a #VipsArrayDouble.
*/
#define VIPS_TYPE_ARRAY_DOUBLE (vips_array_double_get_type())
typedef VipsArea VipsArrayDouble;
typedef struct _VipsArrayDouble {
VipsArea area;
} VipsArrayDouble;
VipsArrayDouble *vips_array_double_new( const double *array, int n );
VipsArrayDouble *vips_array_double_newv( int n, ... );
double *vips_array_double_get( VipsArrayDouble *array, int *n );
GType vips_array_double_get_type( void );
/**
@ -150,9 +169,14 @@ GType vips_array_double_get_type( void );
* The #GType for a #VipsArrayInt.
*/
#define VIPS_TYPE_ARRAY_INT (vips_array_int_get_type())
typedef VipsArea VipsArrayInt;
typedef struct _VipsArrayInt {
VipsArea area;
} VipsArrayInt;
VipsArrayInt *vips_array_int_new( const int *array, int n );
VipsArrayInt *vips_array_int_newv( int n, ... );
int *vips_array_int_get( VipsArrayInt *array, int *n );
GType vips_array_int_get_type( void );
/**
@ -161,7 +185,11 @@ GType vips_array_int_get_type( void );
* The #GType for a #VipsArrayImage.
*/
#define VIPS_TYPE_ARRAY_IMAGE (vips_array_image_get_type())
typedef VipsArea VipsArrayImage;
typedef struct _VipsArrayImage {
VipsArea area;
} VipsArrayImage;
GType vips_array_image_get_type( void );
void vips_value_set_area( GValue *value, VipsCallbackFn free_fn, void *data );
@ -193,8 +221,9 @@ int vips_value_set_array_int( GValue *value, const int *array, int n );
GObject **vips_value_get_array_object( const GValue *value, int *n );
int vips_value_set_array_object( GValue *value, int n );
/* See also image.h, that has vips_value_get_array_image() and
* vips_value_set_array_image(). They need to be declared after VipsImage.
/* See also image.h, that has vips_array_image_get(), vips_array_image_new(),
* vips_value_get_array_image() and vips_value_set_array_image(). They need
* to be declared after VipsImage.
*/
#ifdef __cplusplus

View File

@ -97,7 +97,7 @@ vips_system_dispose( GObject *gobject )
if( system->in_name ) {
int i;
for( i = 0; i < system->in->n; i++ ) {
for( i = 0; i < VIPS_AREA( system->in )->n; i++ ) {
g_unlink( system->in_name[i] );
VIPS_FREE( system->in_name[i] );
}
@ -134,13 +134,13 @@ vips_system_build( VipsObject *object )
if( system->in ) {
char *in_format = system->in_format ?
system->in_format : "%s.tif";
VipsImage **in = (VipsImage **) system->in->data;
int n;
VipsImage **in = vips_array_image_get( system->in, &n );
if( !(system->in_name = VIPS_ARRAY( object,
system->in->n, char * )) )
if( !(system->in_name = VIPS_ARRAY( object, n, char * )) )
return( -1 );
memset( system->in_name, 0, system->in->n * sizeof( char * ) );
for( i = 0; i < system->in->n; i++ ) {
memset( system->in_name, 0, n * sizeof( char * ) );
for( i = 0; i < n; i++ ) {
if( !(system->in_name[i] =
vips__temp_name( in_format )) )
return( -1 );
@ -158,7 +158,7 @@ vips_system_build( VipsObject *object )
vips_strncpy( cmd, system->cmd_format, VIPS_PATH_MAX );
if( system->in )
for( i = 0; i < system->in->n; i++ )
for( i = 0; i < VIPS_AREA( system->in )->n; i++ )
if( vips__substitute( class->nickname,
cmd, VIPS_PATH_MAX, system->in_name[i] ) )
return( -1 );

View File

@ -66,6 +66,16 @@
*/
/* A very simple boxed type for testing. Just an int.
*
* You can manipulate this thing from Python (for example) with:
*
* from gi.repository import Vips
* a = Vips.Thing.new(12)
* print a.i
* b = a
* del a
* print b.i
* del b
*/
/**
@ -107,14 +117,6 @@ vips_thing_free( VipsThing *thing )
g_free( thing );
}
int
vips_thing_get_i( VipsThing *thing )
{
printf( "vips_thing_get_i: %d %p\n", thing->i, thing );
return( thing->i );
}
/*
* glib-2.26+ only
@ -599,6 +601,84 @@ vips_blob_get_type( void )
return( type );
}
/**
* vips_array_int_new:
* @array: (array length=n): array of int
* @n: number of ints
*
* Allocate a new array of ints and copy @array into it. Free with
* vips_area_unref().
*
* See also: #VipsArea.
*
* Returns: (transfer full): A new #VipsArrayInt.
*/
VipsArrayInt *
vips_array_int_new( const int *array, int n )
{
VipsArea *area;
int *array_copy;
area = vips_area_new_array( G_TYPE_INT, sizeof( int ), n );
array_copy = vips_area_get_data( area, NULL, NULL, NULL, NULL );
memcpy( array_copy, array, n * sizeof( int ) );
return( (VipsArrayInt *) area );
}
/**
* vips_array_int_newv:
* @n: number of ints
* @...: list of int arguments
*
* Allocate a new array of @n ints and copy @... into it. Free with
* vips_area_unref().
*
* See also: vips_array_int_new()
*
* Returns: (transfer full): A new #VipsArrayInt.
*/
VipsArrayInt *
vips_array_int_newv( int n, ... )
{
va_list ap;
VipsArea *area;
int *array;
int i;
area = vips_area_new_array( G_TYPE_INT, sizeof( int ), n );
array = vips_area_get_data( area, NULL, NULL, NULL, NULL );
va_start( ap, n );
for( i = 0; i < n; i++ )
array[i] = va_arg( ap, int );
va_end( ap );
return( (VipsArrayInt *) area );
}
/**
* vips_array_int_get:
* @array: the #VipsArrayInt to fetch from
* @n: length of array
*
* Fetch an int array from a #VipsArrayInt. Useful for language bindings.
*
* Returns: (array length=n): (transfer none): array of int
*/
int *
vips_array_int_get( VipsArrayInt *array, int *n )
{
VipsArea *area = VIPS_AREA( array );
g_assert( area->type == G_TYPE_INT );
if( n )
*n = area->n;
return( (int *) VIPS_ARRAY_ADDR( array, 0 ) );
}
static void
transform_array_int_g_string( const GValue *src_value, GValue *dest_value )
{
@ -710,15 +790,7 @@ vips_array_double_new( const double *array, int n )
array_copy = vips_area_get_data( area, NULL, NULL, NULL, NULL );
memcpy( array_copy, array, n * sizeof( double ) );
{
int i;
printf( "vips_array_double_new: %p\n", area );
for( i = 0; i < n; i++ )
printf( "\t%d) %g\n", i, array[i] );
}
return( area );
return( (VipsArrayDouble *) area );
}
/**
@ -749,7 +821,29 @@ vips_array_double_newv( int n, ... )
array[i] = va_arg( ap, double );
va_end( ap );
return( area );
return( (VipsArrayDouble *) area );
}
/**
* vips_array_double_get:
* @array: the #VipsArrayDouble to fetch from
* @n: length of array
*
* Fetch a double array from a #VipsArrayDouble. Useful for language bindings.
*
* Returns: (array length=n): (transfer none): array of double
*/
double *
vips_array_double_get( VipsArrayDouble *array, int *n )
{
VipsArea *area = VIPS_AREA( array );
g_assert( area->type == G_TYPE_DOUBLE );
if( n )
*n = area->n;
return( VIPS_ARRAY_ADDR( array, 0 ) );
}
static void
@ -879,6 +973,53 @@ transform_g_string_array_image( const GValue *src_value, GValue *dest_value )
g_free( str );
}
/**
* vips_array_image_new:
* @array: (array length=n): array of #VipsImage
* @n: number of images
*
* Allocate a new array of images and copy @array into it. Free with
* vips_area_unref().
*
* See also: #VipsArea.
*
* Returns: (transfer full): A new #VipsArrayImage.
*/
VipsArrayImage *
vips_array_image_new( const VipsImage **array, int n )
{
VipsArea *area;
VipsImage *array_copy;
area = vips_area_new_array( G_TYPE_DOUBLE, sizeof( double ), n );
array_copy = vips_area_get_data( area, NULL, NULL, NULL, NULL );
memcpy( array_copy, array, n * sizeof( double ) );
return( (VipsArrayImage *) area );
}
/**
* vips_array_image_get:
* @array: the #VipsArrayImage to fetch from
* @n: length of array
*
* Fetch an image array from a #VipsArrayImage. Useful for language bindings.
*
* Returns: (array length=n): (transfer none): array of #VipsImage
*/
VipsImage **
vips_array_image_get( VipsArrayImage *array, int *n )
{
VipsArea *area = VIPS_AREA( array );
g_assert( area->type == VIPS_TYPE_IMAGE );
if( n )
*n = area->n;
return( (VipsImage **) VIPS_ARRAY_ADDR( array, 0 ) );
}
GType
vips_array_image_get_type( void )
{
@ -1144,62 +1285,6 @@ vips_value_get_array( const GValue *value,
return( area->data );
}
/**
* vips_array_int_new:
* @array: (array length=n): array of int
* @n: number of ints
*
* Allocate a new array of ints and copy @array into it. Free with
* vips_area_unref().
*
* See also: #VipsArea.
*
* Returns: (transfer full): A new #VipsArrayInt.
*/
VipsArrayInt *
vips_array_int_new( const int *array, int n )
{
VipsArea *area;
int *array_copy;
area = vips_area_new_array( G_TYPE_INT, sizeof( int ), n );
array_copy = vips_area_get_data( area, NULL, NULL, NULL, NULL );
memcpy( array_copy, array, n * sizeof( int ) );
return( area );
}
/**
* vips_array_int_newv:
* @n: number of ints
* @...: list of int arguments
*
* Allocate a new array of @n ints and copy @... into it. Free with
* vips_area_unref().
*
* See also: vips_array_int_new()
*
* Returns: (transfer full): A new #VipsArrayInt.
*/
VipsArrayInt *
vips_array_int_newv( int n, ... )
{
va_list ap;
VipsArea *area;
int *array;
int i;
area = vips_area_new_array( G_TYPE_INT, sizeof( int ), n );
array = vips_area_get_data( area, NULL, NULL, NULL, NULL );
va_start( ap, n );
for( i = 0; i < n; i++ )
array[i] = va_arg( ap, int );
va_end( ap );
return( area );
}
/**
* vips_value_get_array_int:
* @value: %GValue to get from

View File

@ -173,10 +173,10 @@ vips_match_build( VipsObject *object )
"ody", dy,
"oarea", oarea,
NULL ) ) {
vips_area_unref( oarea );
vips_area_unref( VIPS_AREA( oarea ) );
return( -1 );
}
vips_area_unref( oarea );
vips_area_unref( VIPS_AREA( oarea ) );
if( vips_image_write( x, match->out ) ) {
g_object_unref( x );

View File

@ -27,8 +27,8 @@ out = a.add(b)
print 'out =', out
ones = Vips.array_double_new([1])
twos = Vips.array_double_new([2])
ones = Vips.ArrayDouble.new([1])
twos = Vips.ArrayDouble.new([2])
out = out.linear(ones, twos)