如何在C++中将16位十六进制颜色转换为RGB888值

How to convert 16 bit hex color to RGB888 values in C++

本文关键字:转换 颜色 RGB888 十六进制 16位 C++ 中将      更新时间:2023-10-16

我有uint16_t color,需要将其转换为RGB等效值。十六进制的设置使前5位表示红色,下6位表示绿色,最后5位表示蓝色。

到目前为止,我已经找到了一些接近解决方案的方法,但还不完全是由于截断。

void hexToRGB(uint16_t hexValue)
{
    int r = ((hexValue >> 11) & 0x1F);  // Extract the 5 R bits
    int g = ((hexValue >> 5) & 0x3F);   // Extract the 6 G bits
    int b = ((hexValue) & 0x1F);        // Extract the 5 B bits
    r = ((r * 255) / 31) - 4;
    g = ((g * 255) / 63) - 2;
    b = ((b * 255) / 31) - 4;
    printf("r: %d, g: %d, b: %dn",r, g, b);
}
int main()
{
    //50712=0xC618 
    hexToRGB(50712);    
    return 0;
}

上面的例子产生了r: 193, g: 192, b: 193,应该是r: 192, g: 192, b: 192我一直在用这个问题作为参考,但我本质上需要一个向后的解决方案来解决他们的问题。

以下内容如何:

unsigned r = (hexValue & 0xF800) >> 8;       // rrrrr... ........ -> rrrrr000
unsigned g = (hexValue & 0x07E0) >> 3;       // .....ggg ggg..... -> gggggg00
unsigned b = (hexValue & 0x1F) << 3;         // ............bbbbb -> bbbbb000
printf("r: %d, g: %d, b: %dn", r, g, b);

这将导致0xC618->1922192,但0xFFFF->24825248,即不是纯白。

如果你想0xFFFF是纯白的,你必须缩放,所以

unsigned r = (hexValue & 0xF800) >> 11;
unsigned g = (hexValue & 0x07E0) >> 5;
unsigned b = hexValue & 0x001F;
r = (r * 255) / 31;
g = (g * 255) / 63;
b = (b * 255) / 31;

然后0xC618->197194197,而不是预期的192192192,但0xFFFF是纯白,0x0000是纯黑。

没有"正确"的方法将RGB565比例转换为RGB888。每个颜色分量需要从其5位或6位范围缩放到8位范围,并且有不同的方法来实现这一点,每个方法通常在图像中产生不同类型的视觉伪影。

当在n位范围内缩放颜色时,我们可能会决定希望以下内容大致正确:

  • 绝对黑色(例如5位空间中的00000)必须映射到8位空间中绝对黑色
  • 绝对白色(例如5位空间中的11111)必须映射到8位空间中绝对白色

实现这一点意味着我们基本上希望将值从n位空间中的(2n-1)阴影缩放到8位空间中(28-1)阴影。也就是说,我们希望以某种方式有效地做到以下几点:

r_8 = (255 * r / 31)
g_8 = (255 * g / 63)
b_8 = (255 * b / 31)

通常采用的不同方法有:

  • 使用整数除法缩放
  • 使用浮动除法然后取整进行缩放
  • 将位移位到8位空间并添加最高有效位

后一种方法实际上是以下

r_8 = (r << 3) | (r >> 2)
g_8 = (g << 2) | (g >> 4)
b_8 = (b << 3) | (b >> 2)

对于5位值11000,这将导致8位值:

  • 197
  • 197
  • 198(11000000 | 110

类似地,您的6位值110000将产生8位值:

  • 194
  • 194
  • 195(11000000 | 11