I haven't posted for a while - I've been busy coding. Something new in the works that should be available in a month or two.
But I do want to quickly publish something I haven't seen documented before, which is how you can do RGB to HSV conversions in a CIFilter. HSV (Hue, Saturation, Value) representations are useful in a number of image manipulations, and CIFilters are part of Apple's image processing in OS X and iOS, and use a reduced version of the OpenGL shader language.
In general, HSV conversion in OpenGL shader language are a problem, because of the conditionals, which shader language aren't good at. Some RGB<->HSV conversions in Open GL shader language have been published before, but all the ones I've seen use functions that aren't available in the subset of the shader language that is available in a CIFilter.
This implementation takes some ideas about the use of the "step" function from Ian Taylor's "normal" shader language implementation.
The CIFilter below adjusts exposure and saturation by converting to HSV, adjusting S and V, and converting back to RGB. You can test this by just pasting it into Quartz Composer. Of course, if all you want to do is to adjust exposure and saturation, there are easier ways than HSV - this is just a demo!
Anyway, without more talk:
/*
A Core Image kernel routine that computes RGB<->HSV.
As a demo, this just adjusts exposure and saturation by multiplying.
H range is 0-6, S and V 0-1
Alpha is preserved unchanged
*/
vec4 HSVtoRGB(vec4 HSV)
{
vec4 hue;
hue.x = abs(HSV.x - 3.0) - 1.0;
hue.y = 2.0 - abs(HSV.x - 2.0);
hue.z = 2.0 - abs(HSV.x - 4.0);
return ((clamp(hue,0.0,1.0) - 1.0) * HSV.y + 1.0) * HSV.z;
}
vec4 RGBtoHSV(vec4 RGB)
{
vec4 HSV;
float maxV = max(RGB.r, max(RGB.g, RGB.b));
float C = maxV - min(RGB.r, min(RGB.g, RGB.b));
float D = step(0.0, -C);
HSV.z = maxV;
HSV.y = C / (maxV + D);
vec4 Delta = (maxV - RGB) / (C + D);
Delta -= Delta.brga;
Delta += vec4(2.0,4.0,6.0,0.0);
Delta *= step(maxV, RGB.gbra);
HSV.x = fract(max(Delta.r, max(Delta.g, Delta.b)) / 6.0)*6.0;
return HSV;
}
kernel vec4 coreImageKernel(sampler image, float exposure, float saturation)
{
vec4 i;
vec4 o;
vec4 hsv;
i = unpremultiply(sample(image, samplerCoord(image)));
hsv = RGBtoHSV(i);
// Whatever processing is required here……
hsv.z *= exposure;
hsv.y *= saturation;
o = HSVtoRGB(hsv);
// Maintain alpha
o.a = i.a;
return premultiply(o);
}
Add a comment