RGB 24至16位颜色转换 - 颜色变暗

时间:2010-11-09 06:13:50

标签: colors rgb linear-interpolation

我注意到我在RGB888 24位到16位RGB565之间转换的例程导致每次转换时颜色逐渐变暗......公式使用线性插值,如此...

typedef struct _RGB24 RGB24;
struct _RGB24 {
   BYTE B;
   BYTE G;
   BYTE R;
};

RGB24 *s; // source
WORD *d; // destination
WORD r;
WORD g;
WORD b;

// Code to convert from 24-bit to 16 bit
r = (WORD)((double)(s[x].r * 31) / 255.0);
g = (WORD)((double)(s[x].g * 63) / 255.0);
b = (WORD)((double)(s[x].b * 31) / 255.0);
d[x] = (r << REDSHIFT) | (g << GREENSHIFT) | (b << BLUESHIFT);

// Code to convert from 16-bit to 24-bit
s[x].r = (BYTE)((double)(((d[x] & REDMASK) >> REDSHIFT) * 255) / 31.0);
s[x].g = (BYTE)((double)(((d[x] & GREENMASK) >> GREENSHIFT) * 255) / 63.0);
s[x].b = (BYTE)((double)(((d[x] & BLUEMASK) >> BLUESHIFT) * 255) / 31.0);

从16位到24位的转换类似但是使用反向插值...我不明白如果它们是对立的,每次颜色循环通过等式时值如何越来越低。最初没有任何演员可以加倍,但我想如果我把它变成一个浮点除以它不会有衰减......但它仍然会... ...

5 个答案:

答案 0 :(得分:3)

将double值转换为WORD时,值将被截断。例如, (126 * 31)/ 255 = 15.439,它被截断为15.因为值被截断,所以它们在每次迭代时逐渐降低。您需要引入舍入(通过在将它们转换为整数之前将计算值加0.5)

继续该示例,然后取15并转换回: (15 * 255)/ 31 = 123.387,截断为123

答案 1 :(得分:3)

不要将浮点用于这样简单的事情。我看到的正常方法是截断下转换但延伸上转换(因此0b11111转到0b11111111)。

// Code to convert from 24-bit to 16 bit
r = s[x].r >> (8-REDBITS);
g = s[x].g >> (8-GREENBITS);
b = s[x].b >> (8-BLUEBITS);
d[x] = (r << REDSHIFT) | (g << GREENSHIFT) | (b << BLUESHIFT);

// Code to convert from 16-bit to 24-bit
s[x].r = (d[x] & REDMASK) >> REDSHIFT;                        // 000abcde
s[x].r = s[x].r << (8-REDBITS) | s[x].r >> (2*REDBITS-8);     // abcdeabc
s[x].g = (d[x] & GREENMASK) >> GREENSHIFT;                    // 00abcdef
s[x].g = s[x].g << (8-GREENBITS) | s[x].g >> (2*GREENBITS-8); // abcdefab
s[x].b = (d[x] & BLUEMASK) >> BLUESHIFT;                      // 000abcde
s[x].b = s[x].b << (8-BLUEBITS) | s[x].b >> (2*BLUEBITS-8);   // abcdeabc

答案 2 :(得分:1)

double转换为WORD不会使double值四舍五入 - 它会截断十进制数字。您需要使用某种舍入例程来获得舍入行为。通常你想要round half to evenThere is a Stack Overflow question on how to round in C++ if you need it


另请注意,从24位到16位的转换会永久丢失信息。当然,将24位信息装入16位是不可能的。你无法通过从16位转换回24位来获得它。

答案 3 :(得分:0)

这是因为16位与值相乘,例如乘以2 2 * 2 * 2 * 2它将以rrggbb形式出现,在相同的32位情况下,它将整数位值乘以2。

简而言之,16位24位32位与rgb乘以2一起工作,并以颜色的形式显示值。
 简而言之,你应该找到位颜色的概念。在维基百科上查看它希望它能帮到你

答案 4 :(得分:0)

因为你无论如何要转换为双倍,至少要用它来避免溢出,即替换

r = (WORD)((double)(s[x].r * 31) / 255.0);

r = (WORD)round(s[x].r / 255.0 * 31.0); 

这样编译器也应该在costant中折叠31.0 / 255.0。

显然,如果必须对大量像素重复这一过程,最好是创建并使用LUT(查找表)。

相关问题