From 2c4cbedc704393504c4d075940afd4ed55d1b6fd Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sat, 22 Oct 2011 13:10:47 +0100 Subject: [PATCH] insert.c compiles and we have VipsArea as a public struct for array arguments --- ChangeLog | 5 +- TODO | 9 ---- libvips/conversion/Makefile.am | 1 + libvips/conversion/conversion.c | 2 + libvips/conversion/insert.c | 54 +++++++++---------- libvips/include/vips/header.h | 43 ++++++++++++--- libvips/include/vips/internal.h | 16 ++++++ libvips/include/vips/object.h | 2 +- libvips/iofuncs/header.c | 95 ++++++++++++--------------------- libvips/iofuncs/region.c | 4 +- 10 files changed, 121 insertions(+), 110 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2b6ed744..5224f5ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,8 @@ 20/8/11 started 7.27.0 - version bump for new dev cycle - im_subtract(), im_avg(), im_min(), im_minpos(), im_copy(), im_embed(), - im_flophor(), im_flipver() redone as classes + im_flophor(), im_flipver(), im_insert(), im_insert_noexpand() redone as + classes - added VIPS_ARGUMENT_APPEND to help control arg ordering - generate has a 'stop' param to signal successful early termination - added optional output args, eg. x/y for min @@ -22,6 +23,8 @@ - more VipsImage props - added vips_image_write(), old one becomes vips_image_write_to_file() - added vips_region_paint_pel() +- added VipsArea as a public struct +- added array members and arguments 12/10/11 started 7.26.6 - NOCACHE was not being set correctly on OS X causing performance diff --git a/TODO b/TODO index 8f74fc5f..228b523f 100644 --- a/TODO +++ b/TODO @@ -1,12 +1,3 @@ -- what should the member of VipsInsert be? what does get_member do for boxed? - just the pointer I guess - - does that mean VipsInsert sees an Area? - - yes, vips_object_set_property() writes g_value_dup_boxed() to the member - - argh do we have to expose Area now? - diff --git a/libvips/conversion/Makefile.am b/libvips/conversion/Makefile.am index 98a64c92..e9d4bada 100644 --- a/libvips/conversion/Makefile.am +++ b/libvips/conversion/Makefile.am @@ -6,6 +6,7 @@ libconversion_la_SOURCES = \ copy.c \ embed.c \ flip.c \ + insert.c \ conver_dispatch.c \ im_black.c \ im_c2amph.c \ diff --git a/libvips/conversion/conversion.c b/libvips/conversion/conversion.c index bac817ec..8f509354 100644 --- a/libvips/conversion/conversion.c +++ b/libvips/conversion/conversion.c @@ -105,9 +105,11 @@ vips_conversion_operation_init( void ) extern GType vips_copy_get_type( void ); extern GType vips_embed_get_type( void ); extern GType vips_flip_get_type( void ); + extern GType vips_insert_get_type( void ); vips_copy_get_type(); vips_embed_get_type(); vips_flip_get_type(); + vips_insert_get_type(); } diff --git a/libvips/conversion/insert.c b/libvips/conversion/insert.c index 0727ba3c..317d4a83 100644 --- a/libvips/conversion/insert.c +++ b/libvips/conversion/insert.c @@ -120,7 +120,7 @@ typedef struct _VipsInsert { int x; int y; gboolean expand; - GArray *background; + VipsArea *background; /* Pixel we paint calculated from background. */ @@ -147,7 +147,7 @@ G_DEFINE_TYPE( VipsInsert, vips_insert, VIPS_TYPE_CONVERSION ); static int vips_insert_just_one( VipsRegion *or, VipsRegion *ir, int x, int y ) { - VIpsRect need; + VipsRect need; /* Find the part of pos we need. */ @@ -204,43 +204,38 @@ vips_insert_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) Rect ovl; - /* Ask for input we need. - */ - if( vips_region_prepare( ir, r ) ) - return( -1 ); - /* Does the rect we have been asked for fall entirely inside the * sub-image? */ - if( vips_rect_includesrect( &ins->rsub, &or->valid ) ) + if( vips_rect_includesrect( &insert->rsub, &or->valid ) ) return( vips_insert_just_one( or, ir[1], - ins->rsub.left, ins->rsub.top ) ); + insert->rsub.left, insert->rsub.top ) ); /* Does it fall entirely inside the main, and not at all inside the * sub? */ - vips_rect_intersectrect( &or->valid, &ins->rsub, &ovl ); - if( vips_rect_includesrect( &ins->rmain, &or->valid ) && + vips_rect_intersectrect( &or->valid, &insert->rsub, &ovl ); + if( vips_rect_includesrect( &insert->rmain, &or->valid ) && vips_rect_isempty( &ovl ) ) return( vips_insert_just_one( or, ir[0], - ins->rmain.left, ins->rmain.top ) ); + insert->rmain.left, insert->rmain.top ) ); /* Output requires both (or neither) input. If it is not entirely * inside both the main and the sub, then there is going to be some * background. */ - if( !(vips_rect_includesrect( &ins->rsub, &or->valid ) && - vips_rect_includesrect( &ins->rmain, &or->valid )) ) + if( !(vips_rect_includesrect( &insert->rsub, &or->valid ) && + vips_rect_includesrect( &insert->rmain, &or->valid )) ) vips_region_paint_pel( or, r, insert->ink ); /* Paste from main. */ - if( vips_insert_paste_region( or, ir[0], &ins->rmain ) ) + if( vips_insert_paste_region( or, ir[0], &insert->rmain ) ) return( -1 ); /* Paste from sub. */ - if( vips_insert_paste_region( or, ir[1], &ins->rsub ) ) + if( vips_insert_paste_region( or, ir[1], &insert->rsub ) ) return( -1 ); return( 0 ); @@ -250,7 +245,7 @@ vips_insert_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) * valid. */ PEL * -vips__vector_to_ink( const char *domain, VipsImage *im, int n, double *vec ) +vips__vector_to_ink( const char *domain, VipsImage *im, double *vec, int n ) { VipsImage *t[3]; double *zeros; @@ -258,7 +253,7 @@ vips__vector_to_ink( const char *domain, VipsImage *im, int n, double *vec ) if( vips_check_vector( domain, n, im ) ) return( NULL ); - if( vips_open_local_array( im, t, 3, domain, "t" ) || + if( vips_image_new_array( VIPS_OBJECT( im ), t, 3 ) || !(zeros = VIPS_ARRAY( im, n, double )) ) return( NULL ); for( i = 0; i < n; i++ ) @@ -285,7 +280,6 @@ vips_insert_build( VipsObject *object ) VipsImage *t[4]; VipsImage **arry; - int i; /* Check args. */ @@ -301,9 +295,11 @@ vips_insert_build( VipsObject *object ) if( vips_image_pio_input( insert->main ) || vips_image_pio_input( insert->sub ) || vips_image_pio_output( conversion->output ) || - vips_check_bands_1orn( domain, in1, in2 ) || - vips_check_coding_known( domain, in1 ) || - vips_check_coding_same( domain, in1, in2 ) ) + vips_check_bands_1orn( "VipsInsert", + insert->main, insert->sub ) || + vips_check_coding_known( "VipsInsert", insert->main ) || + vips_check_coding_same( "VipsInsert", + insert->main, insert->sub ) ) return( -1 ); if( vips_image_new_array( object, t, 4 ) ) @@ -312,7 +308,7 @@ vips_insert_build( VipsObject *object ) /* Cast our input images up to a common format and bands. */ if( vips__formatalike( insert->main, insert->sub, t[0], t[1] ) || - vips__bandalike( domain, t[0], t[1], t[2], t[3] ) ) + vips__bandalike( "VipsInsert", t[0], t[1], t[2], t[3] ) ) return( -1 ); insert->main_processed = t[2]; insert->sub_processed = t[3]; @@ -322,7 +318,7 @@ vips_insert_build( VipsObject *object ) if( vips_image_copy_fields_array( conversion->output, arry ) ) return( -1 ); - vips_demand_hint_array( arithmetic->output, + vips_demand_hint_array( conversion->output, VIPS_DEMAND_STYLE_SMALLTILE, arry ); /* Calculate geometry. @@ -331,8 +327,8 @@ vips_insert_build( VipsObject *object ) insert->rmain.top = 0; insert->rmain.width = insert->main_processed->Xsize; insert->rmain.height = insert->main_processed->Ysize; - insert->rsub.left = x; - insert->rsub.top = y; + insert->rsub.left = insert->x; + insert->rsub.top = insert->y; insert->rsub.width = insert->sub_processed->Xsize; insert->rsub.height = insert->sub_processed->Ysize; @@ -352,14 +348,14 @@ vips_insert_build( VipsObject *object ) insert->rout.top = 0; } else - ins->rout = ins->rmain; + insert->rout = insert->rmain; conversion->output->Xsize = insert->rout.width; conversion->output->Ysize = insert->rout.height; if( !(insert->ink = vips__vector_to_ink( "VipsInsert", conversion->output, - insert->background, insert->n )) ) + insert->background->data, insert->background->n )) ) return( -1 ); if( vips_image_generate( conversion->output, @@ -440,7 +436,7 @@ vips_insert( VipsImage *main, VipsImage *sub, VipsImage **out, va_list ap; int result; - va_start( ap, out ); + va_start( ap, y ); result = vips_call_split( "insert", ap, main, sub, out, x, y ); va_end( ap ); diff --git a/libvips/include/vips/header.h b/libvips/include/vips/header.h index e6e3c825..e827ff60 100644 --- a/libvips/include/vips/header.h +++ b/libvips/include/vips/header.h @@ -77,6 +77,41 @@ extern "C" { */ #define VIPS_META_RESOLUTION_UNIT "resolution-unit" +/* Also used for eg. vips_local() and friends. + */ +typedef int (*VipsCallbackFn)( void *a, void *b ); + +/* A ref-counted area of memory. + */ +typedef struct _VipsArea { + void *data; + size_t length; /* 0 if not known */ + + /* If this area represents an array, the number of elements in the + * array. Equal to length / sizeof(element). + */ + int n; + + /*< private >*/ + + /* Reference count. + */ + int count; + + /* Things like ICC profiles need their own free functions. + */ + VipsCallbackFn free_fn; + + /* If we are holding an array (for exmaple, an array of double), the + * GType of the elements and their size. 0 for not known. + * + * n is always length / sizeof_type, we keep it as a member for + * convenience. + */ + GType type; + size_t sizeof_type; +} VipsArea; + int vips_format_sizeof( VipsBandFormat format ); int vips_image_get_width( const VipsImage *image ); @@ -150,10 +185,6 @@ size_t vips_ref_string_get_length( const GValue *value ); * The #GType for an #vips_blob. */ -/* Also used for eg. vips_local() and friends. - */ -typedef int (*VipsCallbackFn)( void *a, void *b ); - #define VIPS_TYPE_BLOB (vips_blob_get_type()) GType vips_blob_get_type( void ); void *vips_blob_get( const GValue *value, size_t *length ); @@ -168,8 +199,8 @@ int vips_blob_set( GValue *value, VipsCallbackFn free_fn, #define VIPS_TYPE_ARRAY_DOUBLE (vips_array_double_get_type()) GType vips_array_double_get_type( void ); -double *vips_array_double_get( const GValue *value, int *length ); -int vips_array_double_set( GValue *value, double *array, int length ); +double *vips_array_double_get( const GValue *value, int *n ); +int vips_array_double_set( GValue *value, const double *array, int n ); void vips_image_set_area( VipsImage *image, const char *field, VipsCallbackFn free_fn, void *data ); diff --git a/libvips/include/vips/internal.h b/libvips/include/vips/internal.h index dc8323bc..509e21e4 100644 --- a/libvips/include/vips/internal.h +++ b/libvips/include/vips/internal.h @@ -115,6 +115,22 @@ int vips__write_header_bytes( VipsImage *im, unsigned char *to ); extern GMutex *vips__global_lock; + +int vips__formatalike_vec( VipsImage **in, VipsImage **out, int n ); +int vips__formatalike( VipsImage *in1, VipsImage *in2, + VipsImage *out1, VipsImage *out2 ); +int vips__sizealike_vec( VipsImage **in, VipsImage **out, int n ); +int vips__sizealike( VipsImage *in1, VipsImage *in2, + VipsImage *out1, VipsImage *out2 ); +int vips__bandup( const char *domain, VipsImage *in, VipsImage *out, int n ); +int vips__bandalike_vec( const char *domain, + VipsImage **in, VipsImage **out, int n ); +int vips__bandalike( const char *domain, + VipsImage *in1, VipsImage *in2, VipsImage *out1, VipsImage *out2 ); + + + + void im__format_init( void ); void im__tiff_register( void ); diff --git a/libvips/include/vips/object.h b/libvips/include/vips/object.h index f1eb875f..7ca27993 100644 --- a/libvips/include/vips/object.h +++ b/libvips/include/vips/object.h @@ -147,7 +147,7 @@ extern int _vips__argument_id; } #define VIPS_ARG_BOXED( CLASS, NAME, PRIORITY, LONG, DESC, \ - FLAGS, OFFSET, TYPE ) \ + FLAGS, OFFSET, TYPE ) { \ GParamSpec *pspec; \ \ pspec = g_param_spec_boxed( (NAME), (LONG), (DESC), \ diff --git a/libvips/iofuncs/header.c b/libvips/iofuncs/header.c index acac38c6..38339db6 100644 --- a/libvips/iofuncs/header.c +++ b/libvips/iofuncs/header.c @@ -1014,24 +1014,6 @@ transform_save_string_double( const GValue *src_value, GValue *dest_value ) g_ascii_strtod( vips_save_string_get( src_value ), NULL ) ); } -/* A GType for a ref-counted area of memory. - */ -typedef struct _Area { - int count; - - size_t length; /* 0 if not known */ - void *data; - - 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; - #ifdef DEBUG static int area_number = 0; #endif /*DEBUG*/ @@ -1039,12 +1021,12 @@ static int area_number = 0; /* An area of mem with a free func. (eg. \0-terminated string, or a struct). * Inital count == 1, so _unref() after attaching somewhere. */ -static Area * +static VipsArea * area_new( VipsCallbackFn free_fn, void *data ) { - Area *area; + VipsArea *area; - if( !(area = VIPS_NEW( NULL, Area )) ) + if( !(area = VIPS_NEW( NULL, VipsArea )) ) return( NULL ); area->count = 1; area->length = 0; @@ -1065,10 +1047,10 @@ area_new( VipsCallbackFn free_fn, void *data ) /* An area of mem with a free func and a length (some sort of binary object, * like an ICC profile). */ -static Area * +static VipsArea * area_new_blob( VipsCallbackFn free_fn, void *blob, size_t blob_length ) { - Area *area; + VipsArea *area; if( !(area = area_new( free_fn, blob )) ) return( NULL ); @@ -1077,8 +1059,8 @@ area_new_blob( VipsCallbackFn free_fn, void *blob, size_t blob_length ) return( area ); } -static Area * -area_copy( Area *area ) +static VipsArea * +area_copy( VipsArea *area ) { g_assert( area->count >= 0 ); @@ -1092,7 +1074,7 @@ area_copy( Area *area ) } static void -area_unref( Area *area ) +area_unref( VipsArea *area ) { g_assert( area->count > 0 ); @@ -1119,7 +1101,7 @@ area_unref( Area *area ) static void transform_area_g_string( const GValue *src_value, GValue *dest_value ) { - Area *area; + VipsArea *area; char buf[256]; area = g_value_get_boxed( src_value ); @@ -1151,7 +1133,7 @@ vips_area_get_type( void ) static int value_set_area( VipsCallbackFn free_fn, void *data, GValue *value ) { - Area *area; + VipsArea *area; if( !(area = area_new( free_fn, data )) ) return( -1 ); @@ -1168,7 +1150,7 @@ value_set_area( VipsCallbackFn free_fn, void *data, GValue *value ) static void * value_get_area_data( const GValue *value ) { - Area *area; + VipsArea *area; area = g_value_get_boxed( value ); @@ -1178,7 +1160,7 @@ value_get_area_data( const GValue *value ) static size_t value_get_area_length( const GValue *value ) { - Area *area; + VipsArea *area; area = g_value_get_boxed( value ); @@ -1300,7 +1282,7 @@ vips_ref_string_get_length( const GValue *value ) int vips_ref_string_set( GValue *value, const char *str ) { - Area *area; + VipsArea *area; char *str_copy; g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_REF_STRING ); @@ -1387,7 +1369,7 @@ vips_ref_string_get_type( void ) void * vips_blob_get( const GValue *value, size_t *length ) { - Area *area; + VipsArea *area; /* Can't check value type, because we may get called from * vips_blob_get_type(). @@ -1487,7 +1469,7 @@ int vips_blob_set( GValue *value, VipsCallbackFn free_fn, void *data, size_t length ) { - Area *area; + VipsArea *area; g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_BLOB ); @@ -1502,15 +1484,16 @@ vips_blob_set( GValue *value, /* An area which holds a copy of an array of GType. */ -static Area * +static VipsArea * area_new_array( GType type, size_t sizeof_type, int n ) { - Area *area; + VipsArea *area; void *array; array = g_malloc( n * sizeof_type ); - if( !(area = area_new( g_free, array )) ) + if( !(area = area_new( (VipsCallbackFn) g_free, array )) ) return( NULL ); + area->n = n; area->length = n * sizeof_type; area->type = G_TYPE_DOUBLE; area->sizeof_type = sizeof_type; @@ -1524,9 +1507,7 @@ area_new_array( GType type, size_t sizeof_type, int n ) static int vips_array_set( GValue *value, GType type, size_t sizeof_type, int n ) { - Area *area; - - g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_ARRAY ); + VipsArea *area; if( !(area = area_new_array( type, sizeof_type, n )) ) return( -1 ); @@ -1538,17 +1519,17 @@ vips_array_set( GValue *value, GType type, size_t sizeof_type, int n ) static void * vips_array_get( const GValue *value, - int *length, GType *type, size_t *sizeof_type ) + int *n, GType *type, size_t *sizeof_type ) { - Area *area; + VipsArea *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( n ) + *n = area->n; if( type ) *type = area->type; if( sizeof_type ) @@ -1561,20 +1542,19 @@ static void transform_array_g_string( const GValue *src_value, GValue *dest_value ) { char *array; - int length; + int n; GType type; size_t sizeof_type; - int n; char txt[1024]; VipsBuf buf = VIPS_BUF_STATIC( txt ); int i; array = (char *) vips_array_get( src_value, - &length, &type, &sizeof_type ); - n = length / sizeof_type; + &n, &type, &sizeof_type ); for( i = 0; i < n; i++ ) { GValue value = { 0, }; + char *str; if( i > 0 ) vips_buf_appends( &buf, ", " ); @@ -1609,8 +1589,8 @@ vips_array_double_get_type( void ) if( !type ) { type = g_boxed_type_register_static( "vips_array_double", - (GBoxedCopyFunc) area_ref, - (GBoxedFreeFunc) area_copy ); + (GBoxedCopyFunc) area_copy, + (GBoxedFreeFunc) area_unref ); g_value_register_transform_func( type, G_TYPE_STRING, transform_array_g_string ); } @@ -1633,15 +1613,7 @@ vips_array_double_get_type( void ) 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 ); + return( vips_array_get( value, n, NULL, NULL ) ); } /** @@ -1657,12 +1629,11 @@ vips_array_double_get( const GValue *value, int *n ) * Returns: 0 on success, -1 otherwise. */ int -vips_array_double_set( const GValue *value, double *array, int n ) +vips_array_double_set( GValue *value, const double *array, int n ) { double *array_copy; - vips_array_set( value, - G_TYPE_DOUBLE, sizeof( double ), n * sizeof( double ) ); + vips_array_set( value, G_TYPE_DOUBLE, sizeof( double ), n ); array_copy = vips_array_double_get( value, NULL ); memcpy( array_copy, array, n * sizeof( double ) ); @@ -1879,7 +1850,7 @@ vips_image_get_string( VipsImage *image, const char *field, char **out ) { int i; GValue value_copy = { 0 }; - Area *area; + VipsArea *area; for( i = 0; i < VIPS_NUMBER( string_field ); i++ ) if( strcmp( field, string_field[i].field ) == 0 ) { diff --git a/libvips/iofuncs/region.c b/libvips/iofuncs/region.c index 1770b9e8..a728f8d5 100644 --- a/libvips/iofuncs/region.c +++ b/libvips/iofuncs/region.c @@ -886,8 +886,8 @@ vips_region_paint_pel( VipsRegion *reg, VipsRect *r, PEL *ink ) for( x = 0; x < ovl.width; x++ ) { /* Faster than memcpy() for about n<20. */ - for( j = 0; j < ps; j++ ) - q[j] = ink[j]; + for( z = 0; z < ps; z++ ) + q[z] = ink[z]; q += ps; }