gmic uses an imagevec for input images

This commit is contained in:
John Cupitt 2014-10-06 21:52:27 +01:00
parent ae7d81d748
commit 3788c85e54
7 changed files with 82 additions and 129 deletions

View File

@ -15,6 +15,8 @@
- better extra band handling by colour, again - better extra band handling by colour, again
- move zoomify ImageProperties file, now a better match to the offical tool - move zoomify ImageProperties file, now a better match to the offical tool
- rename VIPS_ANGLE_180 as VIPS_ANGLE_D180 etc. to help python - rename VIPS_ANGLE_180 as VIPS_ANGLE_D180 etc. to help python
- update cimg
- add gmic
8/9/14 started 7.40.10 8/9/14 started 7.40.10
- icc_import and icc_transform checks the input profile for compatibility - icc_import and icc_transform checks the input profile for compatibility

View File

@ -42,30 +42,15 @@
#include <iostream> #include <iostream>
/* 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 <pthread.h>
#endif
*/
#include "CImg.h" #include "CImg.h"
#include "gmic.h" #include "gmic.h"
using namespace cimg_library; using namespace cimg_library;
//#define gmic_image cimg_library::CImg
#define GMIC_MAX_INPUT_IMAGES 10
typedef struct _VipsGMic { typedef struct _VipsGMic {
VipsOperation parent_instance; VipsOperation parent_instance;
VipsImage* in[GMIC_MAX_INPUT_IMAGES];
int ninput; VipsArrayImage *in;
VipsImage *out; VipsImage *out;
char *command; char *command;
int padding; int padding;
@ -152,6 +137,7 @@ _gmic_gen( VipsRegion *oreg, void *seq, void *a, void *b, gboolean *stop )
{ {
VipsRegion **ir = (VipsRegion **) seq; VipsRegion **ir = (VipsRegion **) seq;
VipsGMic *vipsgmic = (VipsGMic *) b; VipsGMic *vipsgmic = (VipsGMic *) b;
int ninput = VIPS_AREA( vipsgmic->in )->n;
const int tile_border = gmic_get_tile_border( vipsgmic ); 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<T> images; // List of images, will contain all images pixel data. gmic_list<T> images; // List of images, will contain all images pixel data.
gmic_list<char> images_names; // List of images names. Can be left empty if no names are associated to images. gmic_list<char> images_names; // List of images names. Can be left empty if no names are associated to images.
try { try {
images.assign( (unsigned int)vipsgmic->ninput ); images.assign( (unsigned int)ninput );
for( int i = 0; ir[i]; i++ ) { for( int i = 0; ir[i]; i++ ) {
gmic_image<T>& img = images._data[i]; gmic_image<T>& img = images._data[i];
img.assign(need->width,need->height,1,ir[i]->im->Bands); 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); printf("G'MIC command: %s\n",vipsgmic->command);
std::cout<<" ninput="<<vipsgmic->ninput std::cout<<" ninput="<<ninput
<<std::endl; <<std::endl;
std::cout<<" padding="<<vipsgmic->padding std::cout<<" padding="<<vipsgmic->padding
<<" x scale="<<vipsgmic->x_scale<<std::endl; <<" x scale="<<vipsgmic->x_scale<<std::endl;
@ -265,17 +251,18 @@ static int _gmic_build( VipsObject *object )
VipsObjectClass *klass = VIPS_OBJECT_GET_CLASS( object ); VipsObjectClass *klass = VIPS_OBJECT_GET_CLASS( object );
//VipsOperation *operation = VIPS_OPERATION( object ); //VipsOperation *operation = VIPS_OPERATION( object );
VipsGMic *vipsgmic = (VipsGMic *) object; VipsGMic *vipsgmic = (VipsGMic *) object;
VipsImage **in;
int ninput;
int i; int i;
if( vipsgmic->ninput < 1 ) return -1;
if( !(vipsgmic->in[0]) ) return -1;
if( VIPS_OBJECT_CLASS( vips_gmic_parent_class )->build( object ) ) if( VIPS_OBJECT_CLASS( vips_gmic_parent_class )->build( object ) )
return( -1 ); return( -1 );
for( i = 0; i < vipsgmic->ninput; i++ ) { in = vips_array_image_get( vipsgmic->in, &ninput );
if( vips_image_pio_input( vipsgmic->in[i] ) ||
vips_check_coding_known( klass->nickname, vipsgmic->in[i] ) ) for( i = 0; i < ninput; i++ ) {
if( vips_image_pio_input( in[i] ) ||
vips_check_coding_known( klass->nickname, in[i] ) )
return( -1 ); return( -1 );
} }
@ -285,14 +272,6 @@ static int _gmic_build( VipsObject *object )
*/ */
g_object_set( vipsgmic, "out", vips_image_new(), NULL ); g_object_set( vipsgmic, "out", vips_image_new(), NULL );
VipsImage** in = (VipsImage**)im_malloc( vipsgmic->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. /* Set demand hints.
*/ */
if( vips_image_pipeline_array( vipsgmic->out, if( vips_image_pipeline_array( vipsgmic->out,
@ -300,18 +279,13 @@ static int _gmic_build( VipsObject *object )
in ) ) in ) )
return( -1 ); return( -1 );
vips_image_init_fields( vipsgmic->out, if(ninput > 0) {
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( vips_image_generate( vipsgmic->out, if( vips_image_generate( vipsgmic->out,
vips_start_many, gmic_gen, vips_stop_many, vips_start_many, gmic_gen, vips_stop_many,
in, vipsgmic ) ) in, vipsgmic ) )
return( -1 ); return( -1 );
} else { }
else {
if( vips_image_generate( vipsgmic->out, if( vips_image_generate( vipsgmic->out,
NULL, gmic_gen, NULL, NULL, vipsgmic ) ) NULL, gmic_gen, NULL, NULL, vipsgmic ) )
return( -1 ); return( -1 );
@ -327,6 +301,7 @@ vips_gmic_class_init( VipsGMicClass *klass )
GObjectClass *gobject_class = G_OBJECT_CLASS( klass ); GObjectClass *gobject_class = G_OBJECT_CLASS( klass );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( klass ); VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( klass );
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( klass ); VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( klass );
gobject_class->set_property = vips_object_set_property; gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property; gobject_class->get_property = vips_object_get_property;
vobject_class->nickname = "gmic"; vobject_class->nickname = "gmic";
@ -334,12 +309,12 @@ vips_gmic_class_init( VipsGMicClass *klass )
vobject_class->build = _gmic_build; vobject_class->build = _gmic_build;
operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED; operation_class->flags = VIPS_OPERATION_SEQUENTIAL_UNBUFFERED;
VIPS_ARG_INT( klass, "ninput", 0, VIPS_ARG_BOXED( klass, "in", 0,
_( "NInput" ), _( "Input" ),
_( "Number of input images" ), _( "Array of input images" ),
VIPS_ARGUMENT_REQUIRED_INPUT, VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsGMic, ninput ), G_STRUCT_OFFSET( VipsGMic, in ),
0, GMIC_MAX_INPUT_IMAGES, 0 ); VIPS_TYPE_ARRAY_IMAGE );
VIPS_ARG_IMAGE( klass, "out", 1, VIPS_ARG_IMAGE( klass, "out", 1,
_( "Output" ), _( "Output" ),
@ -374,37 +349,27 @@ vips_gmic_class_init( VipsGMicClass *klass )
VIPS_ARGUMENT_REQUIRED_INPUT, VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsGMic, command ), G_STRUCT_OFFSET( VipsGMic, command ),
NULL ); 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 static void
vips_gmic_init( VipsGMic *vipsgmic ) vips_gmic_init( VipsGMic *vipsgmic )
{ {
} }
int 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, ...)
{ {
VipsArrayImage *array;
va_list ap; va_list ap;
int result; int result;
va_start( ap, y_scale );
//result = vips_call_split( "vips_gmic", ap, n, out, command, padding, x_scale, y_scale ); array = vips_array_image_new( in, n );
result = vips_call_split( "gmic", ap, n, out, padding, x_scale, y_scale, command ); va_start( ap, command );
result = vips_call_split( "gmic", ap, array, out,
padding, x_scale, y_scale, command );
va_end( ap ); va_end( ap );
vips_area_unref( VIPS_AREA( array ) );
return( result ); return( result );
} }

View File

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

View File

@ -463,13 +463,13 @@ gboolean vips_band_format_iscomplex( VipsBandFormat format );
int vips_system( const char *cmd_format, ... ) int vips_system( const char *cmd_format, ... )
__attribute__((sentinel)); __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_new( VipsImage **array, int n );
VipsArrayImage *vips_array_image_newv( int n, ... ); VipsArrayImage *vips_array_image_newv( int n, ... );
VipsImage **vips_array_image_get( VipsArrayImage *array, int *n ); VipsImage **vips_array_image_get( VipsArrayImage *array, int *n );
VipsImage **vips_value_get_array_image( const GValue *value, 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 #ifdef __cplusplus
} }

View File

@ -210,7 +210,7 @@ void vips_value_set_save_stringf( GValue *value, const char *fmt, ... )
__attribute__((format(printf, 2, 3))); __attribute__((format(printf, 2, 3)));
const char *vips_value_get_ref_string( const GValue *value, size_t *length ); 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_get_blob( const GValue *value, size_t *length );
void vips_value_set_blob( GValue *value, 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 ); int *n, GType *type, size_t *sizeof_type );
double *vips_value_get_array_double( const GValue *value, int *n ); 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_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 ); 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(), /* 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 * vips_value_get_array_image() and vips_value_set_array_image(). They need

View File

@ -285,6 +285,8 @@ vips_init( const char *argv0 )
vips_morphology_operation_init(); vips_morphology_operation_init();
vips_draw_operation_init(); vips_draw_operation_init();
vips_mosaicing_operation_init(); vips_mosaicing_operation_init();
extern int vips_gmic_get_type( void );
vips_gmic_get_type(); vips_gmic_get_type();
/* Load up any plugins in the vips libdir. We don't error on failure, /* Load up any plugins in the vips libdir. We don't error on failure,

View File

@ -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 * An area which holds an array of %GObjects. See vips_area_new_array(). When
* the area is freed, each %GObject will be unreffed. * 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(). * See also: vips_area_unref().
* *
* Returns: (transfer full): the new #VipsArea. * Returns: (transfer full): the new #VipsArea.
@ -332,7 +335,7 @@ vips_area_new_array_object( int n )
GObject **array; GObject **array;
VipsArea *area; VipsArea *area;
array = g_new0( GObject *, n ); array = g_new0( GObject *, n + 1 );
area = vips_area_new( (VipsCallbackFn) vips_area_free_array_object, area = vips_area_new( (VipsCallbackFn) vips_area_free_array_object,
array ); array );
area->n = n; area->n = n;
@ -962,7 +965,7 @@ transform_g_string_array_image( const GValue *src_value, GValue *dest_value )
int n; int n;
char *p, *q; char *p, *q;
int i; int i;
GObject **array; VipsImage **array;
/* We need a copy of the string, since we insert \0 during /* We need a copy of the string, since we insert \0 during
* scan. * scan.
@ -975,17 +978,16 @@ transform_g_string_array_image( const GValue *src_value, GValue *dest_value )
g_free( str ); g_free( str );
vips_value_set_array_object( dest_value, n ); vips_value_set_array_image( dest_value, n );
array = vips_value_get_array_object( dest_value, NULL ); array = vips_value_get_array_image( dest_value, NULL );
str = g_value_dup_string( src_value ); str = g_value_dup_string( src_value );
for( i = 0, p = str; (q = vips_break_token( p, " " )); i++, p = q ) for( i = 0, p = str; (q = vips_break_token( p, " " )); i++, p = q )
if( !(array[i] = G_OBJECT( vips_image_new_from_file( p, if( !(array[i] = vips_image_new_from_file( p, NULL )) ) {
NULL ) )) ) {
/* Set the dest to length zero to indicate error. /* 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 ); g_free( str );
return; return;
} }
@ -1005,6 +1007,9 @@ transform_g_string_array_image( const GValue *src_value, GValue *dest_value )
* will be automatically unreffed for you by * will be automatically unreffed for you by
* vips_area_unref(). * vips_area_unref().
* *
* Add an extra NULL element at the end, handy for eg.
* vips_image_pipeline_array() etc.
*
* See also: #VipsArea. * See also: #VipsArea.
* *
* Returns: (transfer full): A new #VipsArrayImage. * 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 * will be automatically unreffed for you by
* vips_area_unref(). * 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() * See also: vips_array_image_new()
* *
* Returns: (transfer full): A new #VipsArrayImage. * 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 * vips_ref_string are immutable C strings that are copied between images by
* copying reference-counted pointers, making the much more efficient than * copying reference-counted pointers, making the much more efficient than
* regular %GValue strings. * regular %GValue strings.
*
* Returns: 0 on success, -1 otherwise.
*/ */
int void
vips_value_set_ref_string( GValue *value, const char *str ) vips_value_set_ref_string( GValue *value, const char *str )
{ {
VipsArea *area; VipsArea *area;
@ -1239,8 +1245,6 @@ vips_value_set_ref_string( GValue *value, const char *str )
g_value_set_boxed( value, area ); g_value_set_boxed( value, area );
vips_area_unref( 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. * Set @value to hold a copy of @array. Pass in the array length in @n.
* *
* See also: vips_array_int_get(). * 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 ) vips_value_set_array_int( GValue *value, const int *array, int n )
{ {
int *array_copy; 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 ) ); vips_value_set_array( value, n, G_TYPE_INT, sizeof( int ) );
array_copy = vips_value_get_array_int( value, NULL ); array_copy = vips_value_get_array_int( value, NULL );
memcpy( array_copy, array, n * sizeof( int ) ); 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. * Set @value to hold a copy of @array. Pass in the array length in @n.
* *
* See also: vips_array_double_get(). * 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 ) vips_value_set_array_double( GValue *value, const double *array, int n )
{ {
double *array_copy; 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 ) ); vips_value_set_array( value, n, G_TYPE_DOUBLE, sizeof( double ) );
array_copy = vips_value_get_array_double( value, NULL ); array_copy = vips_value_get_array_double( value, NULL );
memcpy( array_copy, array, n * sizeof( double ) ); 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: * vips_value_set_array_image:
* @value: (out): %GValue to get from * @value: (out): %GValue to get from
* @array: (array length=n): array of images
* @n: the number of elements * @n: the number of elements
* *
* Set @value to hold a copy of @array. Pass in the array length in @n. * Set @value to hold a copy of @array. Pass in the array length in @n.
* *
* See also: vips_array_image_get(). * See also: vips_array_image_get().
*
* Returns: 0 on success, -1 otherwise.
*/ */
int void
vips_value_set_array_image( GValue *value, VipsImage **array, int n ) vips_value_set_array_image( GValue *value, int n )
{ {
VipsImage **array_copy; VipsArea *area;
g_value_init( value, VIPS_TYPE_ARRAY_IMAGE ); area = vips_area_new_array_object( n );
vips_value_set_array( value, n, VIPS_TYPE_ARRAY_IMAGE, area->type = VIPS_TYPE_IMAGE;
sizeof( VipsImage * ) ); g_value_set_boxed( value, area );
array_copy = vips_value_get_array_image( value, NULL ); vips_area_unref( area );
memcpy( array_copy, array, n * sizeof( VipsImage * ) );
return( 0 );
} }
/** /**
@ -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 * @value: (out): %GValue to set
* @n: the number of elements * @n: the number of elements
* *
* Set @value to hold an array of %GObject. Pass in the array length in @n. * Set @value to hold an array of %GObject. Pass in the array length in @n.
* *
* See also: vips_array_object_get(). * See also: vips_array_object_get().
*
* Returns: 0 on success, -1 otherwise.
*/ */
int void
vips_value_set_array_object( GValue *value, int n ) vips_value_set_array_object( GValue *value, int n )
{ {
VipsArea *area; VipsArea *area;
if( !(area = vips_area_new_array_object( n )) ) area = vips_area_new_array_object( n );
return( -1 );
g_value_set_boxed( value, area ); g_value_set_boxed( value, area );
vips_area_unref( area ); vips_area_unref( area );
return( 0 );
} }
/* Make the types we need for basic functioning. Called from vips_init(). /* Make the types we need for basic functioning. Called from vips_init().