我正在寻找一种快速、准确的RGB到HSB和HSB到RGB的纯C实现。请注意,我特别寻找色相、饱和度、亮度,而不是HSL(亮度)。
当然,我已经进行了广泛的谷歌搜索,但速度是最重要的,我正在寻找任何可靠、快速、可靠的代码的具体建议。
当然,我已经进行了广泛的谷歌搜索,但速度是最重要的,我正在寻找任何可靠、快速、可靠的代码的具体建议。
#include <stdio.h>
#include <math.h>
typedef struct RGB_t { unsigned char red, green, blue; } RGB;
typedef struct HSB_t { float hue, saturation, brightness; } HSB;
/*
* Returns the hue, saturation, and brightness of the color.
*/
void RgbToHsb(struct RGB_t rgb, struct HSB_t* outHsb)
{
// TODO check arguments
float r = rgb.red / 255.0f;
float g = rgb.green / 255.0f;
float b = rgb.blue / 255.0f;
float max = fmaxf(fmaxf(r, g), b);
float min = fminf(fminf(r, g), b);
float delta = max - min;
if (delta != 0)
{
float hue;
if (r == max)
{
hue = (g - b) / delta;
}
else
{
if (g == max)
{
hue = 2 + (b - r) / delta;
}
else
{
hue = 4 + (r - g) / delta;
}
}
hue *= 60;
if (hue < 0) hue += 360;
outHsb->hue = hue;
}
else
{
outHsb->hue = 0;
}
outHsb->saturation = max == 0 ? 0 : (max - min) / max;
outHsb->brightness = max;
}
典型用法和测试:
int main()
{
struct RGB_t rgb = { 132, 34, 255 };
struct HSB_t hsb;
RgbToHsb(rgb, &hsb);
printf("RGB(%u,%u,%u) -> HSB(%f,%f,%f)\n", rgb.red, rgb.green, rgb.blue,
hsb.hue, hsb.saturation, hsb.brightness);
// prints: RGB(132,34,255) -> HSB(266.606354,0.866667,1.000000)
return 0;
}
快速RGB到HSV浮点转换来自lolengine.net,它采用了“常见”的RGB2HSV实现,并做出以下观察:
只有色调偏移K会改变。现在的想法是:
- 使用比较对三元组(r,g,b)进行排序
- 在排序三元组时构建K
- 执行最终计算
我们注意到,最后一次交换有效地改变了K和g-b的符号。由于两者都被添加并传递给fabs(),因此可以实际上省略符号反转。
最后一步看起来像C代码,但它们的最终形式是C++,可以轻松转换为C:
static void RGB2HSV(float r, float g, float b,
float &h, float &s, float &v)
{
float K = 0.f;
if (g < b)
{
std::swap(g, b);
K = -1.f;
}
if (r < g)
{
std::swap(r, g);
K = -2.f / 6.f - K;
}
float chroma = r - std::min(g, b);
h = fabs(K + (g - b) / (6.f * chroma + 1e-20f));
s = chroma / (r + 1e-20f);
v = r;
}