此代码应该将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: %x\n", blue);
printf("result: %x\n", result);
return result;
}
答案 0 :(得分:1)
再看看你的问题后,我真的不知道你在问什么。无论如何,如果你发现它有用,我会留下我的答案。
您的rgb(...)
函数需要三个字节的参数 - 它们各有8位。
我们采取红色&#34;组件首先考虑在内。如果您传递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: %x\n", red);
printf("green: %x\n", green);
printf("blue: %x\n", blue);
printf("result: %x\n", result);
return result;
}
答案 1 :(得分:1)
假设8位char
,您的unsigned char
参数必须已经在0-255范围内,因此您不需要检查它。而你试图用来缩放颜色成分的乘法可能不是一个好方法。
更好的方法是使用掩码对每个组件进行AND以获得高5位(绿色为6),将它们移动到正确的位置,并将它们组合在一起。在移位时,记住要考虑到你使用高位的事实......对于最后一个组件,你不需要使用掩码进行AND,因为不需要的位无论如何都会被移出。所以这会得到这样的东西(作为你函数中的唯一一行):
return ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
(r & 0xf8)
获取r
的高5位。然后它们被移位8位,因此它们从位置3..7移动到11..15。
(g & 0xfc)
获取g
的高6位。然后将它们移位3位,从2..7到5..10。
b
不需要被屏蔽......它只是右移3位。然后它的高5位从3..7移动到0..4,当它们被移出时,它的低3位被丢弃。
然后将所有这些值进行OR运算以获得RGB 5:6:5的值,然后返回。
或者,如果您希望转换为AND,则可以使用:
return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
您也可以考虑将返回类型更改为无符号16位类型,而不必担心返回错误值(这里没有任何类型的错误条件要检查)。
答案 2 :(得分:0)
您需要一个向您显示二进制内容的函数,以便您可以“计算”这些位并更好地查找错误。我的方法增加了一个舍入程序:
#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: %s\n", sprint_bin(r,8,bin));
printf("g: %s\n", sprint_bin(g,8,bin));
printf("b: %s\n", 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: %s\n", sprint_bin(red,16,bin));
printf("green: %s\n", sprint_bin(green,16,bin));
printf("blue: %s\n", sprint_bin(blue,16,bin));
printf("result: %s\n", sprint_bin(result,32,bin));
return result;
}
int main ()
{
rgb (0x81, 0x87, 0x9F);
return 0;
}