topical media & game development
graphic-flex-image-effects-10-source-isolateColor.pbk / pbk
<languageVersion: 1.0;>
kernel IsolateColor
<
namespace: "com.bobs27";
vendor: "Todd Yard";
version: 1;
description: "Isolates hue in image.";
>
{
parameter int3 color
<
minValue: int3(0, 0, 0);
maxValue: int3(255, 255, 255);
defaultValue: int3(255, 0, 0);
description: "The color to isolate.";
>;
parameter int hueThreshold
<
minValue: int(0);
maxValue: int(360);
defaultValue: int(10);
description: "The amount off-hue to allow.";
>;
parameter int luminanceThreshold
<
minValue: int(0);
maxValue: int(255);
defaultValue: int(100);
description: "The amount off-luminance to allow.";
>;
parameter int hideNonIsolated
<
minValue: int(0);
maxValue: int(1);
defaultValue: int(0);
description: "Whether alpha of 0 should be applied to non-isolated pixels.";
>;
const float3 grayValues = float3(0.3, 0.59, 0.11);
input image4 source;
output pixel4 result;
void
evaluatePixel()
{
float4 px = sampleNearest(source, outCoord());
// determine hue of color to isolate, between 0 and 360
int hue = 0;
int r = color.r;
int g = color.g;
int b = color.b;
if (r == g && g == b) {
hue = 0;
} else if (r >= g && g >= b) {
hue = 60 * (g - b)/(r - b);
} else if (g >= r && r >= b) {
hue = 60 + 60*(g - r)/(g - b);
} else if (g >= b && b >= r) {
hue = 120 + 60*(b - r)/(g - r);
} else if (b >= g && g >= r) {
hue = 180 + 60*(b - g)/(b - r);
} else if (b >= r && r >= g){
hue = 240 + 60*(r - g)/(b - g);
} else if (r >= b && b >= g) {
hue = 300 + 60*(r - b)/(r - g);
}
float isolateHue = float(hue);
// determine hue of color current pixel being evaluated, between 0 and 360
hue = 0;
r = int(px.r * 255.0);
g = int(px.g * 255.0);
b = int(px.b * 255.0);
if (r == g && g == b) {
hue = 0;
} else if (r >= g && g >= b) {
hue = 60 * (g - b)/(r - b);
} else if (g >= r && r >= b) {
hue = 60 + 60*(g - r)/(g - b);
} else if (g >= b && b >= r) {
hue = 120 + 60*(b - r)/(g - r);
} else if (b >= g && g >= r) {
hue = 180 + 60*(b - g)/(b - r);
} else if (b >= r && r >= g){
hue = 240 + 60*(r - g)/(b - g);
} else if (r >= b && b >= g) {
hue = 300 + 60*(r - b)/(r - g);
}
float pixelHue = float(hue);
// since hue "wraps" around the 360 degrees, do some manipulation so that
// values can be more easily evaluated when too close to end of spectrum
if (pixelHue - float(hueThreshold) < 0.0 && isolateHue + float(hueThreshold) > 360.0) {
pixelHue = 360.0 - float(hueThreshold);
} else if (pixelHue + float(hueThreshold) > 360.0 && isolateHue - float(hueThreshold) < 0.0) {
pixelHue = float(hueThreshold) - 360.0;
}
// determine the luminance/brightness/value of colors
float pixelLuminance = px.r * 0.3 +
px.g * 0.59 +
px.b * 0.11;
float isolateLuminance = float(color.r)/255.0 * 0.3 +
float(color.g)/255.0 * 0.59 +
float(color.b)/255.0 * 0.11;
// if luminance and hue are NOT within thresholds...
if (abs(pixelHue - isolateHue) > float(hueThreshold) ||
abs(pixelLuminance - isolateLuminance) > float(luminanceThreshold)/255.0
) {
// either hide pixel completely by setting alpha to 0
if (hideNonIsolated == 1) {
px.a = 0.0;
// or recolor pixel to grayscale
} else {
float distanceToDesaturatedValues = dot(px.rgb, grayValues);
px.rgb = float3(distanceToDesaturatedValues);
}
}
result = px;
}
}
(C) Æliens
18/6/2009
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.