using namespace rfb;
rdr::U8 PixelFormat::upconvTable[256*8];
+rdr::U8 PixelFormat::downconvTable[256*8];
class PixelFormat::Init {
public:
{
int bits;
- // Bit replication is almost perfect, but not quite. And
+ // Shifting bits is almost perfect, but not quite. And
// a lookup table is still quicker when there is a large
// difference between the source and destination depth.
for (bits = 1;bits <= 8;bits++) {
int i, maxVal;
- rdr::U8 *subTable;
+ rdr::U8 *subUpTable;
+ rdr::U8 *subDownTable;
maxVal = (1 << bits) - 1;
- subTable = &upconvTable[(bits-1)*256];
+ subUpTable = &upconvTable[(bits-1)*256];
+ subDownTable = &downconvTable[(bits-1)*256];
for (i = 0;i <= maxVal;i++)
- subTable[i] = i * 255 / maxVal;
+ subUpTable[i] = i * 255 / maxVal;
- // Duplicate the table so that we don't have to care about
+ // Duplicate the up table so that we don't have to care about
// the upper bits when doing a lookup
for (;i < 256;i += maxVal+1)
- memcpy(&subTable[i], &subTable[0], maxVal+1);
+ memcpy(&subUpTable[i], &subUpTable[0], maxVal+1);
+
+ for (i = 0;i <= 255;i++)
+ subDownTable[i] = (i * maxVal + 128) / 255;
}
}
bool endianMismatch;
static rdr::U8 upconvTable[256*8];
+ static rdr::U8 downconvTable[256*8];
class Init;
friend class Init;
{
Pixel p;
- /* We don't need to mask since we shift out unwanted bits */
- p = ((Pixel)red >> (16 - redBits)) << redShift;
- p |= ((Pixel)green >> (16 - greenBits)) << greenShift;
- p |= ((Pixel)blue >> (16 - blueBits)) << blueShift;
+ p = (Pixel)downconvTable[(redBits-1)*256 + (red >> 8)] << redShift;
+ p |= (Pixel)downconvTable[(greenBits-1)*256 + (green >> 8)] << greenShift;
+ p |= (Pixel)downconvTable[(blueBits-1)*256 + (blue >> 8)] << blueShift;
return p;
}
{
Pixel p;
- p = ((Pixel)red >> (8 - redBits)) << redShift;
- p |= ((Pixel)green >> (8 - greenBits)) << greenShift;
- p |= ((Pixel)blue >> (8 - blueBits)) << blueShift;
+ p = (Pixel)downconvTable[(redBits-1)*256 + red] << redShift;
+ p |= (Pixel)downconvTable[(greenBits-1)*256 + green] << greenShift;
+ p |= (Pixel)downconvTable[(blueBits-1)*256 + blue] << blueShift;
return p;
}
const rdr::U8 *r, *g, *b;
int dstPad, srcPad;
- int redTruncShift, greenTruncShift, blueTruncShift;
+ const rdr::U8 *redDownTable, *greenDownTable, *blueDownTable;
- redTruncShift = 8 - redBits;
- greenTruncShift = 8 - greenBits;
- blueTruncShift = 8 - blueBits;
+ redDownTable = &downconvTable[(redBits-1)*256];
+ greenDownTable = &downconvTable[(greenBits-1)*256];
+ blueDownTable = &downconvTable[(blueBits-1)*256];
if (srcPF.bigEndian) {
r = src + (24 - srcPF.redShift)/8;
while (w_--) {
rdr::UOUT d;
- d = (*r >> redTruncShift) << redShift;
- d |= (*g >> greenTruncShift) << greenShift;
- d |= (*b >> blueTruncShift) << blueShift;
+ d = redDownTable[*r] << redShift;
+ d |= greenDownTable[*g] << greenShift;
+ d |= blueDownTable[*b] << blueShift;
#if OUTBPP != 8
if (endianMismatch)