use round() rather than rint() where appropriate
rint() rounds to nearest even, rather than nearest ... in some cases, like geometry transforms, we want strict nearest
This commit is contained in:
parent
8503065faa
commit
271d8656e9
@ -37,8 +37,9 @@
|
||||
- support --strip for pngsave
|
||||
- add svgz support [Felix Bünemann]
|
||||
- rename boostrap.sh -> autogen.sh to help snapcraft
|
||||
- resize/reduce/shrink now round output size to nearest rather than rounding
|
||||
down, thanks ioquatix
|
||||
- added VIPS_ROUND as well as VIPS_RINT
|
||||
- resize/reduce*/shrink*/affine now round output size to nearest rather than
|
||||
rounding down, thanks ioquatix
|
||||
|
||||
30/7/16 started 8.3.3
|
||||
- fix performance regression in 8.3.2, thanks Lovell
|
||||
|
@ -95,11 +95,9 @@ vips_Lab2LabQ_line( VipsColour *colour, VipsPel *out, VipsPel **in, int width )
|
||||
int lsbs;
|
||||
int intv;
|
||||
|
||||
/* Scale L up to 10 bits. Add 0.5 rather than call VIPS_RINT
|
||||
* for speed. This will not round negatives correctly! But
|
||||
* this does not matter, since L is >0. L*=100.0 -> 1023.
|
||||
/* Scale L up to 10 bits.
|
||||
*/
|
||||
intv = 10.23 * p[0] + 0.5; /* scale L up to 10 bits */
|
||||
intv = VIPS_ROUND_UINT( 10.23 * p[0] );
|
||||
intv = VIPS_CLIP( 0, intv, 1023 );
|
||||
lsbs = (intv & 0x3) << 6; /* 00000011 -> 11000000 */
|
||||
q[0] = intv >> 2; /* drop bot 2 bits and store */
|
||||
|
@ -50,14 +50,6 @@
|
||||
|
||||
#include "pconversion.h"
|
||||
|
||||
/* Round N down to P boundary.
|
||||
*/
|
||||
#define ROUND_DOWN( N, P ) ((N) - ((N) % P))
|
||||
|
||||
/* Round N up to P boundary.
|
||||
*/
|
||||
#define ROUND_UP( N, P ) (ROUND_DOWN( (N) + (P) - 1, (P) ))
|
||||
|
||||
typedef struct _VipsArrayjoin {
|
||||
VipsConversion parent_instance;
|
||||
|
||||
@ -179,7 +171,7 @@ vips_arrayjoin_build( VipsObject *object )
|
||||
|
||||
/* How many images down the grid?
|
||||
*/
|
||||
join->down = ROUND_UP( n, join->across ) / join->across;
|
||||
join->down = VIPS_ROUND_UP( n, join->across ) / join->across;
|
||||
|
||||
/* The output size.
|
||||
*/
|
||||
|
@ -98,14 +98,6 @@ typedef VipsConversionClass VipsZoomClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsZoom, vips_zoom, VIPS_TYPE_CONVERSION );
|
||||
|
||||
/* Round N down to P boundary.
|
||||
*/
|
||||
#define ROUND_DOWN( N, P ) ((N) - ((N) % P))
|
||||
|
||||
/* Round N up to P boundary.
|
||||
*/
|
||||
#define ROUND_UP( N, P ) (ROUND_DOWN( (N) + (P) - 1, (P) ))
|
||||
|
||||
/* Paint the part of the region containing only whole pels.
|
||||
*/
|
||||
static void
|
||||
@ -265,10 +257,10 @@ vips_zoom_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
|
||||
/* Area of input we need. We have to round out, as we may have
|
||||
* part-pixels all around the edges.
|
||||
*/
|
||||
left = ROUND_DOWN( r->left, zoom->xfac );
|
||||
right = ROUND_UP( ri, zoom->xfac );
|
||||
top = ROUND_DOWN( r->top, zoom->yfac );
|
||||
bottom = ROUND_UP( bo, zoom->yfac );
|
||||
left = VIPS_ROUND_DOWN( r->left, zoom->xfac );
|
||||
right = VIPS_ROUND_UP( ri, zoom->xfac );
|
||||
top = VIPS_ROUND_DOWN( r->top, zoom->yfac );
|
||||
bottom = VIPS_ROUND_UP( bo, zoom->yfac );
|
||||
width = right - left;
|
||||
height = bottom - top;
|
||||
s.left = left / zoom->xfac;
|
||||
@ -280,10 +272,10 @@ vips_zoom_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
|
||||
|
||||
/* Find the part of the output (if any) which uses only whole pels.
|
||||
*/
|
||||
left = ROUND_UP( r->left, zoom->xfac );
|
||||
right = ROUND_DOWN( ri, zoom->xfac );
|
||||
top = ROUND_UP( r->top, zoom->yfac );
|
||||
bottom = ROUND_DOWN( bo, zoom->yfac );
|
||||
left = VIPS_ROUND_UP( r->left, zoom->xfac );
|
||||
right = VIPS_ROUND_DOWN( ri, zoom->xfac );
|
||||
top = VIPS_ROUND_UP( r->top, zoom->yfac );
|
||||
bottom = VIPS_ROUND_DOWN( bo, zoom->yfac );
|
||||
width = right - left;
|
||||
height = bottom - top;
|
||||
|
||||
|
@ -71,14 +71,6 @@ typedef struct _VipsPerlinClass {
|
||||
|
||||
G_DEFINE_TYPE( VipsPerlin, vips_perlin, VIPS_TYPE_CREATE );
|
||||
|
||||
/* Round N down to P boundary.
|
||||
*/
|
||||
#define ROUND_DOWN( N, P ) ((N) - ((N) % P))
|
||||
|
||||
/* Round N up to P boundary.
|
||||
*/
|
||||
#define ROUND_UP( N, P ) (ROUND_DOWN( (N) + (P) - 1, (P) ))
|
||||
|
||||
/* cos and sin from an angle in 0 - 255.
|
||||
*/
|
||||
float vips_perlin_cos[256];
|
||||
@ -261,9 +253,11 @@ vips_perlin_build( VipsObject *object )
|
||||
|
||||
/* Be careful if width is a multiple of cell_size.
|
||||
*/
|
||||
perlin->cells_across = ROUND_UP( perlin->width, perlin->cell_size ) /
|
||||
perlin->cells_across =
|
||||
VIPS_ROUND_UP( perlin->width, perlin->cell_size ) /
|
||||
perlin->cell_size;
|
||||
perlin->cells_down = ROUND_UP( perlin->height, perlin->cell_size ) /
|
||||
perlin->cells_down =
|
||||
VIPS_ROUND_UP( perlin->height, perlin->cell_size ) /
|
||||
perlin->cell_size;
|
||||
|
||||
perlin->seed = g_random_double() * 0xffffffffu;
|
||||
|
@ -75,14 +75,6 @@ G_DEFINE_TYPE( VipsWorley, vips_worley, VIPS_TYPE_CREATE );
|
||||
|
||||
#define MAX_FEATURES (10)
|
||||
|
||||
/* Round N down to P boundary.
|
||||
*/
|
||||
#define ROUND_DOWN( N, P ) ((N) - ((N) % P))
|
||||
|
||||
/* Round N up to P boundary.
|
||||
*/
|
||||
#define ROUND_UP( N, P ) (ROUND_DOWN( (N) + (P) - 1, (P) ))
|
||||
|
||||
typedef struct _Cell {
|
||||
/* Cell position, in number of cells. Scale by cell_size to get
|
||||
* absolute image cods.
|
||||
@ -294,9 +286,11 @@ vips_worley_build( VipsObject *object )
|
||||
|
||||
/* Be careful if width is a multiple of cell_size.
|
||||
*/
|
||||
worley->cells_across = ROUND_UP( worley->width, worley->cell_size ) /
|
||||
worley->cells_across =
|
||||
VIPS_ROUND_UP( worley->width, worley->cell_size ) /
|
||||
worley->cell_size;
|
||||
worley->cells_down = ROUND_UP( worley->height, worley->cell_size ) /
|
||||
worley->cells_down =
|
||||
VIPS_ROUND_UP( worley->height, worley->cell_size ) /
|
||||
worley->cell_size;
|
||||
|
||||
worley->seed = g_random_double() * 0xffffffffu;
|
||||
|
@ -285,14 +285,6 @@ vips__make_xml_metadata( const char *domain, VipsImage *image )
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
|
||||
/* Round N down to P boundary.
|
||||
*/
|
||||
#define ROUND_DOWN( N, P ) ((N) - ((N) % P))
|
||||
|
||||
/* Round N up to P boundary.
|
||||
*/
|
||||
#define ROUND_UP( N, P ) (ROUND_DOWN( (N) + (P) - 1, (P) ))
|
||||
|
||||
/* Simple wrapper around libgsf.
|
||||
*
|
||||
* We need to be able to do scattered writes to structured files. So while
|
||||
@ -672,8 +664,10 @@ pyramid_build( VipsForeignSaveDz *dz, Layer *above,
|
||||
layer->width = width;
|
||||
layer->height = height;
|
||||
|
||||
layer->tiles_across = ROUND_UP( width, dz->tile_size ) / dz->tile_size;
|
||||
layer->tiles_down = ROUND_UP( height, dz->tile_size ) / dz->tile_size;
|
||||
layer->tiles_across = VIPS_ROUND_UP( width, dz->tile_size ) /
|
||||
dz->tile_size;
|
||||
layer->tiles_down = VIPS_ROUND_UP( height, dz->tile_size ) /
|
||||
dz->tile_size;
|
||||
|
||||
layer->real_pixels = *real_pixels;
|
||||
|
||||
|
@ -322,14 +322,6 @@ tiff_openin( const char *name )
|
||||
return( tif );
|
||||
}
|
||||
|
||||
/* Round N down to P boundary.
|
||||
*/
|
||||
#define ROUND_DOWN(N,P) ((N) - ((N) % P))
|
||||
|
||||
/* Round N up to P boundary.
|
||||
*/
|
||||
#define ROUND_UP(N,P) (ROUND_DOWN( (N) + (P) - 1, (P) ))
|
||||
|
||||
static Layer *
|
||||
pyramid_new( Write *write, Layer *above, int width, int height )
|
||||
{
|
||||
@ -975,7 +967,7 @@ write_new( VipsImage *im, const char *filename,
|
||||
if( im->Coding == VIPS_CODING_LABQ )
|
||||
write->tls = write->tilew * 3;
|
||||
else if( write->onebit )
|
||||
write->tls = ROUND_UP( write->tilew, 8 ) / 8;
|
||||
write->tls = VIPS_ROUND_UP( write->tilew, 8 ) / 8;
|
||||
else
|
||||
write->tls = VIPS_IMAGE_SIZEOF_PEL( im ) * write->tilew;
|
||||
|
||||
|
@ -53,11 +53,14 @@ extern "C" {
|
||||
|
||||
#define VIPS_MAX( A, B ) ((A) > (B) ? (A) : (B))
|
||||
#define VIPS_MIN( A, B ) ((A) < (B) ? (A) : (B))
|
||||
#define VIPS_ABS( X ) (((X) >= 0) ? (X) : -(X))
|
||||
|
||||
#define VIPS_CLIP( A, V, B ) VIPS_MAX( (A), VIPS_MIN( (B), (V) ) )
|
||||
#define VIPS_FCLIP( A, V, B ) VIPS_FMAX( (A), VIPS_FMIN( (B), (V) ) )
|
||||
|
||||
#define VIPS_NUMBER( R ) ((int) (sizeof(R) / sizeof(R[0])))
|
||||
|
||||
#define VIPS_ABS( X ) (((X) >= 0) ? (X) : -(X))
|
||||
|
||||
/* The built-in isnan and isinf functions provided by gcc 4+ and clang are
|
||||
* up to 7x faster than their libc equivalent included from <math.h>.
|
||||
*/
|
||||
@ -67,6 +70,7 @@ extern "C" {
|
||||
#define VIPS_FLOOR( V ) __builtin_floor( V )
|
||||
#define VIPS_CEIL( V ) __builtin_ceil( V )
|
||||
#define VIPS_RINT( V ) __builtin_rint( V )
|
||||
#define VIPS_ROUND( V ) __builtin_round( V )
|
||||
#define VIPS_FABS( V ) __builtin_fabs( V )
|
||||
#define VIPS_FMAX( A, B ) __builtin_fmax( A, B )
|
||||
#define VIPS_FMIN( A, B ) __builtin_fmin( A, B )
|
||||
@ -75,13 +79,25 @@ extern "C" {
|
||||
#define VIPS_ISINF( V ) isinf( V )
|
||||
#define VIPS_FLOOR( V ) floor( V )
|
||||
#define VIPS_CEIL( V ) ceil( V )
|
||||
#define VIPS_RINT( R ) ((int) ((R) > 0 ? ((R) + 0.5) : ((R) - 0.5)))
|
||||
#define VIPS_RINT( R ) rint( V )
|
||||
#define VIPS_ROUND( V ) round( V )
|
||||
#define VIPS_FABS( V ) VIPS_ABS( V )
|
||||
#define VIPS_FMAX( A, B ) VIPS_MAX( A, B )
|
||||
#define VIPS_FMIN( A, B ) VIPS_MIN( A, B )
|
||||
#endif
|
||||
|
||||
#define VIPS_FCLIP( A, V, B ) VIPS_FMAX( (A), VIPS_FMIN( (B), (V) ) )
|
||||
/* VIPS_RINT() does "bankers rounding", it rounds to the nerarest even integer.
|
||||
* For things like image geometry, we want strict nearest int.
|
||||
*
|
||||
* If you know it's unsigned, _UINT is a little faster.
|
||||
*/
|
||||
#define VIPS_ROUND_INT( R ) ((int) ((R) > 0 ? ((R) + 0.5) : ((R) - 0.5)))
|
||||
#define VIPS_ROUND_UINT( R ) ((int) ((R) + 0.5))
|
||||
|
||||
/* Round N down and up to the nearest multiple of P.
|
||||
*/
|
||||
#define VIPS_ROUND_DOWN( N, P ) ((N) - ((N) % (P)))
|
||||
#define VIPS_ROUND_UP( N, P ) (VIPS_ROUND_DOWN( N, P ) + (P))
|
||||
|
||||
#define VIPS_SWAP( TYPE, A, B ) \
|
||||
G_STMT_START { \
|
||||
|
@ -922,14 +922,6 @@ vips_threadpool_run( VipsImage *im,
|
||||
return( result );
|
||||
}
|
||||
|
||||
/* Round N down to P boundary.
|
||||
*/
|
||||
#define ROUND_DOWN(N,P) ((N) - ((N) % P))
|
||||
|
||||
/* Round N up to P boundary.
|
||||
*/
|
||||
#define ROUND_UP(N,P) (ROUND_DOWN( (N) + (P) - 1, (P) ))
|
||||
|
||||
/**
|
||||
* vips_get_tile_size:
|
||||
* @im: image to guess for
|
||||
@ -986,7 +978,7 @@ vips_get_tile_size( VipsImage *im,
|
||||
(1 + nthr / VIPS_MAX( 1, im->Xsize / vips__tile_width )) * 2;
|
||||
*n_lines = VIPS_MAX( *n_lines, vips__fatstrip_height * nthr * 2 );
|
||||
*n_lines = VIPS_MAX( *n_lines, vips__thinstrip_height * nthr * 2 );
|
||||
*n_lines = ROUND_UP( *n_lines, *tile_height );
|
||||
*n_lines = VIPS_ROUND_UP( *n_lines, *tile_height );
|
||||
|
||||
/* We make this assumption in several places.
|
||||
*/
|
||||
|
@ -498,13 +498,14 @@ vips_reduceh_build( VipsObject *object )
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, in, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
/* Size output. Note: we round to nearest to hide rounding errors.
|
||||
/* Size output. We need to always round to nearest, so round(), not
|
||||
* rint().
|
||||
*
|
||||
* Don't change xres/yres, leave that to the application layer. For
|
||||
* example, vipsthumbnail knows the true reduce factor (including the
|
||||
* fractional part), we just see the integer part here.
|
||||
*/
|
||||
resample->out->Xsize = VIPS_RINT(
|
||||
resample->out->Xsize = VIPS_ROUND_UINT(
|
||||
(in->Xsize - reduceh->n_point + 1) / reduceh->hshrink );
|
||||
if( resample->out->Xsize <= 0 ) {
|
||||
vips_error( object_class->nickname,
|
||||
|
@ -775,13 +775,14 @@ vips_reducev_raw( VipsReducev *reducev, VipsImage *in )
|
||||
VIPS_DEMAND_STYLE_FATSTRIP, in, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
/* Size output. Note: we round to nearest to hide rounding errors.
|
||||
/* Size output. We need to always round to nearest, so round(), not
|
||||
* rint().
|
||||
*
|
||||
* Don't change xres/yres, leave that to the application layer. For
|
||||
* example, vipsthumbnail knows the true reduce factor (including the
|
||||
* fractional part), we just see the integer part here.
|
||||
*/
|
||||
resample->out->Ysize = VIPS_RINT(
|
||||
resample->out->Ysize = VIPS_ROUND_UINT(
|
||||
(in->Ysize - reducev->n_point + 1) / reducev->vshrink );
|
||||
if( resample->out->Ysize <= 0 ) {
|
||||
vips_error( object_class->nickname,
|
||||
|
@ -275,13 +275,14 @@ vips_shrinkh_build( VipsObject *object )
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, in, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
/* Size output. We need to rint() from the size of the original image.
|
||||
/* Size output. We need to always round to nearest, so round(), not
|
||||
* rint().
|
||||
*
|
||||
* Don't change xres/yres, leave that to the application layer. For
|
||||
* example, vipsthumbnail knows the true shrink factor (including the
|
||||
* fractional part), we just see the integer part here.
|
||||
*/
|
||||
resample->out->Xsize = VIPS_RINT(
|
||||
resample->out->Xsize = VIPS_ROUND_UINT(
|
||||
resample->in->Xsize / shrink->hshrink );
|
||||
if( resample->out->Xsize <= 0 ) {
|
||||
vips_error( class->nickname,
|
||||
|
@ -379,13 +379,14 @@ vips_shrinkv_build( VipsObject *object )
|
||||
VIPS_DEMAND_STYLE_THINSTRIP, in, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
/* Size output. We need to rint() from the size of the original image.
|
||||
/* Size output. We need to always round to nearest, so round(), not
|
||||
* rint().
|
||||
*
|
||||
* Don't change xres/yres, leave that to the application layer. For
|
||||
* example, vipsthumbnail knows the true shrink factor (including the
|
||||
* fractional part), we just see the integer part here.
|
||||
*/
|
||||
resample->out->Ysize = VIPS_RINT(
|
||||
resample->out->Ysize = VIPS_ROUND_UINT(
|
||||
resample->in->Ysize / shrink->vshrink );
|
||||
if( resample->out->Ysize <= 0 ) {
|
||||
vips_error( class->nickname,
|
||||
|
@ -215,10 +215,10 @@ transform_rect( const VipsTransformation *trn, transform_fn transform,
|
||||
top = VIPS_MIN( y1, VIPS_MIN( y2, VIPS_MIN( y3, y4 ) ) );
|
||||
bottom = VIPS_MAX( y1, VIPS_MAX( y2, VIPS_MAX( y3, y4 ) ) );
|
||||
|
||||
out->left = VIPS_RINT( left );
|
||||
out->top = VIPS_RINT( top );
|
||||
out->width = VIPS_RINT( right - left );
|
||||
out->height = VIPS_RINT( bottom - top );
|
||||
out->left = VIPS_ROUND_INT( left );
|
||||
out->top = VIPS_ROUND_INT( top );
|
||||
out->width = VIPS_ROUND_INT( right - left );
|
||||
out->height = VIPS_ROUND_INT( bottom - top );
|
||||
}
|
||||
|
||||
/* Given an area in the input image, calculate the bounding box for those
|
||||
|
Loading…
Reference in New Issue
Block a user