From 3788c85e54d6e22d0883a2aba1e52ec01487865c Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Mon, 6 Oct 2014 21:52:27 +0100 Subject: [PATCH] gmic uses an imagevec for input images --- ChangeLog | 2 + libvips/cimg/vips_gmic.cpp | 121 ++++++++++++---------------------- libvips/conversion/bandjoin.c | 3 +- libvips/include/vips/image.h | 4 +- libvips/include/vips/type.h | 8 +-- libvips/iofuncs/init.c | 2 + libvips/iofuncs/type.c | 71 ++++++++------------ 7 files changed, 82 insertions(+), 129 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8d28f89c..2124a4f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,8 @@ - better extra band handling by colour, again - move zoomify ImageProperties file, now a better match to the offical tool - rename VIPS_ANGLE_180 as VIPS_ANGLE_D180 etc. to help python +- update cimg +- add gmic 8/9/14 started 7.40.10 - icc_import and icc_transform checks the input profile for compatibility diff --git a/libvips/cimg/vips_gmic.cpp b/libvips/cimg/vips_gmic.cpp index f910210b..4b0818af 100644 --- a/libvips/cimg/vips_gmic.cpp +++ b/libvips/cimg/vips_gmic.cpp @@ -42,35 +42,20 @@ #include -/* CImg needs to call pthread directly, this is the preproc magic they - * prefer. -#if defined(sun) || defined(__sun) || defined(linux) || defined(__linux) \ - || defined(__linux__) || defined(__CYGWIN__) || defined(BSD) || defined(__FreeBSD__) \ - || defined(__OPENBSD__) || defined(__MACOSX__) || defined(__APPLE__) || defined(sgi) \ - || defined(__sgi) -#include -#endif - */ - #include "CImg.h" #include "gmic.h" using namespace cimg_library; -//#define gmic_image cimg_library::CImg - - -#define GMIC_MAX_INPUT_IMAGES 10 - typedef struct _VipsGMic { - VipsOperation parent_instance; - VipsImage* in[GMIC_MAX_INPUT_IMAGES]; - int ninput; - VipsImage* out; - char* command; - int padding; - double x_scale; - double y_scale; + VipsOperation parent_instance; + + VipsArrayImage *in; + VipsImage *out; + char *command; + int padding; + double x_scale; + double y_scale; } VipsGMic; typedef VipsOperationClass VipsGMicClass; @@ -152,6 +137,7 @@ _gmic_gen( VipsRegion *oreg, void *seq, void *a, void *b, gboolean *stop ) { VipsRegion **ir = (VipsRegion **) seq; VipsGMic *vipsgmic = (VipsGMic *) b; + int ninput = VIPS_AREA( vipsgmic->in )->n; const int tile_border = gmic_get_tile_border( vipsgmic ); @@ -185,7 +171,7 @@ _gmic_gen( VipsRegion *oreg, void *seq, void *a, void *b, gboolean *stop ) gmic_list images; // List of images, will contain all images pixel data. gmic_list images_names; // List of images names. Can be left empty if no names are associated to images. try { - images.assign( (unsigned int)vipsgmic->ninput ); + images.assign( (unsigned int)ninput ); for( int i = 0; ir[i]; i++ ) { gmic_image& img = images._data[i]; img.assign(need->width,need->height,1,ir[i]->im->Bands); @@ -193,7 +179,7 @@ _gmic_gen( VipsRegion *oreg, void *seq, void *a, void *b, gboolean *stop ) } printf("G'MIC command: %s\n",vipsgmic->command); - std::cout<<" ninput="<ninput + std::cout<<" ninput="<out, sizeof(VipsImage*)*(vipsgmic->ninput+1) ); - if( !in ) return( -1 ); - - for( i = 0; i < vipsgmic->ninput; i++ ) { - in[i] = vipsgmic->in[i]; - } - in[vipsgmic->ninput] = NULL; - /* Set demand hints. */ if( vips_image_pipeline_array( vipsgmic->out, @@ -300,18 +279,13 @@ static int _gmic_build( VipsObject *object ) in ) ) return( -1 ); - vips_image_init_fields( vipsgmic->out, - in[0]->Xsize, in[0]->Ysize, - in[0]->Bands, in[0]->BandFmt, - in[0]->Coding, in[0]->Type, - 1.0, 1.0); - - if(vipsgmic->ninput > 0) { + if(ninput > 0) { if( vips_image_generate( vipsgmic->out, vips_start_many, gmic_gen, vips_stop_many, in, vipsgmic ) ) return( -1 ); - } else { + } + else { if( vips_image_generate( vipsgmic->out, NULL, gmic_gen, NULL, NULL, vipsgmic ) ) return( -1 ); @@ -327,6 +301,7 @@ vips_gmic_class_init( VipsGMicClass *klass ) GObjectClass *gobject_class = G_OBJECT_CLASS( klass ); VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( klass ); VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( klass ); + gobject_class->set_property = vips_object_set_property; gobject_class->get_property = vips_object_get_property; vobject_class->nickname = "gmic"; @@ -334,12 +309,12 @@ vips_gmic_class_init( VipsGMicClass *klass ) vobject_class->build = _gmic_build; operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; - VIPS_ARG_INT( klass, "ninput", 0, - _( "NInput" ), - _( "Number of input images" ), - VIPS_ARGUMENT_REQUIRED_INPUT, - G_STRUCT_OFFSET( VipsGMic, ninput ), - 0, GMIC_MAX_INPUT_IMAGES, 0 ); + VIPS_ARG_BOXED( klass, "in", 0, + _( "Input" ), + _( "Array of input images" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsGMic, in ), + VIPS_TYPE_ARRAY_IMAGE ); VIPS_ARG_IMAGE( klass, "out", 1, _( "Output" ), @@ -374,37 +349,27 @@ vips_gmic_class_init( VipsGMicClass *klass ) VIPS_ARGUMENT_REQUIRED_INPUT, G_STRUCT_OFFSET( VipsGMic, command ), NULL ); - - char tstr[100]; - char tstr2[100]; - char tstr3[100]; - for( int imgid = 0; imgid < GMIC_MAX_INPUT_IMAGES; imgid++ ) { - snprintf(tstr,99,"in%d",imgid); - snprintf(tstr2,99,"Input%d",imgid); - snprintf(tstr3,99,"Input image %d",imgid); - VIPS_ARG_IMAGE( klass, tstr, imgid+11, - _( tstr2 ), - _( tstr3 ), - VIPS_ARGUMENT_OPTIONAL_INPUT, - G_STRUCT_OFFSET( VipsGMic, in )+sizeof(VipsImage*)*imgid ); - } } - static void vips_gmic_init( VipsGMic *vipsgmic ) { } - int -vips_gmic(int n, VipsImage** out, const char* command, int padding, float x_scale, float y_scale,...) +vips_gmic( VipsImage **in, VipsImage **out, int n, + int padding, double x_scale, double y_scale, const char *command, ...) { - va_list ap; - int result; - va_start( ap, y_scale ); - //result = vips_call_split( "vips_gmic", ap, n, out, command, padding, x_scale, y_scale ); - result = vips_call_split( "gmic", ap, n, out, padding, x_scale, y_scale, command ); - va_end( ap ); - return( result ); + VipsArrayImage *array; + va_list ap; + int result; + + array = vips_array_image_new( in, n ); + va_start( ap, command ); + result = vips_call_split( "gmic", ap, array, out, + padding, x_scale, y_scale, command ); + va_end( ap ); + vips_area_unref( VIPS_AREA( array ) ); + + return( result ); } diff --git a/libvips/conversion/bandjoin.c b/libvips/conversion/bandjoin.c index 34a994e8..b0886ce0 100644 --- a/libvips/conversion/bandjoin.c +++ b/libvips/conversion/bandjoin.c @@ -130,8 +130,7 @@ vips_bandjoin_build( VipsObject *object ) VipsBandjoin *bandjoin = (VipsBandjoin *) object; if( bandjoin->in ) { - bandary->in = VIPS_AREA( bandjoin->in )->data; - bandary->n = VIPS_AREA( bandjoin->in )->n; + bandary->in = vips_array_image_get( bandjoin->in, &bandary->n ); if( bandary->n == 1 ) return( vips_bandary_copy( bandary ) ); diff --git a/libvips/include/vips/image.h b/libvips/include/vips/image.h index 762cff61..b7b8a970 100644 --- a/libvips/include/vips/image.h +++ b/libvips/include/vips/image.h @@ -463,13 +463,13 @@ gboolean vips_band_format_iscomplex( VipsBandFormat format ); int vips_system( const char *cmd_format, ... ) __attribute__((sentinel)); -/* Defined in type.c, but declared here since they use VipsImage. +/* Defined in type.c but declared here, since they use VipsImage. */ VipsArrayImage *vips_array_image_new( VipsImage **array, int n ); VipsArrayImage *vips_array_image_newv( 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 ); +void vips_value_set_array_image( GValue *value, int n ); #ifdef __cplusplus } diff --git a/libvips/include/vips/type.h b/libvips/include/vips/type.h index aa7591ee..fab060ab 100644 --- a/libvips/include/vips/type.h +++ b/libvips/include/vips/type.h @@ -210,7 +210,7 @@ void vips_value_set_save_stringf( GValue *value, const char *fmt, ... ) __attribute__((format(printf, 2, 3))); const char *vips_value_get_ref_string( const GValue *value, size_t *length ); -int vips_value_set_ref_string( GValue *value, const char *str ); +void vips_value_set_ref_string( GValue *value, const char *str ); void *vips_value_get_blob( const GValue *value, size_t *length ); void vips_value_set_blob( GValue *value, @@ -222,13 +222,13 @@ void *vips_value_get_array( const GValue *value, int *n, GType *type, size_t *sizeof_type ); double *vips_value_get_array_double( const GValue *value, int *n ); -int vips_value_set_array_double( GValue *value, const double *array, int n ); +void vips_value_set_array_double( GValue *value, const double *array, int n ); int *vips_value_get_array_int( const GValue *value, int *n ); -int vips_value_set_array_int( GValue *value, const int *array, int n ); +void 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 ); +void vips_value_set_array_object( GValue *value, int n ); /* 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 diff --git a/libvips/iofuncs/init.c b/libvips/iofuncs/init.c index 307f1537..c69cac7b 100644 --- a/libvips/iofuncs/init.c +++ b/libvips/iofuncs/init.c @@ -285,6 +285,8 @@ vips_init( const char *argv0 ) vips_morphology_operation_init(); vips_draw_operation_init(); vips_mosaicing_operation_init(); + + extern int vips_gmic_get_type( void ); vips_gmic_get_type(); /* Load up any plugins in the vips libdir. We don't error on failure, diff --git a/libvips/iofuncs/type.c b/libvips/iofuncs/type.c index 880b470c..2babfd34 100644 --- a/libvips/iofuncs/type.c +++ b/libvips/iofuncs/type.c @@ -322,6 +322,9 @@ vips_area_free_array_object( GObject **array, VipsArea *area ) * An area which holds an array of %GObjects. See vips_area_new_array(). When * the area is freed, each %GObject will be unreffed. * + * Add an extra NULL element at the end, handy for eg. + * vips_image_pipeline_array() etc. + * * See also: vips_area_unref(). * * Returns: (transfer full): the new #VipsArea. @@ -332,7 +335,7 @@ vips_area_new_array_object( int n ) GObject **array; VipsArea *area; - array = g_new0( GObject *, n ); + array = g_new0( GObject *, n + 1 ); area = vips_area_new( (VipsCallbackFn) vips_area_free_array_object, array ); area->n = n; @@ -962,7 +965,7 @@ transform_g_string_array_image( const GValue *src_value, GValue *dest_value ) int n; char *p, *q; int i; - GObject **array; + VipsImage **array; /* We need a copy of the string, since we insert \0 during * scan. @@ -975,17 +978,16 @@ transform_g_string_array_image( const GValue *src_value, GValue *dest_value ) g_free( str ); - vips_value_set_array_object( dest_value, n ); - array = vips_value_get_array_object( dest_value, NULL ); + vips_value_set_array_image( dest_value, n ); + array = vips_value_get_array_image( dest_value, NULL ); str = g_value_dup_string( src_value ); for( i = 0, p = str; (q = vips_break_token( p, " " )); i++, p = q ) - if( !(array[i] = G_OBJECT( vips_image_new_from_file( p, - NULL ) )) ) { + if( !(array[i] = vips_image_new_from_file( p, NULL )) ) { /* Set the dest to length zero to indicate error. */ - vips_value_set_array_object( dest_value, 0 ); + vips_value_set_array_image( dest_value, 0 ); g_free( str ); return; } @@ -1005,6 +1007,9 @@ transform_g_string_array_image( const GValue *src_value, GValue *dest_value ) * will be automatically unreffed for you by * vips_area_unref(). * + * Add an extra NULL element at the end, handy for eg. + * vips_image_pipeline_array() etc. + * * See also: #VipsArea. * * Returns: (transfer full): A new #VipsArrayImage. @@ -1040,6 +1045,9 @@ vips_array_image_new( VipsImage **array, int n ) * will be automatically unreffed for you by * vips_area_unref(). * + * Add an extra NULL element at the end, handy for eg. + * vips_image_pipeline_array() etc. + * * See also: vips_array_image_new() * * Returns: (transfer full): A new #VipsArrayImage. @@ -1219,10 +1227,8 @@ vips_value_get_ref_string( const GValue *value, size_t *length ) * vips_ref_string are immutable C strings that are copied between images by * copying reference-counted pointers, making the much more efficient than * regular %GValue strings. - * - * Returns: 0 on success, -1 otherwise. */ -int +void vips_value_set_ref_string( GValue *value, const char *str ) { VipsArea *area; @@ -1239,8 +1245,6 @@ vips_value_set_ref_string( GValue *value, const char *str ) g_value_set_boxed( value, area ); vips_area_unref( area ); - - return( 0 ); } /** @@ -1380,10 +1384,8 @@ vips_value_get_array_int( const GValue *value, int *n ) * Set @value to hold a copy of @array. Pass in the array length in @n. * * See also: vips_array_int_get(). - * - * Returns: 0 on success, -1 otherwise. */ -int +void vips_value_set_array_int( GValue *value, const int *array, int n ) { int *array_copy; @@ -1392,8 +1394,6 @@ vips_value_set_array_int( GValue *value, const int *array, int n ) vips_value_set_array( value, n, G_TYPE_INT, sizeof( int ) ); array_copy = vips_value_get_array_int( value, NULL ); memcpy( array_copy, array, n * sizeof( int ) ); - - return( 0 ); } /** @@ -1423,10 +1423,8 @@ vips_value_get_array_double( const GValue *value, int *n ) * 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 +void vips_value_set_array_double( GValue *value, const double *array, int n ) { double *array_copy; @@ -1435,8 +1433,6 @@ vips_value_set_array_double( GValue *value, const double *array, int n ) vips_value_set_array( value, n, G_TYPE_DOUBLE, sizeof( double ) ); array_copy = vips_value_get_array_double( value, NULL ); memcpy( array_copy, array, n * sizeof( double ) ); - - return( 0 ); } /** @@ -1460,27 +1456,21 @@ vips_value_get_array_image( const GValue *value, int *n ) /** * vips_value_set_array_image: * @value: (out): %GValue to get from - * @array: (array length=n): array of images * @n: the number of elements * * Set @value to hold a copy of @array. Pass in the array length in @n. * * See also: vips_array_image_get(). - * - * Returns: 0 on success, -1 otherwise. */ -int -vips_value_set_array_image( GValue *value, VipsImage **array, int n ) +void +vips_value_set_array_image( GValue *value, int n ) { - VipsImage **array_copy; + VipsArea *area; - g_value_init( value, VIPS_TYPE_ARRAY_IMAGE ); - vips_value_set_array( value, n, VIPS_TYPE_ARRAY_IMAGE, - sizeof( VipsImage * ) ); - array_copy = vips_value_get_array_image( value, NULL ); - memcpy( array_copy, array, n * sizeof( VipsImage * ) ); - - return( 0 ); + area = vips_area_new_array_object( n ); + area->type = VIPS_TYPE_IMAGE; + g_value_set_boxed( value, area ); + vips_area_unref( area ); } /** @@ -1502,27 +1492,22 @@ vips_value_get_array_object( const GValue *value, int *n ) } /** - * vips_array_object_set: + * vips_value_set_array_object: * @value: (out): %GValue to set * @n: the number of elements * * Set @value to hold an array of %GObject. Pass in the array length in @n. * * See also: vips_array_object_get(). - * - * Returns: 0 on success, -1 otherwise. */ -int +void vips_value_set_array_object( GValue *value, int n ) { VipsArea *area; - if( !(area = vips_area_new_array_object( n )) ) - return( -1 ); + area = vips_area_new_array_object( n ); g_value_set_boxed( value, area ); vips_area_unref( area ); - - return( 0 ); } /* Make the types we need for basic functioning. Called from vips_init().