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

上一篇: RGB color converting into 5:6:5 format

下一篇: Converting RGB values into color