prevent int overflow for int pixels in shrinkh

by using double for an accumulator
This commit is contained in:
John Cupitt 2019-08-06 17:00:53 +01:00
parent 6ba34e479e
commit 5ddc154a81

View File

@ -6,6 +6,8 @@
* - reorganise loops, 30% faster, vectorisable * - reorganise loops, 30% faster, vectorisable
* 15/8/16 * 15/8/16
* - rename xshrink -> hshrink for greater consistency * - rename xshrink -> hshrink for greater consistency
* 6/8/19
* - use a double sum buffer for int32 types
*/ */
/* /*
@ -71,13 +73,13 @@ G_DEFINE_TYPE( VipsShrinkh, vips_shrinkh, VIPS_TYPE_RESAMPLE );
/* Integer shrink. /* Integer shrink.
*/ */
#define ISHRINK( TYPE, BANDS ) { \ #define ISHRINK( ACC_TYPE, TYPE, BANDS ) { \
TYPE * restrict p = (TYPE *) in; \ TYPE * restrict p = (TYPE *) in; \
TYPE * restrict q = (TYPE *) out; \ TYPE * restrict q = (TYPE *) out; \
\ \
for( x = 0; x < width; x++ ) { \ for( x = 0; x < width; x++ ) { \
for( b = 0; b < BANDS; b++ ) { \ for( b = 0; b < BANDS; b++ ) { \
int sum; \ ACC_TYPE sum; \
\ \
sum = 0; \ sum = 0; \
x1 = b; \ x1 = b; \
@ -137,26 +139,26 @@ vips_shrinkh_gen2( VipsShrinkh *shrink, VipsRegion *or, VipsRegion *ir,
*/ */
switch( bands ) { switch( bands ) {
case 1: case 1:
ISHRINK( unsigned char, 1 ); break; ISHRINK( int, unsigned char, 1 ); break;
case 3: case 3:
ISHRINK( unsigned char, 3 ); break; ISHRINK( int, unsigned char, 3 ); break;
case 4: case 4:
ISHRINK( unsigned char, 4 ); break; ISHRINK( int, unsigned char, 4 ); break;
default: default:
ISHRINK( unsigned char, bands ); break; ISHRINK( int, unsigned char, bands ); break;
} }
break; break;
case VIPS_FORMAT_CHAR: case VIPS_FORMAT_CHAR:
ISHRINK( char, bands ); break; ISHRINK( int, char, bands ); break;
case VIPS_FORMAT_USHORT: case VIPS_FORMAT_USHORT:
ISHRINK( unsigned short, bands ); break; ISHRINK( int, unsigned short, bands ); break;
case VIPS_FORMAT_SHORT: case VIPS_FORMAT_SHORT:
ISHRINK( short, bands ); break; ISHRINK( int, short, bands ); break;
case VIPS_FORMAT_UINT: case VIPS_FORMAT_UINT:
ISHRINK( unsigned int, bands ); break; ISHRINK( double, unsigned int, bands ); break;
case VIPS_FORMAT_INT: case VIPS_FORMAT_INT:
ISHRINK( int, bands ); break; ISHRINK( double, int, bands ); break;
case VIPS_FORMAT_FLOAT: case VIPS_FORMAT_FLOAT:
FSHRINK( float ); break; FSHRINK( float ); break;
case VIPS_FORMAT_DOUBLE: case VIPS_FORMAT_DOUBLE: