better shrinkv for int32 types

use double as the sum type to prevent int overflow
This commit is contained in:
John Cupitt 2019-08-06 16:55:10 +01:00
parent 25b6f2fcf1
commit 6ba34e479e
2 changed files with 16 additions and 15 deletions

View File

@ -45,6 +45,8 @@
* - rename yshrink -> vshrink for greater consistency * - rename yshrink -> vshrink for greater consistency
* 7/3/17 * 7/3/17
* - add a seq line cache * - add a seq line cache
* 6/8/19
* - use a double sum buffer for int32 types
*/ */
/* /*
@ -180,9 +182,9 @@ vips_shrinkv_add_line( VipsShrinkv *shrink, VipsShrinkvSequence *seq,
case VIPS_FORMAT_SHORT: case VIPS_FORMAT_SHORT:
ADD( int, short ); break; ADD( int, short ); break;
case VIPS_FORMAT_UINT: case VIPS_FORMAT_UINT:
ADD( int, unsigned int ); break; ADD( double, unsigned int ); break;
case VIPS_FORMAT_INT: case VIPS_FORMAT_INT:
ADD( int, int ); break; ADD( double, int ); break;
case VIPS_FORMAT_FLOAT: case VIPS_FORMAT_FLOAT:
ADD( double, float ); break; ADD( double, float ); break;
case VIPS_FORMAT_DOUBLE: case VIPS_FORMAT_DOUBLE:
@ -199,13 +201,12 @@ vips_shrinkv_add_line( VipsShrinkv *shrink, VipsShrinkvSequence *seq,
/* Integer average. /* Integer average.
*/ */
#define IAVG( TYPE, BTYPE ) { \ #define IAVG( ACC_TYPE, TYPE ) { \
int * restrict sum = (int *) seq->sum; \ ACC_TYPE * restrict sum = (ACC_TYPE *) seq->sum; \
TYPE * restrict q = (TYPE *) out; \ TYPE * restrict q = (TYPE *) out; \
\ \
for( x = 0; x < sz; x++ ) \ for( x = 0; x < sz; x++ ) \
q[x] = ((BTYPE) sum[x] + shrink->vshrink / 2) / \ q[x] = (sum[x] + shrink->vshrink / 2) / shrink->vshrink; \
shrink->vshrink; \
} }
/* Float average. /* Float average.
@ -235,17 +236,17 @@ vips_shrinkv_write_line( VipsShrinkv *shrink, VipsShrinkvSequence *seq,
VipsPel *out = VIPS_REGION_ADDR( or, left, top ); VipsPel *out = VIPS_REGION_ADDR( or, left, top );
switch( resample->in->BandFmt ) { switch( resample->in->BandFmt ) {
case VIPS_FORMAT_UCHAR: case VIPS_FORMAT_UCHAR:
IAVG( unsigned char, int ); break; IAVG( int, unsigned char ); break;
case VIPS_FORMAT_CHAR: case VIPS_FORMAT_CHAR:
IAVG( char, int ); break; IAVG( int, char ); break;
case VIPS_FORMAT_USHORT: case VIPS_FORMAT_USHORT:
IAVG( unsigned short, int ); break; IAVG( int, unsigned short ); break;
case VIPS_FORMAT_SHORT: case VIPS_FORMAT_SHORT:
IAVG( short, int ); break; IAVG( int, short ); break;
case VIPS_FORMAT_UINT: case VIPS_FORMAT_UINT:
IAVG( unsigned int, guint64 ); break; IAVG( double, unsigned int ); break;
case VIPS_FORMAT_INT: case VIPS_FORMAT_INT:
IAVG( int, gint64 ); break; IAVG( double, int ); break;
case VIPS_FORMAT_FLOAT: case VIPS_FORMAT_FLOAT:
FAVG( float ); break; FAVG( float ); break;
case VIPS_FORMAT_DOUBLE: case VIPS_FORMAT_DOUBLE: