From: kiirala Date: Tue, 24 Jul 2007 12:48:54 +0000 (+0000) Subject: Fixed rendering glitch in bicubic scaler X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=aec7a0781472450c98c74c107a9a36528dbb9872;p=inkscape.git Fixed rendering glitch in bicubic scaler --- 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 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); + } } } }