kernel ColorDodge < namespace : "Flame"; vendor : "Adobe"; version : 1; description : "ColorDodge blend mode"; > { input image4 dst; input image4 src; output pixel4 result; void evaluatePixel() { pixel4 a = sampleNearest(dst,outCoord()); // cb pixel4 b = sampleNearest(src,outCoord()); // cs // remove premultiplied (srcCP/srcA, dstCP/dstA) pixel3 cb = a.rgb; pixel3 cs = b.rgb; if (a.a > 0.0) { cb.rgb = a.rgb / a.a; } if (b.a > 0.0) { cs.rgb = b.rgb / b.a; } // dstA' = (1-srcA)*dstA + srcA result.a = (1.0-b.a)*a.a + b.a; // temp for Blend(srcCP/srcA, dstCP/dstA) pixel3 blendResult; // = 0, if cb = 0 (*** this case is AE/PS and AGM only, not PDF spec) // = 1, if cb >= (1 -cs) // = cb / (1 -cs), otherwise if (cb.r == 0.0) { blendResult.r = 0.0; } else if ( cb.r >= (1.0 - cs.r)) { blendResult.r = 1.0; } else { blendResult.r = cb.r / (1.0 - cs.r); } if (cb.g == 0.0) { blendResult.g = 0.0; } else if ( cb.g >= (1.0 - cs.g)) { blendResult.g = 1.0; } else { blendResult.g = cb.g / (1.0 - cs.g); } if (cb.b == 0.0) { blendResult.b = 0.0; } else if ( cb.b >= (1.0 - cs.b)) { blendResult.b = 1.0; } else { blendResult.b = cb.b / (1.0 - cs.b); } // dstCP' = (1-srcA)*dstCP + (1-dstA)*srcCP + srcA*dstA*Blend(srcCP/srcA, dstCP/dstA) result.rgb = (1.0-b.a)*a.rgb + (1.0-a.a)*b.rgb + b.a*a.a*blendResult.rgb; } }