Pixel Bender Toolkit:BlendmodesHSL filter
From Adobe Labs
// http://gimp-savvy.com/BOOK/index.html?node49.html
<languageVersion : 1.0;> kernel blendmodes_hsl <
namespace : "default"; vendor : "tvzero"; version : 1; description : "HSL Blendmodes";
> {
parameter int blendmode <
minValue:int(0);
maxValue:int(4);
defaultValue:int(0);
description:"Choose Blendmode (0=normal, 1=hue, 2=saturation, 3=lightness, 4=color)";
>;
input image4 layer1;
input image4 layer2;
output pixel4 result;
void evaluatePixel()
{
pixel4 pxl1 = sampleNearest(layer1, outCoord());
pixel4 pxl2 = sampleNearest(layer2, outCoord());
float h, s, v;
float h1,s1,v1,h2,s2,v2;
// standard NTSC weights of 0.299, 0.587, and 0.114 not used here.
float rwgt = 0.3086;
float gwgt = 0.6094;
float bwgt = 0.0820;
float r1 = pxl1.r;
float g1 = pxl1.g;
float b1 = pxl1.b;
float a1 = pxl1.a;
float r2 = pxl2.r;
float g2 = pxl2.g;
float b2 = pxl2.b;
float a2 = pxl2.a;
float min, max, delta;
// <BOTTOM>
min = min( r1, min(g1, b1) );
max = max( r1, max(g1, b1) );
v1 = max;
delta = max - min;
s1 = delta / max;
s1 = ( max != 0.0 ) ? s1 : 0.0;
h1 = ( max != 0.0 ) ? 0.0 : -1.0;
float h1r = ( g1 - b1 ) / delta; // between yellow & magenta
float h1g = 2.0 + ( b1 - r1 ) / delta; // between cyan & yellow
float h1b = 4.0 + ( r1 - g1 ) / delta; // between magenta & cyan
float h1alt = ( g1 == max ) ? h1g : h1b; // choose between g/b
h1 = ( r1== max ) ? h1r : h1alt;
h1 *= 60.0;
h1 += ( h1 < 0.0 ) ? 360.0 : 0.0;
// </BOTTOM>
// <TOP>
min = min( r2, min(g2, b2) );
max = max( r2, max(g2, b2) );
v2 = max;
delta = max - min;
s2 = delta / max;
s2 = ( max != 0.0 ) ? s2 : 0.0;
h2 = ( max != 0.0 ) ? 0.0 : -1.0;
float h2r = ( g2 - b2 ) / delta; // between yellow & magenta
float h2g = 2.0 + ( b2 - r2 ) / delta; // between cyan & yellow
float h2b = 4.0 + ( r2 - g2 ) / delta; // between magenta & cyan
float h2alt = ( g2 == max ) ? h2g : h2b; // choose between g/b
h2 = ( r2== max ) ? h2r : h2alt;
h2 *= 60.0;
h2 += ( h2 < 0.0 ) ? 360.0 : 0.0;
// </TOP>
// HSL blendmodes
float3 blendmode_hue = float3(h2,s1,v1);
float3 blendmode_saturation = float3(h1,s2,v1);
float3 blendmode_lightness = float3(h1,s1,v2);
float3 blendmode_color = float3(h2,s2,v1);
float3 blend = float3(h2,s2,v2);
blend = (blendmode == 1) ? blendmode_hue : blend;
blend = (blendmode == 2) ? blendmode_saturation : blend;
blend = (blendmode == 3) ? blendmode_lightness : blend;
blend = (blendmode == 4) ? blendmode_color : blend;
h = blend.x;
s = blend.y;
v = blend.z;
// Convert result back to RGB
float r,g,b;
int i;
float f, p, q, t;
h /= 60.0; // sector 0 to 5
i = int(floor( h ));
f = h - float(i); // factorial part of h
p = v * ( 1.0 - s );
q = v * ( 1.0 - s * f );
t = v * ( 1.0 - s * ( 1.0 - f ) );
float3 outrgb = float3(v,v,v);
float3 sector0 = float3(v,t,p);
float3 sector1 = float3(q,v,p);
float3 sector2 = float3(p,v,t);
float3 sector3 = float3(p,q,v);
float3 sector4 = float3(t,p,v);
float3 sector5 = float3(v,p,q);
outrgb = sector5;
outrgb = (i==0) ? sector0 : outrgb;
outrgb = (i==1) ? sector1 : outrgb;
outrgb = (i==2) ? sector2 : outrgb;
outrgb = (i==3) ? sector3 : outrgb;
outrgb = (i==4) ? sector4 : outrgb;
float3 bw = float3(v,v,v);
outrgb = (s==0.0) ? bw : outrgb;
result.rgb = outrgb;
result.a = 1.0;
}
}
