RGB颜色转换为5:6:5格式

时间:2014-11-28 18:55:49

标签: c rgb

此代码应该将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;
}

3 个答案:

答案 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;
}