2010-11-09 199 views
2

我注意到我的RGB888 24位到16位RGB565之间的转换程序导致颜色逐渐变暗,每次转换发生时......公式使用像这样的线性插值...RGB 24位到16位颜色转换 - 颜色变暗

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位的转换是相似的,但与反向插补......我不明白的价值观是如何保持越来越低,每次一颜色是循环的方程,如果他们是相反的......原来没有演员增加一倍,但我想如果我把它作为浮点除法它不会有衰退...但它仍然...

回答

3

当您将双精度值转换为WORD时,值将被截断。例如, (126 * 31)/ 255 = 15.439,它被截断为15.由于值被截断,所以在每次迭代中它们逐渐降低。您需要

继续该示例(将它们转换为整数之前通过添加0.5至所计算出的值)以引入舍入,则再取15和转换回: (15 * 255)/ 31 = 123.387,其截断为123

+0

很酷......让我试试看......谢谢你的想法 – oldSkool 2010-11-09 06:27:33

1

铸造doubleWORD未围绕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位来恢复它。

+0

我知道,但转换后,它似乎会保持稳定在一个值,但转换转换后的信息再次变暗......再次转换变暗......再次变暗......etc – oldSkool 2010-11-09 06:22:42

+0

换句话说,如果我将16位颜色转换为24位颜色,根本不要修改它,但将其转换回16位,它比原来的 – oldSkool 2010-11-09 06:26:06

+0

@ user482910更暗:我意识到这一点。我使用更多信息编辑了我的帖子。 – 2010-11-09 06:27:52

0

这是因为16位的工作原理与用值乘以2例如 2 * 2 * 2 * 2,它会出来作为RRGGBB和在相同的32位的情况下,将乘以整个比特值与2

简而言之,16位24位32位与rgb与2相乘,并以颜色形式显示您的值。
简要你应该找到位色的概念。检查维基百科希望它会帮助你

+0

这是一个四舍五入的问题,而不是掩码 – oldSkool 2010-12-13 05:12:27

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(查找表)。

+0

我忘了提及,同样适用于逆变换。 – CAFxX 2011-01-12 17:39:13

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