Reputation: 3718
I'm trying to create image filter that will shift color of the image. In order to do this I need to convert rgb color to hsl and after shift, convert hsl back to rgb. I make some researches and found formulas that can help me with this task.
I implement them in my playground using Swift just to test if they are reliable and they are. I won't post Swift code here just to keep things clean, but I'll show my test results:
input: rgb (61, 117,237) or (0.24,0.46,0.93)
result:
rgb2hsl [0.613527 0.831325 0.585] or (221, 83, 58.5) //hsl
hsl2rgb [0.24 0.46 0.93] //back to rgb
Great! So far so good.
Now we need to convert our Swift code to Core Image Kernel Language (CIKL). And here it is:
float hue2rgb(float f1, float f2, float hue) {
if (hue < 0) {
hue += 1.0;
}
else if (hue > 1) {
hue -= 1.0;
}
float res;
if (6*hue<1) {
res = f1 + (f2 - f1) * 6 * hue;
}
else if (2*hue<1) {
res = f2;
}
else if (3*hue<2) {
res = f1 + (f2 - f1) * (2.0/3.0 - hue) * 6;
}
else {
res = f1;
}
return res;
}
vec3 hsl2rgb(vec3 hsl) {
vec3 rgb;
if (hsl.y == 0) {
rgb = vec3(hsl.z,hsl.z,hsl.z);
}
else {
float f2;
if (hsl.z < 0.5) {
f2 = hsl.z * (1.0 + hsl.y);
}
else {
f2 = hsl.z + hsl.y - hsl.y * hsl.z;
}
float f1 = 2 * hsl.z - f2;
float r = hue2rgb(f1, f2, hsl.x + 1.0/3.0);
float g = hue2rgb(f1, f2, hsl.x);
float b = hue2rgb(f1, f2, hsl.x - 1.0/3.0);
rgb = vec3(r,g,b);
}
return rgb;
}
vec3 rgb2hsl(vec3 rgb) {
float maxC = max(rgb.x, max(rgb.y,rgb.z));
float minC = min(rgb.x, min(rgb.y,rgb.z));
float l = (maxC + maxC)/2.0;
float h = 0;
float s = 0;
if (maxC != minC) {
float d = maxC - minC;
s = l > 0.5 ? d / (2.0 - maxC - minC) : d / (maxC + minC);
if (maxC == rgb.x) {
h = (rgb.y - rgb.z) / d + (rgb.y < rgb.z ? 6.0 : 0);
} else if (maxC == rgb.y) {
h = (rgb.z - rgb.x) / d + 2.0;
}
else {
h = (rgb.x - rgb.y) / d + 4.0;
}
h /= 6.0;
}
return vec3(h,s,l);
}
And here comes the problem. I'm not able to get right values using this functions in my filter. To check everything I made a Quartz Composer Patch. Since I didn't find any print/log option in CIKL, I made this to check if my conversions work right:
The logic of this patch: my filter takes color as an input, convert it to hsl and back to rgb and returns it; image input ignored for now.
Kernel func of my filter:
kernel vec4 kernelFunc(__sample pixel, __color color) {
vec3 vec = color.rgb;
vec3 hsl = rgb2hsl(vec);
return vec4(hsl2rgb(hsl), 1);
}
Filter includes functions listed above.
The result I see in the viewer is:
Image on the right is cropped constant color image from the input color.
The left image is the output from our filter.
Digital color picker returns rgb (237, 239.7, 252) for left image.
I have no more ideas how to debug this thing and find a problem. Any help will be highly appreciated. Thanks.
Upvotes: 3
Views: 1525
Reputation: 3718
I found the problem. It was me, converting code from Swift to CIKL I made a stupid mistake that was very hard to find, because you have no print / log tools in CIKL or I don't know about it. Anyway, the problem was in the rgb2hsl function:
float l = (maxC + maxC)/2.0; // WRONG
it should be:
float l = (maxC + minC)/2.0;
Hope it'll help someone in the future.
Upvotes: 5