From 22bcb20c1a5663ea2dcbb4b741b0214a27ac20cb Mon Sep 17 00:00:00 2001 From: Jasper van de Gronde Date: Tue, 18 May 2010 09:53:46 +0200 Subject: [PATCH] Fix for bug #577012 --- src/libnr/nr-compose-transform.cpp | 70 +++++++++++++++++------------- src/libnr/nr-pixops.h | 6 ++- 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/src/libnr/nr-compose-transform.cpp b/src/libnr/nr-compose-transform.cpp index e7c286569..05852bf07 100644 --- a/src/libnr/nr-compose-transform.cpp +++ b/src/libnr/nr-compose-transform.cpp @@ -65,11 +65,14 @@ nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, int x, y; if (alpha == 0) return; + if (alpha>255) { + g_warning("In transform PPN alpha=%u>255",alpha); + } - // Both alpha and color components are stored temporarily with a range of [0,255^2], so more supersampling and we get an overflow - if (xd+yd>16) { - xd = 8; - yd = 8; + // The color component is stored temporarily with a range of [0,255^3], so more supersampling and we get an overflow (fortunately Inkscape's preferences also doesn't allow a higher setting) + if (xd+yd>8) { + xd = 4; + yd = 4; } xsize = (1 << xd); @@ -122,38 +125,42 @@ nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, if ((sy >= 0) && (sy < sh)) { const unsigned char *s; s = spx + sy * srs + sx * 4; - r += NR_PREMUL_112 (s[0], s[3]); + r += NR_PREMUL_112 (s[0], s[3]); // s in [0,255] g += NR_PREMUL_112 (s[1], s[3]); b += NR_PREMUL_112 (s[2], s[3]); a += s[3]; + // a=sum(s3) + // r,g,b in [0,sum(s3)*255] } } } a = (a*alpha + rounding_fix) >> dbits; + // a=sum(s3)*alpha/size=avg(s3)*alpha // Compare to nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P if (a != 0) { - r = (r + rounding_fix) >> dbits; - g = (g + rounding_fix) >> dbits; - b = (b + rounding_fix) >> dbits; + r = (r*alpha + rounding_fix) >> dbits; + g = (g*alpha + rounding_fix) >> dbits; + b = (b*alpha + rounding_fix) >> dbits; + // r,g,b in [0,avg(s3)*alpha*255]=[0,a*255] if (a == 255*255) { /* Full coverage, demul src */ - d[0] = NR_NORMALIZE_21(r); - d[1] = NR_NORMALIZE_21(g); - d[2] = NR_NORMALIZE_21(b); + d[0] = NR_NORMALIZE_31(r); + d[1] = NR_NORMALIZE_31(g); + d[2] = NR_NORMALIZE_31(b); d[3] = NR_NORMALIZE_21(a); } else if (d[3] == 0) { /* Only foreground, demul src */ - d[0] = NR_DEMUL_221(r,a); - d[1] = NR_DEMUL_221(g,a); - d[2] = NR_DEMUL_221(b,a); + d[0] = NR_DEMUL_321(r,a); + d[1] = NR_DEMUL_321(g,a); + d[2] = NR_DEMUL_321(b,a); d[3] = NR_NORMALIZE_21(a); } else { unsigned int ca; /* Full composition */ ca = NR_COMPOSEA_213(a, d[3]); - d[0] = NR_COMPOSEPNN_221131 (r, a, d[0], d[3], ca); - d[1] = NR_COMPOSEPNN_221131 (g, a, d[1], d[3], ca); - d[2] = NR_COMPOSEPNN_221131 (b, a, d[2], d[3], ca); + d[0] = NR_COMPOSEPNN_321131 (r, a, d[0], d[3], ca); + d[1] = NR_COMPOSEPNN_321131 (g, a, d[1], d[3], ca); + d[2] = NR_COMPOSEPNN_321131 (b, a, d[2], d[3], ca); d[3] = NR_NORMALIZE_31(ca); } } @@ -272,19 +279,19 @@ nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_n (unsigned char *px, int w, int h } a = (a*alpha + rounding_fix) >> dbits; if (a != 0) { - r = (r + rounding_fix) >> dbits; - g = (g + rounding_fix) >> dbits; - b = (b + rounding_fix) >> dbits; + r = (r*alpha + rounding_fix) >> dbits; + g = (g*alpha + rounding_fix) >> dbits; + b = (b*alpha + rounding_fix) >> dbits; if ((a == 255*255) || (d[3] == 0)) { /* Transparent BG, premul src */ - d[0] = NR_NORMALIZE_21(r); - d[1] = NR_NORMALIZE_21(g); - d[2] = NR_NORMALIZE_21(b); + d[0] = NR_NORMALIZE_31(r); + d[1] = NR_NORMALIZE_31(g); + d[2] = NR_NORMALIZE_31(b); d[3] = NR_NORMALIZE_21(a); } else { - d[0] = NR_COMPOSEPPP_2211 (r, a, d[0]); - d[1] = NR_COMPOSEPPP_2211 (g, a, d[1]); - d[2] = NR_COMPOSEPPP_2211 (b, a, d[2]); + d[0] = NR_COMPOSEPPP_3211 (r, a, d[0]); + d[1] = NR_COMPOSEPPP_3211 (g, a, d[1]); + d[2] = NR_COMPOSEPPP_3211 (b, a, d[2]); d[3] = NR_COMPOSEA_211(a, d[3]); } } @@ -309,11 +316,14 @@ void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, in int i; if (alpha == 0) return; + if (alpha>255) { + g_warning("In transform PPN alpha=%u>255",alpha); + } - // Both alpha and color components are stored temporarily with a range of [0,255^2], so more supersampling and we get an overflow - if (xd+yd>16) { - xd = 8; - yd = 8; + // The color component is stored temporarily with a range of [0,255^3], so more supersampling and we get an overflow (fortunately Inkscape's preferences also doesn't allow a higher setting) + if (xd+yd>8) { + xd = 4; + yd = 4; } dbits = xd + yd; diff --git a/src/libnr/nr-pixops.h b/src/libnr/nr-pixops.h index 417e5e2c9..7eafd1a9d 100644 --- a/src/libnr/nr-pixops.h +++ b/src/libnr/nr-pixops.h @@ -53,6 +53,7 @@ static inline unsigned int NR_COMPOSENNP_11113(unsigned int fc, unsigned int fa, static inline unsigned int NR_COMPOSENNP_11111(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba) { return NR_NORMALIZE_31(NR_COMPOSENNP_11113(fc, fa, bc, ba)); } // Operation: (1 - fa) * bc * ba + fc +static inline unsigned int NR_COMPOSEPNP_32114(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba) { return (255*255 - fa) * ba * bc + 255 * fc; } static inline unsigned int NR_COMPOSEPNP_22114(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba) { return (255*255 - fa) * ba * bc + 255*255 * fc; } static inline unsigned int NR_COMPOSEPNP_11113(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba) { return (255 - fa) * ba * bc + 255*255 * fc; } static inline unsigned int NR_COMPOSEPNP_22111(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba) { return NR_NORMALIZE_41(NR_COMPOSEPNP_22114(fc, fa, bc, ba)); } @@ -65,6 +66,7 @@ static inline unsigned int NR_COMPOSENNN_111121(unsigned int fc, unsigned int fa // Operation: ((1 - fa) * bc * ba + fc)/a // Reuses non-normalized versions of NR_COMPOSEPNP +static inline unsigned int NR_COMPOSEPNN_321131(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba, unsigned int a) { return DIV_ROUND(NR_COMPOSEPNP_32114(fc, fa, bc, ba), a); } static inline unsigned int NR_COMPOSEPNN_221131(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba, unsigned int a) { return DIV_ROUND(NR_COMPOSEPNP_22114(fc, fa, bc, ba), a); } static inline unsigned int NR_COMPOSEPNN_111121(unsigned int fc, unsigned int fa, unsigned int bc, unsigned int ba, unsigned int a) { return DIV_ROUND(NR_COMPOSEPNP_11113(fc, fa, bc, ba), a); } @@ -81,13 +83,15 @@ static inline unsigned int NR_COMPOSENPP_1111(unsigned int fc, unsigned int fa, // Operation: (1 - fa) * bc + fc // (1-fa)*bc+fc = bc-fa*bc+fc = (bc+fc)-fa*bc // This rewritten form results in faster code (found out through testing) -static inline unsigned int NR_COMPOSEPPP_2224(unsigned int fc, unsigned int fa, unsigned int bc) { return 255*255*(bc+fc) - fa*bc; } +static inline unsigned int NR_COMPOSEPPP_2224(unsigned int fc, unsigned int fa, unsigned int bc) { return 255*255*(bc+fc) - fa*bc; } // Note that this can temporarily overflow (but it probably doesn't cause problems) // NR_COMPOSEPPP_2224 assumes that fa and fc have a common component (fa=a*x and fc=c*x), because then the maximum value is: // (255*255-255*x)*255*255 + 255*x*255*255 = 255*255*( (255*255-255*x) + 255*x ) = 255*255*255*( (255-x)+x ) = 255*255*255*255 +static inline unsigned int NR_COMPOSEPPP_3213(unsigned int fc, unsigned int fa, unsigned int bc) { return 255*255*bc + fc - fa*bc; } static inline unsigned int NR_COMPOSEPPP_2213(unsigned int fc, unsigned int fa, unsigned int bc) { return 255*(255*bc+fc) - fa*bc; } static inline unsigned int NR_COMPOSEPPP_1213(unsigned int fc, unsigned int fa, unsigned int bc) { return 255*255*(bc+fc) - fa*bc; } static inline unsigned int NR_COMPOSEPPP_1112(unsigned int fc, unsigned int fa, unsigned int bc) { return 255*(bc+fc) - fa*bc; } static inline unsigned int NR_COMPOSEPPP_2221(unsigned int fc, unsigned int fa, unsigned int bc) { return NR_NORMALIZE_41(NR_COMPOSEPPP_2224(fc, fa, bc)); } +static inline unsigned int NR_COMPOSEPPP_3211(unsigned int fc, unsigned int fa, unsigned int bc) { return NR_NORMALIZE_31(NR_COMPOSEPPP_3213(fc, fa, bc)); } static inline unsigned int NR_COMPOSEPPP_2211(unsigned int fc, unsigned int fa, unsigned int bc) { return NR_NORMALIZE_31(NR_COMPOSEPPP_2213(fc, fa, bc)); } static inline unsigned int NR_COMPOSEPPP_1211(unsigned int fc, unsigned int fa, unsigned int bc) { return NR_NORMALIZE_21(NR_COMPOSEPPP_1213(fc, fa, bc)); } static inline unsigned int NR_COMPOSEPPP_1111(unsigned int fc, unsigned int fa, unsigned int bc) { return NR_NORMALIZE_21(NR_COMPOSEPPP_1112(fc, fa, bc)); } -- 2.30.2