From 3145b7aed53de4b2c46ae725955c3760191da273 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Fri, 1 Oct 2010 11:03:11 +0000 Subject: [PATCH] added complex convolution --- ChangeLog | 1 + TODO | 4 ---- libvips/convolution/im_compass.c | 5 ----- libvips/convolution/im_conv.c | 16 +++++++++++----- libvips/convolution/im_conv_f.c | 16 +++++++++------- libvips/convolution/im_convsep.c | 14 ++++++++------ libvips/convolution/im_convsep_f.c | 14 ++++++++------ 7 files changed, 37 insertions(+), 33 deletions(-) diff --git a/ChangeLog b/ChangeLog index bd9ce73a..5837d7ee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -30,6 +30,7 @@ - added im_draw_point(), moved im_plotpoint() to deprecated - added im_read_point(), now partial, moved im_readpoint() to deprecated - added im_draw_smudge(), moved im_smudge() / im_smear() to deprecated +- convolution functions support complex images 12/5/10 started 7.22.2 - the conditional image of ifthenelse can be any format, a (!=0) is added if diff --git a/TODO b/TODO index b6817458..7fdd523c 100644 --- a/TODO +++ b/TODO @@ -1,9 +1,5 @@ - check gtk-doc output -- convsep / conv need to be able to do COMPLEX - - just double the bands - - maybe im_draw_smudge() is too slow :-( also, we had a sanity failure with it, argh diff --git a/libvips/convolution/im_compass.c b/libvips/convolution/im_compass.c index c60262eb..309445ba 100644 --- a/libvips/convolution/im_compass.c +++ b/libvips/convolution/im_compass.c @@ -40,11 +40,6 @@ #endif /*HAVE_CONFIG_H*/ #include -#include -#include -#include -#include - #include #ifdef WITH_DMALLOC diff --git a/libvips/convolution/im_conv.c b/libvips/convolution/im_conv.c index c2bb0951..592a911f 100644 --- a/libvips/convolution/im_conv.c +++ b/libvips/convolution/im_conv.c @@ -53,6 +53,8 @@ * - more cleanups * 23/08/10 * - add a special case for 3x3 masks, about 20% faster + * 1/10/10 + * - support complex (just double the bands) */ /* @@ -331,7 +333,8 @@ conv_gen( REGION *or, void *vseq, void *a, void *b ) int le = r->left; int to = r->top; int bo = IM_RECT_BOTTOM( r ); - int sz = IM_REGION_N_ELEMENTS( or ); + int sz = IM_REGION_N_ELEMENTS( or ) * + (vips_bandfmt_iscomplex( in->BandFmt ) ? 2 : 1); int x, y, z, i; @@ -394,10 +397,12 @@ conv_gen( REGION *or, void *vseq, void *a, void *b ) break; case IM_BANDFMT_FLOAT: + case IM_BANDFMT_COMPLEX: CONV_FLOAT( float ); break; case IM_BANDFMT_DOUBLE: + case IM_BANDFMT_DPCOMPLEX: CONV_FLOAT( double ); break; @@ -497,7 +502,8 @@ conv3x3_gen( REGION *or, void *vseq, void *a, void *b ) int le = r->left; int to = r->top; int bo = IM_RECT_BOTTOM( r ); - int sz = IM_REGION_N_ELEMENTS( or ); + int sz = IM_REGION_N_ELEMENTS( or ) * + (vips_bandfmt_iscomplex( in->BandFmt ) ? 2 : 1); int bands = in->Bands; Rect s; @@ -545,10 +551,12 @@ conv3x3_gen( REGION *or, void *vseq, void *a, void *b ) break; case IM_BANDFMT_FLOAT: + case IM_BANDFMT_COMPLEX: CONV3x3_FLOAT( float ); break; case IM_BANDFMT_DOUBLE: + case IM_BANDFMT_DPCOMPLEX: CONV3x3_FLOAT( double ); break; @@ -570,7 +578,6 @@ im_conv_raw( IMAGE *in, IMAGE *out, INTMASK *mask ) */ if( im_piocheck( in, out ) || im_check_uncoded( "im_conv", in ) || - im_check_noncomplex( "im_conv", in ) || im_check_imask( "im_conv", mask ) ) return( -1 ); if( mask->scale == 0 ) { @@ -617,8 +624,7 @@ im_conv_raw( IMAGE *in, IMAGE *out, INTMASK *mask ) * @mask: convolution mask * * Convolve @in with @mask using integer arithmetic. The output image - * always has the same #VipsBandFmt as the input image. Non-complex images - * only. + * always has the same #VipsBandFmt as the input image. * * Each output pixel is * calculated as sigma[i]{pixel[i] * mask[i]} / scale + offset, where scale diff --git a/libvips/convolution/im_conv_f.c b/libvips/convolution/im_conv_f.c index 9b34d93c..cf467584 100644 --- a/libvips/convolution/im_conv_f.c +++ b/libvips/convolution/im_conv_f.c @@ -31,11 +31,13 @@ * - add restrict, though it doesn't seem to help gcc * - add mask-all-zero check * 13/11/09 - * - rename as im_conv_f() to make it easier to vips.c to make the + * - rename as im_conv_f() to make it easier for vips.c to make the * overloaded version * 3/2/10 * - gtkdoc * - more cleanups + * 1/10/10 + * - support complex (just double the bands) */ /* @@ -72,7 +74,6 @@ #include #include #include -#include #include @@ -241,7 +242,8 @@ conv_gen( REGION *or, void *vseq, void *a, void *b ) int le = r->left; int to = r->top; int bo = IM_RECT_BOTTOM(r); - int sz = IM_REGION_N_ELEMENTS( or ); + int sz = IM_REGION_N_ELEMENTS( or ) * + (vips_bandfmt_iscomplex( in->BandFmt ) ? 2 : 1); int x, y, z, i; @@ -292,12 +294,14 @@ conv_gen( REGION *or, void *vseq, void *a, void *b ) case IM_BANDFMT_INT: CONV_FLOAT( signed int, float ); break; case IM_BANDFMT_FLOAT: + case IM_BANDFMT_COMPLEX: CONV_FLOAT( float, float ); break; case IM_BANDFMT_DOUBLE: + case IM_BANDFMT_DPCOMPLEX: CONV_FLOAT( double, double ); break; default: - assert( 0 ); + g_assert( 0 ); } } @@ -313,7 +317,6 @@ im_conv_f_raw( IMAGE *in, IMAGE *out, DOUBLEMASK *mask ) */ if( im_piocheck( in, out ) || im_check_uncoded( "im_conv", in ) || - im_check_noncomplex( "im_conv", in ) || im_check_dmask( "im_conv", mask ) ) return( -1 ); if( mask->scale == 0 ) { @@ -360,8 +363,7 @@ im_conv_f_raw( IMAGE *in, IMAGE *out, DOUBLEMASK *mask ) * * Convolve @in with @mask using floating-point arithmetic. The output image * is always %IM_BANDFMT_FLOAT unless @in is %IM_BANDFMT_DOUBLE, in which case - * @out is also %IM_BANDFMT_DOUBLE. Non-complex images - * only. + * @out is also %IM_BANDFMT_DOUBLE. * * Each output pixel is * calculated as sigma[i]{pixel[i] * mask[i]} / scale + offset, where scale diff --git a/libvips/convolution/im_convsep.c b/libvips/convolution/im_convsep.c index da5da3cd..30dedccc 100644 --- a/libvips/convolution/im_convsep.c +++ b/libvips/convolution/im_convsep.c @@ -21,6 +21,8 @@ * 3/2/10 * - gtkdoc * - more cleanups + * 1/10/10 + * - support complex (just double the bands) */ /* @@ -57,7 +59,6 @@ #include #include #include -#include #include @@ -311,7 +312,8 @@ conv_gen( REGION *or, void *vseq, void *a, void *b ) int le = r->left; int to = r->top; int bo = IM_RECT_BOTTOM(r); - int osz = IM_REGION_N_ELEMENTS( or ); + int osz = IM_REGION_N_ELEMENTS( or ) * + (vips_bandfmt_iscomplex( in->BandFmt ) ? 2 : 1); Rect s; int lskip; @@ -350,14 +352,16 @@ conv_gen( REGION *or, void *vseq, void *a, void *b ) CONV_INT( signed int, IM_CLIP_NONE( sum, seq ) ); break; case IM_BANDFMT_FLOAT: + case IM_BANDFMT_COMPLEX: CONV_FLOAT( float ); break; case IM_BANDFMT_DOUBLE: + case IM_BANDFMT_DPCOMPLEX: CONV_FLOAT( double ); break; default: - assert( 0 ); + g_assert( 0 ); } } @@ -373,7 +377,6 @@ im_convsep_raw( IMAGE *in, IMAGE *out, INTMASK *mask ) */ if( im_piocheck( in, out ) || im_check_uncoded( "im_convsep", in ) || - im_check_noncomplex( "im_convsep", in ) || im_check_imask( "im_convsep", mask ) ) return( -1 ); if( mask->xsize != 1 && mask->ysize != 1 ) { @@ -423,8 +426,7 @@ im_convsep_raw( IMAGE *in, IMAGE *out, INTMASK *mask ) * * The mask must be 1xn or nx1 elements. * The output image - * always has the same #VipsBandFmt as the input image. Non-complex images - * only. + * always has the same #VipsBandFmt as the input image. * * The image is convolved twice: once with @mask and then again with @mask * rotated by 90 degrees. This is much faster for certain types of mask diff --git a/libvips/convolution/im_convsep_f.c b/libvips/convolution/im_convsep_f.c index 01e9ee8e..946827dc 100644 --- a/libvips/convolution/im_convsep_f.c +++ b/libvips/convolution/im_convsep_f.c @@ -14,6 +14,8 @@ * 3/2/10 * - gtkdoc * - more cleanups + * 1/10/10 + * - support complex (just double the bands) */ /* @@ -50,7 +52,6 @@ #include #include #include -#include #include @@ -223,7 +224,8 @@ conv_gen( REGION *or, void *vseq, void *a, void *b ) int le = r->left; int to = r->top; int bo = IM_RECT_BOTTOM(r); - int osz = IM_REGION_N_ELEMENTS( or ); + int osz = IM_REGION_N_ELEMENTS( or ) * + (vips_bandfmt_iscomplex( in->BandFmt ) ? 2 : 1); Rect s; int lskip; @@ -256,12 +258,14 @@ conv_gen( REGION *or, void *vseq, void *a, void *b ) case IM_BANDFMT_INT: CONV_FLOAT( signed int, float ); break; case IM_BANDFMT_FLOAT: + case IM_BANDFMT_COMPLEX: CONV_FLOAT( float, float ); break; case IM_BANDFMT_DOUBLE: + case IM_BANDFMT_DPCOMPLEX: CONV_FLOAT( double, double ); break; default: - assert( 0 ); + g_assert( 0 ); } } @@ -277,7 +281,6 @@ im_convsep_f_raw( IMAGE *in, IMAGE *out, DOUBLEMASK *mask ) */ if( im_piocheck( in, out ) || im_check_uncoded( "im_convsep_f", in ) || - im_check_noncomplex( "im_convsep_f", in ) || im_check_dmask( "im_convsep_f", mask ) ) return( -1 ); if( mask->xsize != 1 && mask->ysize != 1 ) { @@ -331,8 +334,7 @@ im_convsep_f_raw( IMAGE *in, IMAGE *out, DOUBLEMASK *mask ) * The mask must be 1xn or nx1 elements. * The output image * is always %IM_BANDFMT_FLOAT unless @in is %IM_BANDFMT_DOUBLE, in which case - * @out is also %IM_BANDFMT_DOUBLE. Non-complex images - * only. + * @out is also %IM_BANDFMT_DOUBLE. * * The image is convolved twice: once with @mask and then again with @mask * rotated by 90 degrees. This is much faster for certain types of mask