使用 Core Image Kernel Language 将 RGB 颜色转换为 HSL
Color conversion RGB to HSL using Core Image Kernel Language
我正在尝试创建可以改变图像颜色的图像过滤器。为此,我需要将 rgb 颜色转换为 hsl,并在转换后将 hsl 转换回 rgb。我进行了一些研究并找到了可以帮助我完成这项任务的公式。
我在我的操场上使用 Swift 实现了它们,只是为了测试它们是否可靠。我不会 post Swift 在这里编写代码只是为了保持整洁,但我会展示我的测试结果:
输入:rgb (61, 117,237) 或 (0.24,0.46,0.93)
结果:
rgb2hsl [0.613527 0.831325 0.585] or (221, 83, 58.5) //hsl
hsl2rgb [0.24 0.46 0.93] //back to rgb
太棒了!到目前为止一切顺利。
现在我们需要将 Swift 代码转换为 Core Image Kernel Language (CIKL)。
这是:
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);
}
问题来了。我无法在我的过滤器中使用此函数获得正确的值。为了检查所有内容,我制作了一个 Quartz Composer 补丁。
由于我在 CIKL 中没有找到任何 print/log 选项,我这样做是为了检查我的转换是否正确:
这个补丁的逻辑:我的滤镜将颜色作为输入,将其转换为 hsl 并返回 rgb 并 returns 它;现在忽略图像输入。
我的过滤器的内核函数:
kernel vec4 kernelFunc(__sample pixel, __color color) {
vec3 vec = color.rgb;
vec3 hsl = rgb2hsl(vec);
return vec4(hsl2rgb(hsl), 1);
}
过滤器包括上面列出的功能。
我在查看器中看到的结果是:
右边的图像是从输入颜色中裁剪出的恒定颜色图像。
左图是我们过滤器的输出。
数字颜色选择器 returns 左图的 rgb (237, 239.7, 252)。
我不知道如何调试这个东西并找到问题。任何帮助将不胜感激。谢谢。
我发现了问题。是我,将代码从 Swift 转换为 CIKL 我犯了一个很难发现的愚蠢错误,因为 CIKL 中没有打印/日志工具,或者我不知道。
无论如何,问题出在 rgb2hsl 函数中:
float l = (maxC + maxC)/2.0; // WRONG
应该是:
float l = (maxC + minC)/2.0;
希望它能对以后的人有所帮助。
我正在尝试创建可以改变图像颜色的图像过滤器。为此,我需要将 rgb 颜色转换为 hsl,并在转换后将 hsl 转换回 rgb。我进行了一些研究并找到了可以帮助我完成这项任务的公式。
我在我的操场上使用 Swift 实现了它们,只是为了测试它们是否可靠。我不会 post Swift 在这里编写代码只是为了保持整洁,但我会展示我的测试结果:
输入:rgb (61, 117,237) 或 (0.24,0.46,0.93)
结果:
rgb2hsl [0.613527 0.831325 0.585] or (221, 83, 58.5) //hsl
hsl2rgb [0.24 0.46 0.93] //back to rgb
太棒了!到目前为止一切顺利。
现在我们需要将 Swift 代码转换为 Core Image Kernel Language (CIKL)。 这是:
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);
}
问题来了。我无法在我的过滤器中使用此函数获得正确的值。为了检查所有内容,我制作了一个 Quartz Composer 补丁。 由于我在 CIKL 中没有找到任何 print/log 选项,我这样做是为了检查我的转换是否正确:
这个补丁的逻辑:我的滤镜将颜色作为输入,将其转换为 hsl 并返回 rgb 并 returns 它;现在忽略图像输入。
我的过滤器的内核函数:
kernel vec4 kernelFunc(__sample pixel, __color color) {
vec3 vec = color.rgb;
vec3 hsl = rgb2hsl(vec);
return vec4(hsl2rgb(hsl), 1);
}
过滤器包括上面列出的功能。
我在查看器中看到的结果是:
数字颜色选择器 returns 左图的 rgb (237, 239.7, 252)。
我不知道如何调试这个东西并找到问题。任何帮助将不胜感激。谢谢。
我发现了问题。是我,将代码从 Swift 转换为 CIKL 我犯了一个很难发现的愚蠢错误,因为 CIKL 中没有打印/日志工具,或者我不知道。 无论如何,问题出在 rgb2hsl 函数中:
float l = (maxC + maxC)/2.0; // WRONG
应该是:
float l = (maxC + minC)/2.0;
希望它能对以后的人有所帮助。