From 79153081556cad89996b4a348611f6f8bf751eaf Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 25 Sep 2014 09:58:51 +0100 Subject: [PATCH] test for bandrank and bandmean --- libvips/conversion/bandrank.c | 23 +++++++++----- python/test_conversion.py | 56 ++++++++++++++++++++++++++--------- 2 files changed, 57 insertions(+), 22 deletions(-) diff --git a/libvips/conversion/bandrank.c b/libvips/conversion/bandrank.c index 071c1d99..940bd3f5 100644 --- a/libvips/conversion/bandrank.c +++ b/libvips/conversion/bandrank.c @@ -62,7 +62,7 @@ typedef struct _VipsBandrank { /* The input images. */ - VipsArea *in; + VipsArrayImage *in; int index; /* Pick out this one */ } VipsBandrank; @@ -178,27 +178,34 @@ vips_bandrank_build( VipsObject *object ) VipsBandrank *bandrank = (VipsBandrank *) object; if( bandrank->in ) { + int n; + VipsImage **in = vips_array_image_get( bandrank->in, &n ); VipsImage **band = (VipsImage **) - vips_object_local_array( object, bandrank->in->n ); + vips_object_local_array( object, n ); - if( bandrank->in->n == 1 ) + int i; + + for( i = 0; i < n; i++ ) + if( vips_check_noncomplex( class->nickname, in[i] ) ) + return( -1 ); + + if( n == 1 ) return( vips_bandary_copy( bandary ) ); /* We need to keep one band element for every input image * on the stack. */ - if( sizeof( double ) * bandrank->in->n > SORT_BUFFER ) { + if( sizeof( double ) * n > SORT_BUFFER ) { vips_error( class->nickname, "%s", _( "too many input images" ) ); return( -1 ); } - if( vips__bandalike_vec( class->nickname, - bandrank->in->data, band, bandrank->in->n, 0 ) ) + if( vips__bandalike_vec( class->nickname, in, band, n, 0 ) ) return( -1 ); bandary->in = band; - bandary->n = bandrank->in->n; + bandary->n = n; bandary->out_bands = band[0]->Bands; if( bandrank->index == -1 ) @@ -281,7 +288,7 @@ vips_bandrankv( VipsImage **in, VipsImage **out, int n, va_list ap ) * image in which each band element is selected from the sorted list by the * @index parameter. For example, if @index * is zero, then each output band element will be the minimum of all the - * corresponding input band element. + * corresponding input band elements. * * By default, @index is -1, meaning pick the median value. * diff --git a/python/test_conversion.py b/python/test_conversion.py index d3637e75..a044a7e8 100755 --- a/python/test_conversion.py +++ b/python/test_conversion.py @@ -44,7 +44,7 @@ class TestConversion(unittest.TestCase): # run a function on an image and on a single pixel, the results # should match - def run_cmp(self, message, im, x, y, fn): + def run_cmp_unary(self, message, im, x, y, fn): a = im.getpoint(x, y) v1 = fn(a) im2 = fn(im) @@ -53,7 +53,7 @@ class TestConversion(unittest.TestCase): # run a function on a pair of images and on a pair of pixels, the results # should match - def run_cmp2(self, message, left, right, x, y, fn): + def run_cmp_binary(self, message, left, right, x, y, fn): a = left.getpoint(x, y) b = right.getpoint(x, y) v1 = fn(a, b) @@ -63,20 +63,25 @@ class TestConversion(unittest.TestCase): # run a function on a pair of images # 50,50 and 10,10 should have different values on the test image - def run_test2(self, message, left, right, fn): - self.run_cmp2(message, left, right, 50, 50, fn) - self.run_cmp2(message, left, right, 10, 10, fn) + def run_testbinary(self, message, left, right, fn): + self.run_cmp_binary(message, left, right, 50, 50, fn) + self.run_cmp_binary(message, left, right, 10, 10, fn) # run a function on an image, # 50,50 and 10,10 should have different values on the test image def run_testunary(self, message, im, fn): - self.run_cmp(message, im, 50, 50, fn) - self.run_cmp(message, im, 10, 10, fn) + self.run_cmp_unary(message, im, 50, 50, fn) + self.run_cmp_unary(message, im, 10, 10, fn) def run_unary(self, images, fn, fmt = all_formats): - [self.run_testunary(fn.func_name + ' image', x.cast(y), fn) + [self.run_testunary(fn.func_name + (' %s' % y), x.cast(y), fn) for x in images for y in fmt] + def run_binary(self, images, fn, fmt = all_formats): + [self.run_testbinary(fn.func_name + (' %s %s' % (y, z)), + x.cast(y), x.cast(z), fn) + for x in images for y in fmt for z in fmt] + def setUp(self): im = Vips.Image.mask_ideal(100, 100, 0.5, reject = True, optical = True) self.colour = im * [1, 2, 3] + [2, 3, 4] @@ -111,13 +116,36 @@ class TestConversion(unittest.TestCase): self.run_unary([self.colour], band_eor, fmt = int_formats) def test_bandjoin(self): - im2 = Vips.Image.bandjoin([self.colour, self.mono]) + def bandjoin(x, y): + if isinstance(x, Vips.Image) and isinstance(y, Vips.Image): + return x.bandjoin2(y) + else: + return x + y - self.assertEqual(im2.bands, self.colour.bands + self.mono.bands) - v = im2.getpoint(10, 10) - self.assertAlmostEqualObjects(v, [2, 3, 4, 3]) - v = im2.getpoint(50, 50) - self.assertAlmostEqualObjects(v, [3, 5, 7, 5]) + self.run_binary(self.all_images, bandjoin) + + def test_bandmean(self): + def bandmean(x): + if isinstance(x, Vips.Image): + return x.bandmean() + else: + return [sum(x) / len(x)] + + self.run_unary([self.colour], bandmean, fmt = noncomplex_formats) + + def test_bandrank(self): + def median(x, y): + joined = zip(x, y) + map(lambda x: list(x).sort(), joined) + return map(lambda x: x[len(x) / 2], joined) + + def bandrank(x, y): + if isinstance(x, Vips.Image) and isinstance(y, Vips.Image): + return Vips.Image.bandrank([x, y]) + else: + return median(x, y) + + self.run_binary(self.all_images, bandrank, fmt = noncomplex_formats) if __name__ == '__main__': unittest.main()