From 4aeedd971131ee86005e236fe1b6cfdcbd128cd6 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 30 Jan 2020 16:53:18 +0000 Subject: [PATCH] add "nearest" region shrink --- libvips/include/vips/region.h | 2 ++ libvips/iofuncs/enumtypes.c | 1 + libvips/iofuncs/region.c | 25 +++++++++++++++++++------ test/test-suite/test_foreign.py | 5 ++++- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/libvips/include/vips/region.h b/libvips/include/vips/region.h index bcce3c47..d52a3fa7 100644 --- a/libvips/include/vips/region.h +++ b/libvips/include/vips/region.h @@ -62,6 +62,7 @@ extern "C" { * @VIPS_REGION_SHRINK_MODE: use the mode * @VIPS_REGION_SHRINK_MAX: use the maximum * @VIPS_REGION_SHRINK_MIN: use the minimum + * @VIPS_REGION_SHRINK_NEAREST: use the top-left pixel * * How to calculate the output pixels when shrinking a 2x2 region. */ @@ -71,6 +72,7 @@ typedef enum { VIPS_REGION_SHRINK_MODE, VIPS_REGION_SHRINK_MAX, VIPS_REGION_SHRINK_MIN, + VIPS_REGION_SHRINK_NEAREST, VIPS_REGION_SHRINK_LAST } VipsRegionShrink; diff --git a/libvips/iofuncs/enumtypes.c b/libvips/iofuncs/enumtypes.c index 2f571331..767a43f9 100644 --- a/libvips/iofuncs/enumtypes.c +++ b/libvips/iofuncs/enumtypes.c @@ -905,6 +905,7 @@ vips_region_shrink_get_type( void ) {VIPS_REGION_SHRINK_MODE, "VIPS_REGION_SHRINK_MODE", "mode"}, {VIPS_REGION_SHRINK_MAX, "VIPS_REGION_SHRINK_MAX", "max"}, {VIPS_REGION_SHRINK_MIN, "VIPS_REGION_SHRINK_MIN", "min"}, + {VIPS_REGION_SHRINK_NEAREST, "VIPS_REGION_SHRINK_NEAREST", "nearest"}, {VIPS_REGION_SHRINK_LAST, "VIPS_REGION_SHRINK_LAST", "last"}, {0, NULL, NULL} }; diff --git a/libvips/iofuncs/region.c b/libvips/iofuncs/region.c index ab201ff5..a59a5d9a 100644 --- a/libvips/iofuncs/region.c +++ b/libvips/iofuncs/region.c @@ -1283,8 +1283,6 @@ vips_region_shrink_uncoded_mean( VipsRegion *from, tq[z] = v[index]; \ } \ \ - /* Move on two pels in input. \ - */ \ p += ps << 1; \ q += ps; \ } \ @@ -1303,8 +1301,6 @@ vips_region_shrink_uncoded_mean( VipsRegion *from, ); \ } \ \ - /* Move on two pels in input. \ - */ \ p += ps << 1; \ q += ps; \ } \ @@ -1323,8 +1319,20 @@ vips_region_shrink_uncoded_mean( VipsRegion *from, ); \ } \ \ - /* Move on two pels in input. \ - */ \ + p += ps << 1; \ + q += ps; \ + } \ +} + +#define SHRINK_TYPE_NEAREST( TYPE ) { \ + for( x = 0; x < target->width; x++ ) { \ + TYPE *tp = (TYPE *) p; \ + TYPE *tp1 = (TYPE *) (p + ls); \ + TYPE *tq = (TYPE *) q; \ + \ + for( z = 0; z < nb; z++ ) \ + tq[z] = tp[z]; \ + \ p += ps << 1; \ q += ps; \ } \ @@ -1377,6 +1385,7 @@ VIPS_REGION_SHRINK( MAX ); VIPS_REGION_SHRINK( MIN ); VIPS_REGION_SHRINK( MODE ); VIPS_REGION_SHRINK( MEDIAN ); +VIPS_REGION_SHRINK( NEAREST ); /* Generate area @target in @to using pixels in @from. Non-complex. */ @@ -1405,6 +1414,10 @@ vips_region_shrink_uncoded( VipsRegion *from, vips_region_shrink_uncoded_MIN( from, to, target ); break; + case VIPS_REGION_SHRINK_NEAREST: + vips_region_shrink_uncoded_NEAREST( from, to, target ); + break; + default: g_assert_not_reached(); } diff --git a/test/test-suite/test_foreign.py b/test/test-suite/test_foreign.py index 4c18af71..517f3379 100644 --- a/test/test-suite/test_foreign.py +++ b/test/test-suite/test_foreign.py @@ -419,11 +419,14 @@ class TestForeign: assert a.height == b.height assert a.avg() == b.avg() - # region-shrink added in 8.7 x = pyvips.Image.new_from_file(TIF_FILE) buf = x.tiffsave_buffer(tile=True, pyramid=True, region_shrink="mean") buf = x.tiffsave_buffer(tile=True, pyramid=True, region_shrink="mode") buf = x.tiffsave_buffer(tile=True, pyramid=True, region_shrink="median") + buf = x.tiffsave_buffer(tile=True, pyramid=True, region_shrink="max") + buf = x.tiffsave_buffer(tile=True, pyramid=True, region_shrink="min") + buf = x.tiffsave_buffer(tile=True, pyramid=True, + region_shrink="nearest") @skip_if_no("magickload") def test_magickload(self):