summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPeter Moulder <peter.moulder@monash.edu>2009-04-05 11:56:55 +0000
committerpjrm <pjrm@users.sourceforge.net>2009-04-05 11:56:55 +0000
commitc4aaf22898d7960a34b0b0509a72370605562669 (patch)
tree4dcb652d73a0603addf12fb159f34c86f3fef5a9 /src
parentTranslation fixes in the swatches menu (en_GB) (diff)
downloadinkscape-c4aaf22898d7960a34b0b0509a72370605562669.tar.gz
inkscape-c4aaf22898d7960a34b0b0509a72370605562669.zip
Fix a divide-by-zero problem apparently introduced in r21012.
(bzr r7625)
Diffstat (limited to 'src')
-rw-r--r--src/display/nr-filter-displacement-map.cpp71
1 files changed, 43 insertions, 28 deletions
diff --git a/src/display/nr-filter-displacement-map.cpp b/src/display/nr-filter-displacement-map.cpp
index 321018fca..d2b1c2a0b 100644
--- a/src/display/nr-filter-displacement-map.cpp
+++ b/src/display/nr-filter-displacement-map.cpp
@@ -60,38 +60,53 @@ static pixel_t interpolatePixels(NRPixBlock const* pb, double x, double y) {
pixel_t p10 = pixelValue(pb, xi+0, yi+1);
pixel_t p11 = pixelValue(pb, xi+1, yi+1);
+ /* It's a good idea to interpolate premultiplied colors:
+ *
+ * Consider two pixels, one being rgba(255,0,0,0), which is fully transparent,
+ * and the other being rgba(0,0,255,255), or blue (fully opaque).
+ * If these two colors are interpolated the expected result would be bluish pixels
+ * containing no red.
+ *
+ * However, if our final alpha value is zero, then the RGB values aren't really determinate.
+ * We might as well avoid premultiplication in this case, which still gives us a fully
+ * transparent result, but with interpolated RGB parts. */
+
+ /* First calculate interpolated alpha value. */
+ unsigned ra = 0;
+ if (!PREMULTIPLIED) {
+ unsigned const y0 = sf*p00[3] + xf*(p01[3]-p00[3]); // range [0,a*sf]
+ unsigned const y1 = sf*p10[3] + xf*(p11[3]-p10[3]);
+ ra = sf*y0 + yf*(y1-y0); // range [0,a*sf*sf]
+ }
+
pixel_t r;
- if (PREMULTIPLIED) {
- unsigned int p0[4]; // range [0,a*sf]
- unsigned int p1[4];
- for(size_t i=0; i<4; i++) {
- p0[i] = sf*p00[i] + xf*((unsigned int)p01[i]-(unsigned int)p00[i]);
- p1[i] = sf*p10[i] + xf*((unsigned int)p11[i]-(unsigned int)p10[i]);
- }
- for(size_t i=0; i<4; i++) {
- unsigned int ru = sf*p0[i] + yf*(p1[i]-p0[i]); // range [0,a*sf^2]
- r[i] = (ru + sf2h)>>(2u*sfl); // range [0,a]
+ if (ra == 0) {
+ /* Either premultiplied or the interpolated alpha value is zero,
+ * so do simple interpolation. */
+ for (unsigned i = 0; i != 4; ++i) {
+ // y0,y1 have range [0,a*sf]
+ unsigned const y0 = sf*p00[i] + xf*((unsigned int)p01[i]-(unsigned int)p00[i]);
+ unsigned const y1 = sf*p10[i] + xf*((unsigned int)p11[i]-(unsigned int)p10[i]);
+
+ unsigned const ri = sf*y0 + yf*(y1-y0); // range [0,a*sf*sf]
+ r[i] = (ri + sf2h)>>(2*sfl); // range [0,a]
}
} else {
- // It's a good idea to interpolate premultiplied colors
- // Consider two pixels, one being rgb(255,0,0,0), which is fully transparent,
- // and the other being rgb(0,255,0,255), or green (fully opaque).
- // If these two colors are interpolated the expected result would be greenish pixels containing no red.
- unsigned int p0[4];
- unsigned int p1[4];
- for(size_t i=0; i<3; i++) {
- unsigned int c00 = p00[i]*p00[3], c01 = p01[i]*p01[3], c10 = p10[i]*p10[3], c11 = p11[i]*p11[3]; // range [0,255*a]
- p0[i] = sf*c00 + xf*(c01-c00); // range [0,255*a*sf]
- p1[i] = sf*c10 + xf*(c11-c10); // range [0,255*a*sf]
- }
- p0[3] = sf*p00[3] + xf*(p01[3]-p00[3]); // range [0,a*sf]
- p1[3] = sf*p10[3] + xf*(p11[3]-p10[3]);
- unsigned int ru = sf*p0[3] + yf*(p1[3]-p0[3]); // range [0,a*sf^2]
- r[3] = (ru + sf2h)>>(2u*sfl); // range [0,a]
- for(size_t i=0; i<3; i++) {
- unsigned int ru = sf*p0[i] + yf*(p1[i]-p0[i]); // range [0,255*a*sf^2]
- r[i] = (ru + ru/2u)/ru; // range [0,255]
+ /* Do premultiplication ourselves. */
+ for (unsigned i = 0; i != 3; ++i) {
+ // Premultiplied versions. Range [0,255*a].
+ unsigned const c00 = p00[i]*p00[3];
+ unsigned const c01 = p01[i]*p01[3];
+ unsigned const c10 = p10[i]*p10[3];
+ unsigned const c11 = p11[i]*p11[3];
+
+ // Interpolation.
+ unsigned const y0 = sf*c00 + xf*(c01-c00); // range [0,255*a*sf]
+ unsigned const y1 = sf*c10 + xf*(c11-c10); // range [0,255*a*sf]
+ unsigned const ri = sf*y0 + yf*(y1-y0); // range [0,255*a*sf*sf]
+ r[i] = (ri + ra/2) / ra; // range [0,255]
}
+ r[3] = (ra + sf2h)>>(2*sfl); // range [0,a]
}
return r;