// Developed by Neil Kemp: http://neilkemp.us // All blending math (using C macros) was programmed by Nathan Moinvaziri at http://nathanm.com/?p=592 // Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php #include #include // B is the base channel - L is the foreground layer channel, O is opacity from 0.0f - 1.0f inline unsigned char blend_normal(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * (L) + (1.0f - O) * B); } inline unsigned char blend_lighten(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * ((L > B) ? L : B) + (1.0f - O) * B); } inline unsigned char blend_darken(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * ((L > B) ? B : L) + (1.0f - O) * B); } inline unsigned char blend_multiply(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * ((B * L) / 255) + (1.0f - O) * B); } inline unsigned char blend_average(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * ((B + L) / 2) + (1.0f - O) * B); } inline unsigned char blend_add(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * (_cpp_min(255, (B + L))) + (1.0f - O) * B); } inline unsigned char blend_subtract(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * ((B + L < 255) ? 0 : (B + L - 255)) + (1.0f - O) * B); } inline unsigned char blend_difference(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * (abs(B - L)) + (1.0f - O) * B); } inline unsigned char blend_negation(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * (255 - abs(255 - B - L)) + (1.0f - O) * B); } inline unsigned char blend_screen(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * (255 - (((255 - B) * (255 - L)) >> 8)) + (1.0f - O) * B); } inline unsigned char blend_exclusion(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * (B + L - 2 * B * L / 255) + (1.0f - O) * B); } inline unsigned char blend_overlay(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * ((L < 128) ? (2 * B * L / 255) : (255 - 2 * (255 - B) * (255 - L) / 255)) + (1.0f - O) * B); } inline unsigned char blend_soft_light(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * ((L < 128) ? (2 * ((B >> 1) + 64)) * ((float)L / 255) : (255 - (2 * (255 - ((B >> 1) + 64)) * (float)(255 - L) / 255))) + (1.0f - O) * B); } inline unsigned char blend_hard_light(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * ((B < 128) ? (2 * L * B / 255) : (255 - 2 * (255 - L) * (255 - B) / 255)) + (1.0f - O) * B); } inline unsigned char blend_color_dodge(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * ((L == 255) ? L : _cpp_min(255, ((B << 8 ) / (255 - L)))) + (1.0f - O) * B); } inline unsigned char blend_color_burn(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * ((L == 0) ? L : _cpp_max(0, (255 - ((255 - B) << 8 ) / L))) + (1.0f - O) * B); } inline unsigned char blend_linear_dodge(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * (_cpp_min(255, (B + L))) + (1.0f - O) * B); } inline unsigned char blend_linear_burn(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * ((B + L < 255) ? 0 : (B + L - 255)) + (1.0f - O) * B); } inline unsigned char blend_linear_light(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * ((2 * L) < 128) ? ((B + (2 * L) < 255) ? 0 : (B + (2 * L) - 255)) : (_cpp_min(255, (B + (2 * (L - 128))))) + (1.0f - O) * B); } inline unsigned char blend_vivid_light(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * (L < 128) ? (((2 * L) == 0) ? (2 * L) : _cpp_max(0, (255 - ((255 - B) << 8 ) / (2 * L)))) : (_cpp_min(255, (B + (2 * (L - 128))))) + (1.0f - O) * B); } inline unsigned char blend_pin_light(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * (L < 128) ? (((2 * L) > B) ? B : (2 * L)) : (((2 * (L - 128)) > B) ? (2 * (L - 128)) : B) + (1.0f - O) * B); } inline unsigned char blend_hard_mix(unsigned char B, unsigned char L, float O) { return (unsigned char)(O * (((L < 128) ? (((2 * L) == 0) ? (2 * L) : _cpp_max(0, (255 - ((255 - B) << 8 ) / (2 * L)))) : (_cpp_min(255, (B + (2 * (L - 128))))) < 128) ? 0 : 255) + (1.0f - O) * B); }