From 8ef38e99109c62f52d9c00c69dfae2531b16e472 Mon Sep 17 00:00:00 2001 From: Christophe CURIS Date: Sat, 11 May 2013 00:07:16 +0200 Subject: [PATCH] WRaster: Changed equality/inequality comparison on floating point number The equality comparison (a == b) is known to be a dangerous trap when floating-point arithmetics are involved. This patch changes all the cases which try to do this to a safer check. --- wrlib/png.c | 2 +- wrlib/rotate.c | 21 +++++++++++++++++---- wrlib/scale.c | 14 +++++++++++++- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/wrlib/png.c b/wrlib/png.c index fed178e1..03074ead 100644 --- a/wrlib/png.c +++ b/wrlib/png.c @@ -140,7 +140,7 @@ RImage *RLoadPNG(RContext *context, const char *file) sgamma = (context->attribs->rgamma + context->attribs->ggamma + context->attribs->bgamma) / 3; } else if ((tmp = getenv("DISPLAY_GAMMA")) != NULL) { sgamma = atof(tmp); - if (sgamma == 0) + if (sgamma < 1.0E-3) sgamma = 1; } else { /* blah */ diff --git a/wrlib/rotate.c b/wrlib/rotate.c index b1379ba3..d296815a 100644 --- a/wrlib/rotate.c +++ b/wrlib/rotate.c @@ -43,12 +43,23 @@ RImage *RRotateImage(RImage * image, float angle) int x, y; int bpp = image->format == RRGBAFormat ? 4 : 3; + /* + * Angle steps below this value would represent a rotation + * of less than 1 pixel for a 4k wide image, so not worth + * bothering the difference. That makes it a perfect + * candidate for an Epsilon when trying to compare angle + * to known values + */ + static const float min_usable_angle = 0.00699; + angle = ((int)angle % 360) + (angle - (int)angle); - if (angle == 0.0) { + if (angle < min_usable_angle) { + /* Rotate by 0 degree */ return RCloneImage(image); - } else if (angle == 90.0) { + } else if ((angle > 90.0 - min_usable_angle) && + (angle < 90.0 + min_usable_angle)) { nwidth = image->height; nheight = image->width; @@ -91,7 +102,8 @@ RImage *RRotateImage(RImage * image, float angle) } } } - } else if (angle == 180.0) { + } else if ((angle > 180.0 - min_usable_angle) && + (angle < 180.0 + min_usable_angle)) { nwidth = image->width; nheight = image->height; @@ -129,7 +141,8 @@ RImage *RRotateImage(RImage * image, float angle) nptr--; } } - } else if (angle == 270.0) { + } else if ((angle > 270.0 - min_usable_angle) && + (angle < 270.0 + min_usable_angle)) { nwidth = image->height; nheight = image->width; diff --git a/wrlib/scale.c b/wrlib/scale.c index 6990afe2..d2cc1e6c 100644 --- a/wrlib/scale.c +++ b/wrlib/scale.c @@ -187,8 +187,20 @@ static double B_spline_filter(double t) /* box (*) box (*) box (*) box */ static double sinc(double x) { + /* + * The original code did this: + * if (x != 0) ... + * This code is unsafe, it should be: + * if (fabs(x) > EPSILON) ... + * + * But the call to fabs is already done in the *ONLY* function + * that call sinc: 'Lanczos3_filter' + * + * The goal was to avoid a Divide-by-0 error, now we also + * avoid a +/-inf result too + */ x *= PI; - if (x != 0) + if (x > 1.0E-9) return (sin(x) / x); return (1.0); } -- 2.11.4.GIT