2010-11-09 141 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