2

我注意到我在 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 位的转换是相似的,但使用反向插值......我不明白每次颜色在等式中循环时,如果它们是相反的,值是如何越来越低的......原来有没有加倍,但我想如果我把它做成一个浮点除法,它就不会有衰减......但它仍然......

4

5 回答 5

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
于 2011-03-23T11:40:29.313 回答
3

当您将双精度值转换为 WORD 时,这些值将被截断。例如,(126 * 31)/255 = 15.439,被截断为 15。因为值被截断,它们在每次迭代中逐渐变小。您需要引入舍入(通过在将计算值转换为整数之前将其添加 0.5)

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

于 2010-11-09T06:24:38.327 回答
1

转换doubleWORD不会对double值进行四舍五入 - 它会截断十进制数字。您需要使用某种舍入例程来获得舍入行为。通常,您希望将一半舍入到偶数如果需要,有一个关于如何在 C++ 中舍入的 Stack Overflow 问题


另请注意,从 24 位到 16 位的转换会永久丢失信息。当然,不可能将 24 位信息放入 16 位中。您无法通过从 16 位转换回 24 位来恢复它。

于 2010-11-09T06:20:04.080 回答
0

由于您无论如何都要转换为双精度,因此至少使用它来避免溢出,即替换

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

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

通过这种方式,编译器还应该将 31.0/255.0 折叠到一个成本中。

显然,如果必须对大量像素重复此操作,则最好创建并使用 LUT(查找表)。

于 2011-01-12T17:37:36.693 回答
0

这是因为 16 位与乘以 2 的值一起使用,例如 2*2*2*2,它会以 rrggbb 的形式出现,在同样的 32 位情况下,它将整个位值乘以 2。

简而言之,16 位 24 位 32 位适用于 rgb 与 2 的乘法,并以颜色的形式显示值。
简而言之,您应该找到位颜色的概念。在维基百科上查看它希望它对你有帮助

于 2010-11-20T07:04:12.990 回答