]> source.dussan.org Git - tigervnc.git/commitdiff
Converting to RGB might involve a precision increase
authorPierre Ossman <ossman@cendio.se>
Fri, 28 Feb 2014 10:54:34 +0000 (11:54 +0100)
committerPierre Ossman <ossman@cendio.se>
Mon, 7 Jul 2014 11:21:35 +0000 (13:21 +0200)
Need to do more than a simple shift to get the appropriate
new value. This isn't quite as exact as a proper multiplication
and division, but the error is so small it's not worth the
extra cycles.

common/rfb/PixelFormat.cxx
common/rfb/PixelFormat.h
common/rfb/PixelFormat.inl

index 8df5140fa89d5a3ecd89114b94e83526c5b09ce1..3604a6b24740c3696414ef0f0d3450652c2efade 100644 (file)
@@ -567,16 +567,23 @@ static int bits(rdr::U16 value)
 
 void PixelFormat::updateState(void)
 {
-  int redBits, greenBits, blueBits;
   int endianTest = 1;
 
   redBits = bits(redMax);
   greenBits = bits(greenMax);
   blueBits = bits(blueMax);
 
-  redConvShift = 16 - redBits;
-  greenConvShift = 16 - greenBits;
-  blueConvShift = 16 - blueBits;
+  maxBits = redBits;
+  if (greenBits > maxBits)
+    maxBits = greenBits;
+  if (blueBits > maxBits)
+    maxBits = blueBits;
+
+  minBits = redBits;
+  if (greenBits < minBits)
+    minBits = greenBits;
+  if (blueBits < minBits)
+    minBits = blueBits;
 
   if (((*(char*)&endianTest) == 0) != bigEndian)
     endianMismatch = true;
index aef309cf84d30c8031ab1da79d7cb8a30e0f9b90..dd4147449839ef8f6e0fe62a62830e7f6ef078df 100644 (file)
@@ -89,9 +89,9 @@ namespace rfb {
     int blueShift;
 
   protected:
-    int redConvShift;
-    int greenConvShift;
-    int blueConvShift;
+    /* Pre-computed values to keep algorithms simple */
+    int redBits, greenBits, blueBits;
+    int maxBits, minBits;
     bool endianMismatch;
   };
 }
index 90d8e6da9de7b25112c696cd369e7435f7e7ee85..5743e4955b217aa277cffad86b85d4bbb52b75d4 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright 2009 Pierre Ossman for Cendio AB
+/* Copyright 2009-2014 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -78,10 +78,28 @@ inline void PixelFormat::bufferFromPixel(rdr::U8* buffer, Pixel p) const
 inline void PixelFormat::rgbFromPixel(Pixel p, ColourMap* cm, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const
 {
   if (trueColour) {
-    /* We don't need to mask since we shift out unwanted bits */
-    *r = (p >> redShift) << redConvShift;
-    *g = (p >> greenShift) << greenConvShift;
-    *b = (p >> blueShift) << blueConvShift;
+    int mb, rb, gb, bb;
+
+    /* Bit replication is much cheaper than multiplication and division */
+
+    mb = minBits;
+    rb = redBits;
+    gb = greenBits;
+    bb = blueBits;
+
+    *r = (p >> redShift) << (16 - rb);
+    *g = (p >> greenShift) << (16 - gb);
+    *b = (p >> blueShift) << (16 - bb);
+
+    while (mb < 16) {
+      *r = *r | (*r >> rb);
+      *g = *g | (*g >> gb);
+      *b = *b | (*b >> bb);
+      mb <<= 1;
+      rb <<= 1;
+      gb <<= 1;
+      bb <<= 1;
+    }
   } else if (cm) {
     int ir, ig, ib;
     cm->lookup(p, &ir, &ig, &ib);
@@ -100,9 +118,28 @@ inline void PixelFormat::rgbFromPixel(Pixel p, ColourMap* cm, rdr::U16 *r, rdr::
 inline void PixelFormat::rgbFromPixel(Pixel p, ColourMap* cm, rdr::U8 *r, rdr::U8 *g, rdr::U8 *b) const
 {
   if (trueColour) {
-    *r = (p >> redShift) << (redConvShift - 8);
-    *g = (p >> greenShift) << (greenConvShift - 8);
-    *b = (p >> blueShift) << (blueConvShift - 8);
+    int mb, rb, gb, bb;
+
+    /* Bit replication is much cheaper than multiplication and division */
+
+    mb = minBits;
+    rb = redBits;
+    gb = greenBits;
+    bb = blueBits;
+
+    *r = (p >> redShift) << (8 - rb);
+    *g = (p >> greenShift) << (8 - gb);
+    *b = (p >> blueShift) << (8 - bb);
+
+    while (mb < 8) {
+      *r = *r | (*r >> rb);
+      *g = *g | (*g >> gb);
+      *b = *b | (*b >> bb);
+      mb <<= 1;
+      rb <<= 1;
+      gb <<= 1;
+      bb <<= 1;
+    }
   } else {
     rdr::U16 r2, g2, b2;