summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNiko Kiirala <niko@kiirala.com>2007-07-24 12:48:54 +0000
committerkiirala <kiirala@users.sourceforge.net>2007-07-24 12:48:54 +0000
commited06b534c440e543937f4fe71eb593e556916306 (patch)
tree69a51ff3081126745822a309457a83fe3913b1a1 /src
parentFixed a memory leak in lighting effects rendering (diff)
downloadinkscape-ed06b534c440e543937f4fe71eb593e556916306.tar.gz
inkscape-ed06b534c440e543937f4fe71eb593e556916306.zip
Fixed rendering glitch in bicubic scaler
(bzr r3289)
Diffstat (limited to 'src')
-rw-r--r--src/display/nr-filter-utils.cpp21
-rw-r--r--src/display/nr-filter-utils.h12
-rw-r--r--src/display/pixblock-scaler.cpp31
3 files changed, 53 insertions, 11 deletions
diff --git a/src/display/nr-filter-utils.cpp b/src/display/nr-filter-utils.cpp
index 85faadebc..52c8ecc7d 100644
--- a/src/display/nr-filter-utils.cpp
+++ b/src/display/nr-filter-utils.cpp
@@ -2,10 +2,27 @@
namespace NR {
-int clamp(int val) {
+int clamp(int const val) {
if (val < 0) return 0;
if (val > 255) return 255;
return val;
}
-
+
+int clamp_alpha(int const val, int const alpha) {
+ if (val < 0) return 0;
+ if (val > alpha) return alpha;
+ return val;
+}
+
} //namespace NR
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-filter-utils.h b/src/display/nr-filter-utils.h
index b591b37cb..5ac6fa5ab 100644
--- a/src/display/nr-filter-utils.h
+++ b/src/display/nr-filter-utils.h
@@ -23,13 +23,23 @@ namespace NR {
* \return 0 if the value is smaller than 0, 255 if it is greater 255, else v
* \param v the value to clamp
*/
-int clamp(int val);
+int clamp(int const val);
/**
* Macro to use the clamp function with double inputs and unsigned char output
*/
#define CLAMP_D_TO_U8(v) (unsigned char) clamp((int)round((v)))
+/**
+ * Clamps an integer to a value between 0 and alpha. Useful when handling
+ * images with premultiplied alpha, as setting some of RGB channels
+ * to a value bigger than alpha confuses the alpha blending in Inkscape
+ * \return 0 if val is negative, alpha if val is bigger than alpha, val otherwise
+ * \param val the value to clamp
+ * \param alpha the maximum value to clamp to
+ */
+int clamp_alpha(int const val, int const alpha);
+
} /* namespace NR */
#endif /* __NR_FILTER_UTILS_H__ */
diff --git a/src/display/pixblock-scaler.cpp b/src/display/pixblock-scaler.cpp
index c5acaace0..d65cfd4e0 100644
--- a/src/display/pixblock-scaler.cpp
+++ b/src/display/pixblock-scaler.cpp
@@ -15,6 +15,7 @@
#include <cmath>
using std::floor;
+#include "display/nr-filter-utils.h"
#include "libnr/nr-pixblock.h"
namespace NR {
@@ -61,16 +62,16 @@ inline int sampley(unsigned const char a, unsigned const char b,
* Returns the interpolated value in 8-bit format, ready to be written
* to output buffer.
*/
-inline unsigned char samplex(const int a, const int b, const int c, const int d, const double len) {
+inline int samplex(const int a, const int b, const int c, const int d, const double len) {
double lenf = len - floor(len);
int sum = 0;
sum += (int)(a * (((-1.0 / 3.0) * lenf + 4.0 / 5.0) * lenf - 7.0 / 15.0) * lenf);
sum += (int)(b * (((lenf - 9.0 / 5.0) * lenf - 1.0 / 5.0) * lenf + 1.0));
sum += (int)(c * ((((1 - lenf) - 9.0 / 5.0) * (1 - lenf) - 1.0 / 5.0) * (1 - lenf) + 1.0));
sum += (int)(d * (((-1.0 / 3.0) * (1 - lenf) + 4.0 / 5.0) * (1 - lenf) - 7.0 / 15.0) * (1 - lenf));
- if (sum < 0) sum = 0;
- if (sum >= 256*256) sum = 255 * 256;
- return (unsigned char)(sum / 256);
+ //if (sum < 0) sum = 0;
+ //if (sum > 255 * 256) sum = 255 * 256;
+ return sum / 256;
}
/**
@@ -169,10 +170,24 @@ void scale_bicubic(NRPixBlock *to, NRPixBlock *from)
from_x);
_check_index(to, to_y * to->rs + to_x * 4, __LINE__);
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4] = result.r;
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 1] = result.g;
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 2] = result.b;
- NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 3] = result.a;
+
+ if (to->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
+ /* Clamp the colour channels to range from 0 to result.a to
+ * make sure, we don't exceed 100% per colour channel with
+ * images that have premultiplied alpha */
+
+ result.a = clamp(result.a);
+
+ NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4] = clamp_alpha(result.r, result.a);
+ NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 1] = clamp_alpha(result.g, result.a);
+ NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 2] = clamp_alpha(result.b, result.a);
+ NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 3] = result.a;
+ } else {
+ NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4] = clamp(result.r);
+ NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 1] = clamp(result.g);
+ NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 2] = clamp(result.b);
+ NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x * 4 + 3] = clamp(result.a);
+ }
}
}
}