diff --git a/ChangeLog b/ChangeLog index 3476ca74..fce78806 100644 --- a/ChangeLog +++ b/ChangeLog @@ -44,6 +44,8 @@ - dilate/erode do (!=0) on non-uchar images - add multipass Orc to im_conv(), 3.5x faster for 5x5 mask - im_profile() works for any image format, any number of bands +- im_rank_image() works for mix of formats, bands +- morph gtk-doc done 12/5/10 started 7.22.2 - the conditional image of ifthenelse can be any format, a (!=0) is added if diff --git a/doc/reference/Makefile.am b/doc/reference/Makefile.am index 0b2b88eb..64872d31 100644 --- a/doc/reference/Makefile.am +++ b/doc/reference/Makefile.am @@ -59,7 +59,7 @@ EXTRA_HFILES= # Header files to ignore when scanning. Use base file name, no paths # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h -IGNORE_HFILES=merge.h debug.h internal.h intl.h CImg.h im_video_v4l1.h global_balance.h dbh.h base64.h templates.h mosaic.h deprecated.h thread.h private.h internal.h almostdeprecated.h inlines.h struct.h disp.h +IGNORE_HFILES=merge.h debug.h internal.h intl.h CImg.h im_video_v4l1.h global_balance.h dbh.h base64.h templates.h mosaic.h deprecated.h thread.h private.h internal.h almostdeprecated.h inlines.h struct.h disp.h vector.h # Images to copy into HTML directory. # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png diff --git a/doc/reference/libvips-docs.sgml.in b/doc/reference/libvips-docs.sgml.in index d0c2048c..6dc0e3cf 100644 --- a/doc/reference/libvips-docs.sgml.in +++ b/doc/reference/libvips-docs.sgml.in @@ -43,11 +43,11 @@ + VIPS operation API by section (no gtkdoc comments yet) - diff --git a/libvips/arithmetic/im_add.c b/libvips/arithmetic/im_add.c index cba87e7a..676a5fa8 100644 --- a/libvips/arithmetic/im_add.c +++ b/libvips/arithmetic/im_add.c @@ -237,7 +237,7 @@ im__formatalike( IMAGE *in1, IMAGE *in2, IMAGE *out1, IMAGE *out2 ) /* Make an n-band image. Input 1 or n bands. */ int -im__bandup( IMAGE *in, IMAGE *out, int n ) +im__bandup( const char *domain, IMAGE *in, IMAGE *out, int n ) { IMAGE *bands[256]; int i; @@ -245,11 +245,11 @@ im__bandup( IMAGE *in, IMAGE *out, int n ) if( in->Bands == n ) return( im_copy( in, out ) ); if( in->Bands != 1 ) { - im_error( "im__bandup", _( "not one band or %d bands" ), n ); + im_error( domain, _( "not one band or %d bands" ), n ); return( -1 ); } if( n > 256 || n < 1 ) { - im_error( "im__bandup", "%s", _( "bad bands" ) ); + im_error( domain, "%s", _( "bad bands" ) ); return( -1 ); } @@ -260,12 +260,35 @@ im__bandup( IMAGE *in, IMAGE *out, int n ) } int -im__bandalike( IMAGE *in1, IMAGE *in2, IMAGE *out1, IMAGE *out2 ) +im__bandalike_vec( const char *domain, IMAGE **in, IMAGE **out, int n ) { - if( im_check_bands_1orn( "im__bandalike", in1, in2 ) ) - return( -1 ); - if( im__bandup( in1, out1, IM_MAX( in1->Bands, in2->Bands ) ) || - im__bandup( in2, out2, IM_MAX( in1->Bands, in2->Bands ) ) ) + int i; + int max_bands; + + g_assert( n >= 1 ); + + max_bands = in[0]->Bands; + for( i = 1; i < n; i++ ) + max_bands = IM_MAX( max_bands, in[i]->Bands ); + for( i = 0; i < n; i++ ) + if( im__bandup( domain, in[i], out[i], max_bands ) ) + return( -1 ); + + return( 0 ); +} + +int +im__bandalike( const char *domain, + IMAGE *in1, IMAGE *in2, IMAGE *out1, IMAGE *out2 ) +{ + IMAGE *in[2]; + IMAGE *out[2]; + + in[0] = in1; + in[1] = in2; + out[0] = out1; + out[1] = out2; + if( im__bandalike_vec( domain, in, out, 2 ) ) return( -1 ); return( 0 ); @@ -301,7 +324,7 @@ im__arith_binary( const char *domain, */ if( im_open_local_array( out, t, 4, domain, "p" ) || im__formatalike( in1, in2, t[0], t[1] ) || - im__bandalike( t[0], t[1], t[2], t[3] ) ) + im__bandalike( domain, t[0], t[1], t[2], t[3] ) ) return( -1 ); /* Generate the output. diff --git a/libvips/arithmetic/im_remainder.c b/libvips/arithmetic/im_remainder.c index 5dfd716c..144eb988 100644 --- a/libvips/arithmetic/im_remainder.c +++ b/libvips/arithmetic/im_remainder.c @@ -262,7 +262,7 @@ make_pixel( IMAGE *out, VipsBandFmt fmt, int n, double *p ) } int -im__arith_binary_const( const char *name, +im__arith_binary_const( const char *domain, IMAGE *in, IMAGE *out, int n, double *c, VipsBandFmt vfmt, int format_table[10], @@ -271,8 +271,8 @@ im__arith_binary_const( const char *name, PEL *vector; if( im_piocheck( in, out ) || - im_check_vector( name, n, in ) || - im_check_uncoded( name, in ) ) + im_check_vector( domain, n, in ) || + im_check_uncoded( domain, in ) ) return( -1 ); if( im_cp_desc( out, in ) ) return( -1 ); @@ -297,8 +297,8 @@ im__arith_binary_const( const char *name, if( n > 1 && out->Bands == 1 ) { IMAGE *t; - if( !(t = im_open_local( out, "arith_binary_const", "p" )) || - im__bandup( in, t, n ) ) + if( !(t = im_open_local( out, domain, "p" )) || + im__bandup( domain, in, t, n ) ) return( -1 ); in = t; diff --git a/libvips/conversion/im_gbandjoin.c b/libvips/conversion/im_gbandjoin.c index b9af40d8..1fca2e8f 100644 --- a/libvips/conversion/im_gbandjoin.c +++ b/libvips/conversion/im_gbandjoin.c @@ -66,7 +66,7 @@ /* Struct we carry stuff around in. */ typedef struct joins { - int n; /* Number of input images */ + int n; /* Number of input images */ IMAGE **in; /* Array of input images, NULL-terminated */ int *is; /* An int for SIZEOF_PEL() for each image */ } Join; diff --git a/libvips/conversion/im_insert.c b/libvips/conversion/im_insert.c index 68d91365..1651ab7c 100644 --- a/libvips/conversion/im_insert.c +++ b/libvips/conversion/im_insert.c @@ -97,7 +97,7 @@ im__insert_base( const char *domain, */ if( im_open_local_array( out, t, 4, domain, "p" ) || im__formatalike( in1, in2, t[0], t[1] ) || - im__bandalike( t[0], t[1], t[2], t[3] ) || + im__bandalike( domain, t[0], t[1], t[2], t[3] ) || !(vec = im_allocate_input_array( out, t[2], t[3], NULL )) ) return( NULL ); diff --git a/libvips/conversion/im_ri2c.c b/libvips/conversion/im_ri2c.c index 9d0c8c4a..e1913235 100644 --- a/libvips/conversion/im_ri2c.c +++ b/libvips/conversion/im_ri2c.c @@ -97,7 +97,7 @@ join_buffer( PEL **p, PEL *q, int n, IMAGE *im ) * * Compose two real images to make a complex image. If either @in1 or @in2 are * %IM_BANDFMT_DOUBLE, @out is %IM_BANDFMT_DPCOMPLEX. Otherwise @out is - * %IM_BANDFMT_COMPLEX. @in1 becomes the real component fo @out and @in2 the + * %IM_BANDFMT_COMPLEX. @in1 becomes the real component of @out and @in2 the * imaginary. * * If the number of bands differs, one of the images @@ -105,10 +105,6 @@ join_buffer( PEL **p, PEL *q, int n, IMAGE *im ) * one-band image by joining n copies of the one-band image together, and then * the two n-band images are operated upon. * - * The two input images are cast up to the smallest common type (see table - * Smallest common format in - * arithmetic). - * * See also: im_c2real(), im_c2imag(). * * Returns: 0 on success, -1 on error @@ -141,7 +137,7 @@ im_ri2c( IMAGE *in1, IMAGE *in2, IMAGE *out ) if( im_open_local_array( out, t, 4, "im_ri2c", "p" ) || im_clip2fmt( in1, t[0], fmt ) || im_clip2fmt( in2, t[1], fmt ) || - im__bandalike( t[0], t[1], t[2], t[3] ) ) + im__bandalike( "im_ri2c", t[0], t[1], t[2], t[3] ) ) return( -1 ); /* Remember to NULL-terminate. diff --git a/libvips/include/vips/internal.h b/libvips/include/vips/internal.h index 63084901..43cf6047 100644 --- a/libvips/include/vips/internal.h +++ b/libvips/include/vips/internal.h @@ -151,15 +151,17 @@ char *im__gslist_gvalue_get( const GSList *list ); void im__buffer_init( void ); -int im__bandup( IMAGE *in, IMAGE *out, int n ); -int im__bandalike( IMAGE *in1, IMAGE *in2, IMAGE *out1, IMAGE *out2 ); +int im__bandup( const char *domain, IMAGE *in, IMAGE *out, int n ); +int im__bandalike_vec( const char *domain, IMAGE **in, IMAGE **out, int n ); +int im__bandalike( const char *domain, + IMAGE *in1, IMAGE *in2, IMAGE *out1, IMAGE *out2 ); int im__formatalike_vec( IMAGE **in, IMAGE **out, int n ); int im__formatalike( IMAGE *in1, IMAGE *in2, IMAGE *out1, IMAGE *out2 ); -int im__arith_binary( const char *name, +int im__arith_binary( const char *domain, IMAGE *in1, IMAGE *in2, IMAGE *out, int format_table[10], im_wrapmany_fn fn, void *b ); -int im__arith_binary_const( const char *name, +int im__arith_binary_const( const char *domain, IMAGE *in, IMAGE *out, int n, double *c, VipsBandFmt vfmt, int format_table[10], diff --git a/libvips/include/vips/morphology.h b/libvips/include/vips/morphology.h index 658babc8..1ec61c16 100644 --- a/libvips/include/vips/morphology.h +++ b/libvips/include/vips/morphology.h @@ -37,15 +37,15 @@ extern "C" { #endif /*__cplusplus*/ -int im_dilate( IMAGE *in, IMAGE *out, INTMASK *m ); -int im_erode( IMAGE *in, IMAGE *out, INTMASK *m ); +int im_dilate( IMAGE *in, IMAGE *out, INTMASK *mask ); +int im_erode( IMAGE *in, IMAGE *out, INTMASK *mask ); -int im_rank( IMAGE *in, IMAGE *out, int xsize, int ysize, int order ); +int im_rank( IMAGE *in, IMAGE *out, int width, int height, int index ); int im_rank_image( IMAGE **in, IMAGE *out, int n, int index ); int im_maxvalue( IMAGE **in, IMAGE *out, int n ); int im_cntlines( IMAGE *im, double *nolines, int flag ); -int im_zerox( IMAGE *in, IMAGE *out, int flag ); +int im_zerox( IMAGE *in, IMAGE *out, int sign ); int im_profile( IMAGE *in, IMAGE *out, int dir ); int im_label_regions( IMAGE *test, IMAGE *mask, int *segments ); diff --git a/libvips/inplace/im_draw_image.c b/libvips/inplace/im_draw_image.c index acc27035..9f09c9cc 100644 --- a/libvips/inplace/im_draw_image.c +++ b/libvips/inplace/im_draw_image.c @@ -89,7 +89,7 @@ im__inplace_base( const char *domain, /* Cast sub to match main in bands and format. */ if( im_open_local_array( out, t, 2, domain, "p" ) || - im__bandup( sub, t[0], main->Bands ) || + im__bandup( domain, sub, t[0], main->Bands ) || im_clip2fmt( t[0], t[1], main->BandFmt ) ) return( NULL ); diff --git a/libvips/iofuncs/check.c b/libvips/iofuncs/check.c index b3f36468..8257a659 100644 --- a/libvips/iofuncs/check.c +++ b/libvips/iofuncs/check.c @@ -711,7 +711,7 @@ int im_check_bands( const char *domain, IMAGE *im, int bands ) { if( im->Bands != bands ) { - im_error( domain, _( "image must %d bands" ), bands ); + im_error( domain, _( "image must have %d bands" ), bands ); return( -1 ); } @@ -735,7 +735,8 @@ int im_check_bands_1or3( const char *domain, IMAGE *im ) { if( im->Bands != 1 && im->Bands != 3 ) { - im_error( domain, "%s", _( "image must one or three bands" ) ); + im_error( domain, "%s", + _( "image must have one or three bands" ) ); return( -1 ); } diff --git a/libvips/morphology/im_rank.c b/libvips/morphology/im_rank.c index 8be9e032..536a4573 100644 --- a/libvips/morphology/im_rank.c +++ b/libvips/morphology/im_rank.c @@ -70,7 +70,7 @@ typedef struct { IMAGE *in, *out; /* Images we run */ int xsize, ysize; /* Window size */ - int order; /* Element select */ + int index; /* Element select */ int n; /* xsize * ysize */ } RankInfo; @@ -142,7 +142,7 @@ rank_start( IMAGE *out, void *a, void *b ) d += ls; \ } \ \ - /* Rearrange sort[] to make the order-th element the order-th + /* Rearrange sort[] to make the index-th element the index-th * smallest, adapted from Numerical Recipes in C. */ \ lower = 0; /* Range we know the result lies in */ \ @@ -202,14 +202,14 @@ rank_start( IMAGE *out, void *a, void *b ) \ /* Move to partition with the kth element. */ \ - if( j >= rnk->order ) \ + if( j >= rnk->index ) \ upper = j - 1; \ - if( j <= rnk->order ) \ + if( j <= rnk->index ) \ lower = i; \ } \ } \ \ - q[x] = sort[rnk->order]; \ + q[x] = sort[rnk->index]; \ } \ } @@ -320,9 +320,9 @@ rank_gen( REGION *or, void *vseq, void *a, void *b ) ls = IM_REGION_LSKIP( ir ) / IM_IMAGE_SIZEOF_ELEMENT( in ); for( y = to; y < bo; y++ ) { - if( rnk->order == 0 ) + if( rnk->index == 0 ) SWITCH( LOOP_MIN ) - else if( rnk->order == rnk->n - 1 ) + else if( rnk->index == rnk->n - 1 ) SWITCH( LOOP_MAX ) else SWITCH( LOOP_SELECT ) } @@ -333,7 +333,7 @@ rank_gen( REGION *or, void *vseq, void *a, void *b ) /* Rank filter. */ int -im_rank_raw( IMAGE *in, IMAGE *out, int xsize, int ysize, int order ) +im_rank_raw( IMAGE *in, IMAGE *out, int xsize, int ysize, int index ) { RankInfo *rnk; @@ -342,7 +342,7 @@ im_rank_raw( IMAGE *in, IMAGE *out, int xsize, int ysize, int order ) im_check_noncomplex( "im_rank", in ) ) return( -1 ); if( xsize > 1000 || ysize > 1000 || xsize <= 0 || ysize <= 0 || - order < 0 || order > xsize * ysize - 1 ) { + index < 0 || index > xsize * ysize - 1 ) { im_error( "im_rank", "%s", _( "bad parameters" ) ); return( -1 ); } @@ -355,7 +355,7 @@ im_rank_raw( IMAGE *in, IMAGE *out, int xsize, int ysize, int order ) rnk->out = out; rnk->xsize = xsize; rnk->ysize = ysize; - rnk->order = order; + rnk->index = index; rnk->n = xsize * ysize; /* Prepare output. Consider a 7x7 window and a 7x7 image --- the output @@ -394,12 +394,12 @@ im_rank_raw( IMAGE *in, IMAGE *out, int xsize, int ysize, int order ) * @out: output image * @width: window width * @height: window height - * @order: select pixel + * @index: select pixel * * im_rank() does rank filtering on an image. A window of size @width by * @height is passed over the image. At each position, the pixels inside the - * window are sorted into ascending order and the pixel at position @order is - * output. @order numbers from 0. + * window are sorted into ascending order and the pixel at position @index is + * output. @index numbers from 0. * * It works for any non-complex image type, with any number of bands. * The input is expanded by copying edge pixels before performing the @@ -418,7 +418,7 @@ im_rank_raw( IMAGE *in, IMAGE *out, int xsize, int ysize, int order ) * Returns: 0 on success, -1 on error */ int -im_rank( IMAGE *in, IMAGE *out, int width, int height, int order ) +im_rank( IMAGE *in, IMAGE *out, int width, int height, int index ) { IMAGE *t1; @@ -426,7 +426,7 @@ im_rank( IMAGE *in, IMAGE *out, int width, int height, int order ) im_embed( in, t1, 1, width / 2, height / 2, in->Xsize + width - 1, in->Ysize + height - 1 ) || - im_rank_raw( t1, out, width, height, order ) ) + im_rank_raw( t1, out, width, height, index ) ) return( -1 ); out->Xoffset = 0; diff --git a/libvips/morphology/im_rank_image.c b/libvips/morphology/im_rank_image.c index e486e24d..c9e32de1 100644 --- a/libvips/morphology/im_rank_image.c +++ b/libvips/morphology/im_rank_image.c @@ -5,6 +5,7 @@ * 10/11/10 * - gtkdoc * - cleanups + * - any mix of formats and bands */ /* @@ -43,6 +44,7 @@ #include #include +#include #ifdef WITH_DMALLOC #include @@ -63,7 +65,7 @@ static Rank * rank_new( IMAGE **in, IMAGE *out, int n, int index ) { Rank *rank; - int i; + IMAGE **t; if( !(rank = IM_NEW( out, Rank )) ) return( NULL ); @@ -71,10 +73,17 @@ rank_new( IMAGE **in, IMAGE *out, int n, int index ) rank->n = n; rank->index = index; rank->out = out; - if( !(rank->in = IM_ARRAY( out, n + 1, IMAGE * )) ) + if( !(t = IM_ARRAY( out, n, IMAGE * )) || + !(rank->in = IM_ARRAY( out, n + 1, IMAGE * )) ) + return( NULL ); + + /* Cast inputs up to a common format, common bands. + */ + if( im_open_local_array( out, rank->in, n, "im_rank_image", "p" ) || + im_open_local_array( out, rank->in, n, "im_rank_image", "p" ) || + im__bandalike_vec( "im_rank_image", in, t, n ) || + im__formatalike_vec( t, rank->in, n ) ) return( NULL ); - for( i = 0; i < n; i++ ) - rank->in[i] = in[i]; rank->in[n] = NULL; return( rank ); @@ -270,23 +279,27 @@ rank_gen( REGION *or, void *vseq, void *a, void *b ) * @in: input image array * @out: output image * @n: number of input images - * @order: select pixel + * @index: select pixel * - * im_rank_image() sorts the input images pixel-wise, then outputs an image - * in which each pixel is selected from the sorted list by the - * @order parameter. For example, if @order + * im_rank_image() sorts the images @in pixel-wise, then outputs an + * image in which each pixel is selected from the sorted list by the + * @index parameter. For example, if @index * is zero, then each output pixel will be the minimum of all the * corresponding input pixels. * - * It works for any uncoded, non-complex image type. All input images must - * match in size, format, and number of bands. + * It works for any uncoded, non-complex image type. Images are cast up to the + * smallest common-format. + * + * Any image can have either 1 band or n bands, where n is the same for all + * the non-1-band images. Single band images are then effectively copied to + * make n-band images. * * See also: im_rank(), im_maxvalue(). * * Returns: 0 on success, -1 on error */ int -im_rank_image( IMAGE **in, IMAGE *out, int n, int order ) +im_rank_image( IMAGE **in, IMAGE *out, int n, int index ) { int i; Rank *rank; @@ -295,7 +308,7 @@ im_rank_image( IMAGE **in, IMAGE *out, int n, int order ) im_error( "im_rank_image", "%s", _( "zero input images!" ) ); return( -1 ); } - if( order < 0 || order > n - 1 ) { + if( index < 0 || index > n - 1 ) { im_error( "im_rank_image", _( "index should be in range 0 - %d" ), n - 1 ); return( -1 ); @@ -306,12 +319,10 @@ im_rank_image( IMAGE **in, IMAGE *out, int n, int order ) if( im_pincheck( in[i] ) || im_check_uncoded( "im_rank_image", in[i] ) || im_check_noncomplex( "im_rank_image", in[i] ) || - im_check_size_same( "im_rank_image", in[i], in[0] ) || - im_check_format_same( "im_rank_image", in[i], in[0] ) || - im_check_bands_same( "im_rank_image", in[i], in[0] ) ) + im_check_size_same( "im_rank_image", in[i], in[0] ) ) return( -1 ); - if( !(rank = rank_new( in, out, n, order )) || + if( !(rank = rank_new( in, out, n, index )) || im_cp_desc_array( out, rank->in ) || im_demand_hint_array( out, IM_THINSTRIP, rank->in ) || im_generate( out, @@ -327,16 +338,17 @@ im_rank_image( IMAGE **in, IMAGE *out, int n, int order ) * @out: output image * @n: number of input images * - * im_maxvalue() sorts the input images pixel-wise, then outputs an image - * in which each pixel is - * @order parameter. For example, if @order - * is zero, then each output pixel will be the minimum of all the - * corresponding input pixels. + * im_maxvalue() is a convenience function over im_rank_image(). It sorts the + * input images pixel-wise, then outputs an image + * in which each pixel is the maximum of all the corresponding input images. + * It works for any uncoded, non-complex image type. Images are cast up to the + * smallest common-format. * - * It works for any uncoded, non-complex image type. All input images must - * match in size, format, and number of bands. + * Any image can have either 1 band or n bands, where n is the same for all + * the non-1-band images. Single band images are then effectively copied to + * make n-band images. * - * See also: im_rank(), im_maxvalue(). + * See also: im_rank_image(). * * Returns: 0 on success, -1 on error */ diff --git a/libvips/morphology/im_zerox.c b/libvips/morphology/im_zerox.c index 7365c6e3..09b4bd44 100644 --- a/libvips/morphology/im_zerox.c +++ b/libvips/morphology/im_zerox.c @@ -137,7 +137,7 @@ zerox_gen( REGION *or, void *seq, void *a, void *b ) * Returns: 0 on success, -1 on error */ int -im_zerox( IMAGE *in, IMAGE *out, int flag ) +im_zerox( IMAGE *in, IMAGE *out, int sign ) { IMAGE *t1; diff --git a/libvips/relational/im_blend.c b/libvips/relational/im_blend.c index f38ccfeb..afb2d2f5 100644 --- a/libvips/relational/im_blend.c +++ b/libvips/relational/im_blend.c @@ -378,7 +378,7 @@ im_blend( IMAGE *c, IMAGE *a, IMAGE *b, IMAGE *out ) /* Make a and b match in bands and format. */ if( im__formatalike( a, b, t[2], t[3] ) || - im__bandalike( t[2], t[3], t[4], t[5] ) ) + im__bandalike( "im_blend", t[2], t[3], t[4], t[5] ) ) return( -1 ); if( blend( c, t[4], t[5], t[6] ) ) diff --git a/libvips/relational/im_ifthenelse.c b/libvips/relational/im_ifthenelse.c index 618ac8d0..d03e72ca 100644 --- a/libvips/relational/im_ifthenelse.c +++ b/libvips/relational/im_ifthenelse.c @@ -216,7 +216,7 @@ im_ifthenelse( IMAGE *c, IMAGE *a, IMAGE *b, IMAGE *out ) * special-case this in code above ^^^ for speed. */ if( im__formatalike( a, b, t[0], t[1] ) || - im__bandalike( t[0], t[1], t[2], t[3] ) ) + im__bandalike( "im_ifthenelse", t[0], t[1], t[2], t[3] ) ) return( -1 ); /* If c is not uchar, do (!=0) to make a uchar image.