This changes fixes issues with the non-separable blend modes. They were not producing the correct results if alpha was involved.
I fixed the math so everything happens in premultiplied alpha so there is no loss in precision. I also fixed the math of color-burn and color-dodge. Author: cabanier@gmail.com Reviewed By: reed@google.com Review URL: https://chromiumcodereview.appspot.com/12662006 git-svn-id: http://skia.googlecode.com/svn/trunk@8283 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
c1641fc922
commit
311d4eafab
@ -290,57 +290,41 @@ static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
|
||||
static inline int colordodge_byte(int sc, int dc, int sa, int da) {
|
||||
int diff = sa - sc;
|
||||
int rc;
|
||||
if (0 == diff) {
|
||||
if (0 == dc) {
|
||||
return SkAlphaMulAlpha(sc, 255 - da);
|
||||
} else if (0 == diff) {
|
||||
rc = sa * da + sc * (255 - da) + dc * (255 - sa);
|
||||
rc = SkDiv255Round(rc);
|
||||
} else {
|
||||
int tmp = (dc * sa << 15) / (da * diff);
|
||||
rc = SkDiv255Round(sa * da) * tmp >> 15;
|
||||
// don't clamp here, since we'll do it in our modeproc
|
||||
diff = dc * sa / diff;
|
||||
rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
|
||||
}
|
||||
return rc;
|
||||
return clamp_div255round(rc);
|
||||
}
|
||||
static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
|
||||
// added to avoid div-by-zero in colordodge_byte
|
||||
if (0 == dst) {
|
||||
return src;
|
||||
}
|
||||
|
||||
int sa = SkGetPackedA32(src);
|
||||
int da = SkGetPackedA32(dst);
|
||||
int a = srcover_byte(sa, da);
|
||||
int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
|
||||
int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
|
||||
int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
|
||||
r = clamp_max(r, a);
|
||||
g = clamp_max(g, a);
|
||||
b = clamp_max(b, a);
|
||||
return SkPackARGB32(a, r, g, b);
|
||||
}
|
||||
|
||||
// kColorBurn_Mode
|
||||
static inline int colorburn_byte(int sc, int dc, int sa, int da) {
|
||||
int rc;
|
||||
if (dc == da && 0 == sc) {
|
||||
rc = sa * da + dc * (255 - sa);
|
||||
if (dc == da) {
|
||||
rc = sa * da + sc * (255 - da) + dc * (255 - sa);
|
||||
} else if (0 == sc) {
|
||||
return SkAlphaMulAlpha(dc, 255 - sa);
|
||||
} else {
|
||||
int tmp = (sa * (da - dc) * 256) / (sc * da);
|
||||
if (tmp > 256) {
|
||||
tmp = 256;
|
||||
}
|
||||
int tmp2 = sa * da;
|
||||
rc = tmp2 - (tmp2 * tmp >> 8) + sc * (255 - da) + dc * (255 - sa);
|
||||
int tmp = (da - dc) * sa / sc;
|
||||
rc = sa * (da - ((da < tmp) ? da : tmp))
|
||||
+ sc * (255 - da) + dc * (255 - sa);
|
||||
}
|
||||
return SkDiv255Round(rc);
|
||||
return clamp_div255round(rc);
|
||||
}
|
||||
static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
|
||||
// added to avoid div-by-zero in colorburn_byte
|
||||
if (0 == dst) {
|
||||
return src;
|
||||
}
|
||||
|
||||
int sa = SkGetPackedA32(src);
|
||||
int da = SkGetPackedA32(dst);
|
||||
int a = srcover_byte(sa, da);
|
||||
@ -438,7 +422,7 @@ static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
|
||||
// See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
|
||||
static inline int Lum(int r, int g, int b)
|
||||
{
|
||||
return (r * 77 + g * 151 + b * 28) >> 8;
|
||||
return SkDiv255Round(r * 77 + g * 150 + b * 28);
|
||||
}
|
||||
|
||||
static inline int min2(int a, int b) { return a < b ? a : b; }
|
||||
@ -452,7 +436,7 @@ static inline int Sat(int r, int g, int b) {
|
||||
|
||||
static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
|
||||
if(*Cmax > *Cmin) {
|
||||
*Cmid = (((*Cmid - *Cmin) * s ) / (*Cmax - *Cmin));
|
||||
*Cmid = SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
|
||||
*Cmax = s;
|
||||
} else {
|
||||
*Cmax = 0;
|
||||
@ -480,35 +464,35 @@ static inline void SetSat(int* r, int* g, int* b, int s) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline void clipColor(int* r, int* g, int* b) {
|
||||
static inline void clipColor(int* r, int* g, int* b, int a) {
|
||||
int L = Lum(*r, *g, *b);
|
||||
int n = minimum(*r, *g, *b);
|
||||
int x = maximum(*r, *g, *b);
|
||||
if(n < 0) {
|
||||
*r = L + (((*r - L) * L) / (L - n));
|
||||
*g = L + (((*g - L) * L) / (L - n));
|
||||
*b = L + (((*b - L) * L) / (L - n));
|
||||
*r = L + SkMulDiv(*r - L, L, L - n);
|
||||
*g = L + SkMulDiv(*g - L, L, L - n);
|
||||
*b = L + SkMulDiv(*b - L, L, L - n);
|
||||
}
|
||||
|
||||
if(x > 255) {
|
||||
*r = L + (((*r - L) * (255 - L)) / (x - L));
|
||||
*g = L + (((*g - L) * (255 - L)) / (x - L));
|
||||
*b = L + (((*b - L) * (255 - L)) / (x - L));
|
||||
if (x > a) {
|
||||
*r = L + SkMulDiv(*r - L, a - L, x - L);
|
||||
*g = L + SkMulDiv(*g - L, a - L, x - L);
|
||||
*b = L + SkMulDiv(*b - L, a - L, x - L);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SetLum(int* r, int* g, int* b, int l) {
|
||||
static inline void SetLum(int* r, int* g, int* b, int a, int l) {
|
||||
int d = l - Lum(*r, *g, *b);
|
||||
*r += d;
|
||||
*g += d;
|
||||
*b += d;
|
||||
|
||||
clipColor(r, g, b);
|
||||
clipColor(r, g, b, a);
|
||||
}
|
||||
|
||||
// non-separable blend modes are done in non-premultiplied alpha
|
||||
#define blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
|
||||
clamp_div255round(sc * (255 - da) + dc * (255 - sa) + clamp_div255round(sa * da) * blendval)
|
||||
clamp_div255round(sc * (255 - da) + dc * (255 - sa) + blendval)
|
||||
|
||||
// kHue_Mode
|
||||
// B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
|
||||
@ -526,14 +510,11 @@ static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
|
||||
int Sr, Sg, Sb;
|
||||
|
||||
if(sa && da) {
|
||||
Sr = SkMulDiv255Round(sr, sa);
|
||||
Sg = SkMulDiv255Round(sg, sa);
|
||||
Sb = SkMulDiv255Round(sb, sa);
|
||||
int Dr = SkMulDiv255Round(dr, da);
|
||||
int Dg = SkMulDiv255Round(dg, da);
|
||||
int Db = SkMulDiv255Round(db, da);
|
||||
SetSat(&Sr, &Sg, &Sb, Sat(Dr, Dg, Db));
|
||||
SetLum(&Sr, &Sg, &Sb, Lum(Dr, Dg, Db));
|
||||
Sr = sr * sa;
|
||||
Sg = sg * sa;
|
||||
Sb = sb * sa;
|
||||
SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
|
||||
SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
|
||||
} else {
|
||||
Sr = 0;
|
||||
Sg = 0;
|
||||
@ -563,15 +544,11 @@ static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
|
||||
int Dr, Dg, Db;
|
||||
|
||||
if(sa && da) {
|
||||
int Sr = SkMulDiv255Round(sr, sa);
|
||||
int Sg = SkMulDiv255Round(sg, sa);
|
||||
int Sb = SkMulDiv255Round(sb, sa);
|
||||
Dr = SkMulDiv255Round(dr, da);
|
||||
Dg = SkMulDiv255Round(dg, da);
|
||||
Db = SkMulDiv255Round(db, da);
|
||||
int LumD = Lum(Dr, Dg, Db);
|
||||
SetSat(&Dr, &Dg, &Db, Sat(Sr, Sg, Sb));
|
||||
SetLum(&Dr, &Dg, &Db, LumD);
|
||||
Dr = dr * sa;
|
||||
Dg = dg * sa;
|
||||
Db = db * sa;
|
||||
SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
|
||||
SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
|
||||
} else {
|
||||
Dr = 0;
|
||||
Dg = 0;
|
||||
@ -601,13 +578,10 @@ static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
|
||||
int Sr, Sg, Sb;
|
||||
|
||||
if(sa && da) {
|
||||
Sr = SkMulDiv255Round(sr, sa);
|
||||
Sg = SkMulDiv255Round(sg, sa);
|
||||
Sb = SkMulDiv255Round(sb, sa);
|
||||
int Dr = SkMulDiv255Round(dr, da);
|
||||
int Dg = SkMulDiv255Round(dg, da);
|
||||
int Db = SkMulDiv255Round(db, da);
|
||||
SetLum(&Sr, &Sg, &Sb, Lum(Dr, Dg, Db));
|
||||
Sr = sr * da;
|
||||
Sg = sg * da;
|
||||
Sb = sb * da;
|
||||
SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
|
||||
} else {
|
||||
Sr = 0;
|
||||
Sg = 0;
|
||||
@ -637,13 +611,10 @@ static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
|
||||
int Dr, Dg, Db;
|
||||
|
||||
if(sa && da) {
|
||||
int Sr = SkMulDiv255Round(sr, sa);
|
||||
int Sg = SkMulDiv255Round(sg, sa);
|
||||
int Sb = SkMulDiv255Round(sb, sa);
|
||||
Dr = SkMulDiv255Round(dr, da);
|
||||
Dg = SkMulDiv255Round(dg, da);
|
||||
Db = SkMulDiv255Round(db, da);
|
||||
SetLum(&Dr, &Dg, &Db, Lum(Sr, Sg, Sb));
|
||||
Dr = dr * sa;
|
||||
Dg = dg * sa;
|
||||
Db = db * sa;
|
||||
SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
|
||||
} else {
|
||||
Dr = 0;
|
||||
Dg = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user