"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "libvips/resample/mapim.c" between
vips-8.10.6.tar.gz and vips-8.11.0.tar.gz

About: VIPS is a free image processing system (see also the GUI nip2).

mapim.c  (vips-8.10.6):mapim.c  (vips-8.11.0)
/* resample with an index image /* resample with an index image
* *
* 15/11/15 * 15/11/15
* - from affine.c * - from affine.c
* 12/8/18 * 12/8/18
* - prevent float->int overflow * - prevent float->int overflow
* - a bit quicker * - a bit quicker
* 17/12/18 * 17/12/18
* - we were not offsetting pixel fetches by window_offset * - we were not offsetting pixel fetches by window_offset
* 30/1/21 afontenot
* - avoid NaN
*/ */
/* /*
This file is part of VIPS. This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
skipping to change at line 81 skipping to change at line 83
} VipsMapim; } VipsMapim;
typedef VipsResampleClass VipsMapimClass; typedef VipsResampleClass VipsMapimClass;
G_DEFINE_TYPE( VipsMapim, vips_mapim, VIPS_TYPE_RESAMPLE ); G_DEFINE_TYPE( VipsMapim, vips_mapim, VIPS_TYPE_RESAMPLE );
/* Minmax of a line of pixels. Pass in a thing to convert back to int /* Minmax of a line of pixels. Pass in a thing to convert back to int
* coordinates. * coordinates.
*/ */
#define MINMAX( TYPE, CLIP_LOW, CLIP_HIGH ) { \ #define MINMAX( TYPE, CLIP ) { \
TYPE * restrict p1 = (TYPE *) p; \ TYPE * restrict p1 = (TYPE *) p; \
TYPE t_max_x = max_x; \ TYPE t_max_x = max_x; \
TYPE t_min_x = min_x; \ TYPE t_min_x = min_x; \
TYPE t_max_y = max_y; \ TYPE t_max_y = max_y; \
TYPE t_min_y = min_y; \ TYPE t_min_y = min_y; \
\ \
for( x = 0; x < r->width; x++ ) { \ for( x = 0; x < r->width; x++ ) { \
TYPE px = p1[0]; \ TYPE px = p1[0]; \
TYPE py = p1[1]; \ TYPE py = p1[1]; \
\ \
skipping to change at line 115 skipping to change at line 117
\ \
if( py > t_max_y ) \ if( py > t_max_y ) \
t_max_y = py; \ t_max_y = py; \
else if( py < t_min_y ) \ else if( py < t_min_y ) \
t_min_y = py; \ t_min_y = py; \
} \ } \
\ \
p1 += 2; \ p1 += 2; \
} \ } \
\ \
min_x = CLIP_LOW( t_min_x ); \ min_x = CLIP( t_min_x ); \
max_x = CLIP_HIGH( t_max_x ); \ max_x = CLIP( t_max_x ); \
min_y = CLIP_LOW( t_min_y ); \ min_y = CLIP( t_min_y ); \
max_y = CLIP_HIGH( t_max_y ); \ max_y = CLIP( t_max_y ); \
}
/* Minmax of a line of float pixels. We have to ignore NaN.
*/
#define FMINMAX( TYPE ) { \
TYPE * restrict p1 = (TYPE *) p; \
TYPE t_max_x = max_x; \
TYPE t_min_x = min_x; \
TYPE t_max_y = max_y; \
TYPE t_min_y = min_y; \
\
for( x = 0; x < r->width; x++ ) { \
TYPE px = p1[0]; \
TYPE py = p1[1]; \
\
if( !VIPS_ISNAN( px ) && \
!VIPS_ISNAN( py ) ) { \
if( first ) { \
t_min_x = px; \
t_max_x = px; \
t_min_y = py; \
t_max_y = py; \
\
first = FALSE; \
} \
else { \
if( px > t_max_x ) \
t_max_x = px; \
else if( px < t_min_x ) \
t_min_x = px; \
\
if( py > t_max_y ) \
t_max_y = py; \
else if( py < t_min_y ) \
t_min_y = py; \
} \
}\
\
p1 += 2; \
} \
\
if( !first ) { \
min_x = VIPS_CLIP( 0, floor( t_min_x ), VIPS_MAX_COORD ); \
max_x = VIPS_CLIP( 0, floor( t_max_x ), VIPS_MAX_COORD ); \
min_y = VIPS_CLIP( 0, floor( t_min_y ), VIPS_MAX_COORD ); \
max_y = VIPS_CLIP( 0, floor( t_max_y ), VIPS_MAX_COORD ); \
} \
} }
/* All the clippers. These vary with TYPE. /* All the clippers. These vary with TYPE.
*/ */
/* Clip a small (max val < VIPS_MAX_COORD) unsigned int type. /* Clip a small (max val < VIPS_MAX_COORD) unsigned int type.
*/ */
#define CLIP_UINT_SMALL( X ) (X) #define CLIP_UINT_SMALL( X ) (X)
/* Clip a small (max val < VIPS_MAX_COORD) signed int type. /* Clip a small (max val < VIPS_MAX_COORD) signed int type.
skipping to change at line 140 skipping to change at line 189
#define CLIP_SINT_SMALL( X ) VIPS_MAX( X, 0 ); #define CLIP_SINT_SMALL( X ) VIPS_MAX( X, 0 );
/* An unsigned int type larger than VIPS_MAX_COORD. Trim upper range. /* An unsigned int type larger than VIPS_MAX_COORD. Trim upper range.
*/ */
#define CLIP_UINT_LARGE( X ) VIPS_MIN( X, VIPS_MAX_COORD ); #define CLIP_UINT_LARGE( X ) VIPS_MIN( X, VIPS_MAX_COORD );
/* A large signed int. /* A large signed int.
*/ */
#define CLIP_SINT_LARGE( X ) VIPS_CLIP( 0, X, VIPS_MAX_COORD ); #define CLIP_SINT_LARGE( X ) VIPS_CLIP( 0, X, VIPS_MAX_COORD );
/* Float types must clip the range, and also round up or down at the extremes.
*/
#define CLIP_FLOAT_LOW( X ) VIPS_CLIP( 0, floor( X ), VIPS_MAX_COORD );
#define CLIP_FLOAT_HIGH( X ) VIPS_CLIP( 0, ceil( X ), VIPS_MAX_COORD );
/* Scan a region and find min/max in the two axes. /* Scan a region and find min/max in the two axes.
*/ */
static void static void
vips_mapim_region_minmax( VipsRegion *region, VipsRect *r, VipsRect *bounds ) vips_mapim_region_minmax( VipsRegion *region, VipsRect *r, VipsRect *bounds )
{ {
int min_x; int min_x;
int max_x; int max_x;
int min_y; int min_y;
int max_y; int max_y;
gboolean first; gboolean first;
skipping to change at line 168 skipping to change at line 212
max_x = 0; max_x = 0;
min_y = 0; min_y = 0;
max_y = 0; max_y = 0;
first = TRUE; first = TRUE;
for( y = 0; y < r->height; y++ ) { for( y = 0; y < r->height; y++ ) {
VipsPel * restrict p = VipsPel * restrict p =
VIPS_REGION_ADDR( region, r->left, r->top + y ); VIPS_REGION_ADDR( region, r->left, r->top + y );
switch( region->im->BandFmt ) { switch( region->im->BandFmt ) {
case VIPS_FORMAT_UCHAR: case VIPS_FORMAT_UCHAR:
MINMAX( unsigned char, MINMAX( unsigned char, CLIP_UINT_SMALL );
CLIP_UINT_SMALL, CLIP_UINT_SMALL );
break; break;
case VIPS_FORMAT_CHAR: case VIPS_FORMAT_CHAR:
MINMAX( signed char, MINMAX( signed char, CLIP_SINT_SMALL );
CLIP_SINT_SMALL, CLIP_SINT_SMALL );
break; break;
case VIPS_FORMAT_USHORT: case VIPS_FORMAT_USHORT:
MINMAX( unsigned short, MINMAX( unsigned short, CLIP_UINT_SMALL );
CLIP_UINT_SMALL, CLIP_UINT_SMALL );
break; break;
case VIPS_FORMAT_SHORT: case VIPS_FORMAT_SHORT:
MINMAX( signed short, MINMAX( signed short, CLIP_SINT_SMALL );
CLIP_SINT_SMALL, CLIP_SINT_SMALL );
break; break;
case VIPS_FORMAT_UINT: case VIPS_FORMAT_UINT:
MINMAX( unsigned int, MINMAX( unsigned int, CLIP_UINT_LARGE );
CLIP_UINT_LARGE, CLIP_UINT_LARGE );
break; break;
case VIPS_FORMAT_INT: case VIPS_FORMAT_INT:
MINMAX( signed int, MINMAX( signed int, CLIP_SINT_LARGE );
CLIP_SINT_LARGE, CLIP_SINT_LARGE );
break; break;
case VIPS_FORMAT_FLOAT: case VIPS_FORMAT_FLOAT:
case VIPS_FORMAT_COMPLEX: case VIPS_FORMAT_COMPLEX:
MINMAX( float, FMINMAX( float );
CLIP_FLOAT_LOW, CLIP_FLOAT_HIGH );
break; break;
case VIPS_FORMAT_DOUBLE: case VIPS_FORMAT_DOUBLE:
case VIPS_FORMAT_DPCOMPLEX: case VIPS_FORMAT_DPCOMPLEX:
MINMAX( double, FMINMAX( double );
CLIP_FLOAT_LOW, CLIP_FLOAT_HIGH );
break; break;
default: default:
g_assert_not_reached(); g_assert_not_reached();
} }
} }
bounds->left = min_x; bounds->left = min_x;
bounds->top = min_y; bounds->top = min_y;
bounds->width = max_x - min_x + 1; bounds->width = max_x - min_x + 1;
bounds->height = max_y - min_y + 1; bounds->height = max_y - min_y + 1;
} }
/* Unsigned int types.
*/
#define ULOOKUP( TYPE ) { \ #define ULOOKUP( TYPE ) { \
TYPE * restrict p1 = (TYPE *) p; \ TYPE * restrict p1 = (TYPE *) p; \
\ \
for( x = 0; x < r->width; x++ ) { \ for( x = 0; x < r->width; x++ ) { \
TYPE px = p1[0]; \ TYPE px = p1[0]; \
TYPE py = p1[1]; \ TYPE py = p1[1]; \
\ \
if( px >= clip_width || \ if( px >= clip_width || \
py >= clip_height ) { \ py >= clip_height ) { \
for( z = 0; z < ps; z++ ) \ for( z = 0; z < ps; z++ ) \
skipping to change at line 241 skipping to change at line 279
} \ } \
else \ else \
interpolate( mapim->interpolate, q, ir[0], \ interpolate( mapim->interpolate, q, ir[0], \
px + window_offset, py + window_offset ); \ px + window_offset, py + window_offset ); \
\ \
p1 += 2; \ p1 += 2; \
q += ps; \ q += ps; \
} \ } \
} }
/* Signed int types.
*/
#define LOOKUP( TYPE ) { \ #define LOOKUP( TYPE ) { \
TYPE * restrict p1 = (TYPE *) p; \ TYPE * restrict p1 = (TYPE *) p; \
\ \
for( x = 0; x < r->width; x++ ) { \ for( x = 0; x < r->width; x++ ) { \
TYPE px = p1[0]; \ TYPE px = p1[0]; \
TYPE py = p1[1]; \ TYPE py = p1[1]; \
\ \
if( px < 0 || \ if( px < 0 || \
px >= clip_width || \ px >= clip_width || \
py < 0 || \ py < 0 || \
skipping to change at line 264 skipping to change at line 304
} \ } \
else \ else \
interpolate( mapim->interpolate, q, ir[0], \ interpolate( mapim->interpolate, q, ir[0], \
px + window_offset, py + window_offset ); \ px + window_offset, py + window_offset ); \
\ \
p1 += 2; \ p1 += 2; \
q += ps; \ q += ps; \
} \ } \
} }
/* Float types.
*/
#define FLOOKUP( TYPE ) { \
TYPE * restrict p1 = (TYPE *) p; \
\
for( x = 0; x < r->width; x++ ) { \
TYPE px = p1[0]; \
TYPE py = p1[1]; \
\
if( VIPS_ISNAN( px ) || \
VIPS_ISNAN( py ) || \
px < 0 || \
px >= clip_width || \
py < 0 || \
py >= clip_height ) { \
for( z = 0; z < ps; z++ ) \
q[z] = 0; \
} \
else \
interpolate( mapim->interpolate, q, ir[0], \
px + window_offset, py + window_offset ); \
\
p1 += 2; \
q += ps; \
} \
}
static int static int
vips_mapim_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) vips_mapim_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
{ {
VipsRect *r = &or->valid; VipsRect *r = &or->valid;
VipsRegion **ir = (VipsRegion **) seq; VipsRegion **ir = (VipsRegion **) seq;
const VipsImage **in_array = (const VipsImage **) a; const VipsImage **in_array = (const VipsImage **) a;
const VipsMapim *mapim = (VipsMapim *) b; const VipsMapim *mapim = (VipsMapim *) b;
const VipsResample *resample = VIPS_RESAMPLE( mapim ); const VipsResample *resample = VIPS_RESAMPLE( mapim );
const VipsImage *in = in_array[0]; const VipsImage *in = in_array[0];
const int window_size = const int window_size =
skipping to change at line 309 skipping to change at line 376
return( -1 ); return( -1 );
VIPS_GATE_START( "vips_mapim_gen: work" ); VIPS_GATE_START( "vips_mapim_gen: work" );
vips_mapim_region_minmax( ir[1], r, &bounds ); vips_mapim_region_minmax( ir[1], r, &bounds );
VIPS_GATE_STOP( "vips_mapim_gen: work" ); VIPS_GATE_STOP( "vips_mapim_gen: work" );
/* The bounding box of that area is what we will need from @in. Add /* The bounding box of that area is what we will need from @in. Add
* enough for the interpolation stencil as well. * enough for the interpolation stencil as well.
*
*/ */
bounds.width += window_size - 1; bounds.width += window_size - 1;
bounds.height += window_size - 1; bounds.height += window_size - 1;
/* Clip against the expanded image. /* Clip against the expanded image.
*/ */
image.left = 0; image.left = 0;
image.top = 0; image.top = 0;
image.width = in->Xsize; image.width = in->Xsize;
image.height = in->Ysize; image.height = in->Ysize;
skipping to change at line 364 skipping to change at line 430
ULOOKUP( unsigned short ); break; ULOOKUP( unsigned short ); break;
case VIPS_FORMAT_SHORT: case VIPS_FORMAT_SHORT:
LOOKUP( signed short ); break; LOOKUP( signed short ); break;
case VIPS_FORMAT_UINT: case VIPS_FORMAT_UINT:
ULOOKUP( unsigned int ); break; ULOOKUP( unsigned int ); break;
case VIPS_FORMAT_INT: case VIPS_FORMAT_INT:
LOOKUP( signed int ); break; LOOKUP( signed int ); break;
case VIPS_FORMAT_FLOAT: case VIPS_FORMAT_FLOAT:
case VIPS_FORMAT_COMPLEX: case VIPS_FORMAT_COMPLEX:
LOOKUP( float ); break; FLOOKUP( float ); break;
break; break;
case VIPS_FORMAT_DOUBLE: case VIPS_FORMAT_DOUBLE:
case VIPS_FORMAT_DPCOMPLEX: case VIPS_FORMAT_DPCOMPLEX:
LOOKUP( double ); break; FLOOKUP( double ); break;
default: default:
g_assert_not_reached(); g_assert_not_reached();
} }
} }
VIPS_GATE_STOP( "vips_mapim_gen: work" ); VIPS_GATE_STOP( "vips_mapim_gen: work" );
return( 0 ); return( 0 );
} }
 End of changes. 18 change blocks. 
29 lines changed or deleted 95 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)