RGB颜色转换为5:6:5格式
此代码应该将RGB颜色转换为5:6:5格式的十六进制。 红色5位,绿色6位,蓝色5位。 我不知道为什么这不能描绘出正确的颜色。
有谁知道为什么?
int rgb(unsigned char r, unsigned char g, unsigned char b) {
if (r < 0 || 255 < r || g < 0 || 255 < g || b < 0 || b > 255)
return -1;
int result;
int red = r * 31 / 255;
int green = g * 63/ 255;
int blue = b * 31 / 255;
//int result = (red << 11) | (green << 5) | blue;
green = green << 5;
red = red << 11;
result = red | green | blue;
//tests
printf("nred: %x", red);
printf("ngreen: %x", green);
printf("blue: %xn", blue);
printf("result: %xn", result);
return result;
}
假设8位char
,你的unsigned char
参数必须已经在0-255范围内,所以你不需要检查。 你试图用来缩放颜色分量的乘法可能不是一个好方法。
一个更好的方法是将每个组件与一个掩码进行比较,以获得高5位(绿色为6),将它们移到适当的位置,并将它们组合在一起。 在移位时,记住要考虑到使用高位的事实......并且对于最后一个组件,由于不需要的位无论如何都将被移出,所以不需要与掩码进行AND。 所以这会得到你这样的东西(作为函数中唯一的一行):
return ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
(r & 0xf8)
得到的高5位的r
然后左移8位,所以它们从位置3..7移动到11..15。
(g & 0xfc)
获得的高6位g
。 那些然后左移3位,从2..7到5..10。
b
不需要被屏蔽......它只是右移3位。 它的高5位然后从3..7移到0..4,当它们移出时,它的低3位被丢弃。
然后将所有这些值进行“或”运算以得到RGB 5:6:5值,然后返回。
或者,如果您偏好转换AND,则可以使用:
return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
您也可以考虑将返回类型更改为无符号的16位类型,而不用担心返回错误值(这里没有任何类型的错误条件来检查)。
再看看你的问题,我真的不知道你在问什么。 无论如何,如果你觉得它有用,我会离开我的答案。
你的rgb(...)
函数需要三个字节的参数 - 它们每个都有8位。
首先考虑“红色”部分。 如果您通过XXXX XXXX(8位)并想要将它们转换为5位等效表示形式,则将值右移3位即可:
int red = r >> 3;
值XXXXXXXX将在管道字符处被截断:
XXXXX|xxx
因此只有标有大Xes的位才会保存到red
变量中。
蓝色也是一样,对于绿色部分,你必须将它向右移两(8 - 6 = 2)。
你可能想让你的函数像这样工作:
int rgb(unsigned char r, unsigned char g, unsigned char b) {
if (r < 0 || 255 < r || g < 0 || 255 < g || b < 0 || b > 255)
return -1;
unsigned char red = r >> 3;
unsigned char green = g >> 2;
unsigned char blue = b >> 3;
int result = (red << (5 + 6)) | (green << 5) | blue;
//tests
printf("red: %xn", red);
printf("green: %xn", green);
printf("blue: %xn", blue);
printf("result: %xn", result);
return result;
}
您需要一个显示二进制内容的函数,以便您可以“计数”这些位并更好地查找错误。 我的方法增加了一个舍入程序:
#include <stdio.h>
#include <math.h>
char* sprint_bin (unsigned a, unsigned count, char* bin)
{
char* p = bin;
unsigned i;
unsigned mask = pow(2,count-1);
unsigned b;
for (i = 0; i<count; ++i)
{
b = (a & mask) ? '1' : '0';
p += sprintf (p, "%c ",b);
mask >>= 1;
}
return bin;
}
unsigned rgb(unsigned char r, unsigned char g, unsigned char b) {
char bin[64];
int result;
printf("r: %sn", sprint_bin(r,8,bin));
printf("g: %sn", sprint_bin(g,8,bin));
printf("b: %sn", sprint_bin(b,8,bin));
// masks
unsigned red = (unsigned)(r & 0xF8) << 8;
unsigned green = (unsigned)(g & 0xFC) << 3;
unsigned blue = (unsigned)(b >> 3);
// rounding
if ((r & 4) && (r<0xF8)) red += 0x0800;
if ((g & 2) && (g<0xFC)) green += 0x20;
if ((b & 4) && (b<0xF8)) blue++;
// 5:6:5
result = red | green | blue;
// test
printf("red: %sn", sprint_bin(red,16,bin));
printf("green: %sn", sprint_bin(green,16,bin));
printf("blue: %sn", sprint_bin(blue,16,bin));
printf("result: %sn", sprint_bin(result,32,bin));
return result;
}
int main ()
{
rgb (0x81, 0x87, 0x9F);
return 0;
}
链接地址: http://www.djcxy.com/p/15395.html