]> source.dussan.org Git - tigervnc.git/commitdiff
Add support for TurboVNC pseudo-encodings and Grayscale JPEG compression so that...
authorDRC <dcommander@users.sourceforge.net>
Fri, 19 Aug 2011 04:57:18 +0000 (04:57 +0000)
committerDRC <dcommander@users.sourceforge.net>
Fri, 19 Aug 2011 04:57:18 +0000 (04:57 +0000)
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4641 3789f03b-4d11-0410-bbf8-ca57d06f2519

common/rfb/ConnParams.cxx
common/rfb/ConnParams.h
common/rfb/Encoder.h
common/rfb/JpegCompressor.cxx
common/rfb/JpegCompressor.h
common/rfb/SMsgWriter.cxx
common/rfb/TightEncoder.cxx
common/rfb/TightEncoder.h
common/rfb/encodings.h
common/rfb/tightEncode.h

index a6368851d81c990fcf93f2c3bf8dbaed758f2cf3..e44facc9d82c52e0f50619afa6467b97c37f99cb 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -34,7 +35,8 @@ ConnParams::ConnParams()
     supportsDesktopRename(false), supportsLastRect(false),
     supportsSetDesktopSize(false),
     customCompressLevel(false), compressLevel(6),
-    noJpeg(false), qualityLevel(-1), 
+    noJpeg(false), qualityLevel(-1), fineQualityLevel(-1),
+    subsampling(SUBSAMP_UNDEFINED),
     name_(0), nEncodings_(0), encodings_(0),
     currentEncoding_(encodingRaw), verStrPos(0)
 {
@@ -102,6 +104,8 @@ void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
   compressLevel = -1;
   noJpeg = true;
   qualityLevel = -1;
+  fineQualityLevel = -1;
+  subsampling = SUBSAMP_UNDEFINED;
   currentEncoding_ = encodingRaw;
 
   for (int i = nEncodings-1; i >= 0; i--) {
@@ -132,4 +136,18 @@ void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
     } else if (Encoder::supported(encodings[i]))
       currentEncoding_ = encodings[i];
   }
+
+  // If the TurboVNC fine quality/subsampling encodings exist, let them
+  // override the coarse TightVNC quality level
+  for (int i = nEncodings-1; i >= 0; i--) {
+    if (encodings[i] >= pseudoEncodingFineQualityLevel0 + 1 &&
+        encodings[i] <= pseudoEncodingFineQualityLevel100) {
+      noJpeg = false;
+      fineQualityLevel = encodings[i] - pseudoEncodingFineQualityLevel0;
+    } else if (encodings[i] >= pseudoEncodingSubsamp1X &&
+               encodings[i] <= pseudoEncodingSubsampGray) {
+      noJpeg = false;
+      subsampling = (JPEG_SUBSAMP)(encodings[i] - pseudoEncodingSubsamp1X);
+    }
+  }
 }
index c25e5630f9ef8a10978e27c96777f3df528abf1c..f81a358497898d2596a6fdd5abd7acd17a01dc46 100644 (file)
@@ -25,6 +25,7 @@
 #include <rdr/types.h>
 #include <rfb/PixelFormat.h>
 #include <rfb/ScreenSet.h>
+#include <rfb/JpegCompressor.h>
 
 namespace rdr { class InStream; }
 
@@ -84,6 +85,8 @@ namespace rfb {
     int compressLevel;
     bool noJpeg;
     int qualityLevel;
+    int fineQualityLevel;
+    JPEG_SUBSAMP subsampling;
 
   private:
 
index 893c013800cca57767759fde24b8dbd426ccfb3b..da2c5c09fca263c911a9123e4e84dcf3567b24c5 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,6 +22,7 @@
 #include <rfb/Rect.h>
 #include <rfb/encodings.h>
 #include <rfb/TransImageGetter.h>
+#include <rfb/JpegCompressor.h>
 
 namespace rfb {
   class SMsgWriter;
@@ -34,6 +36,7 @@ namespace rfb {
 
     virtual void setCompressLevel(int level) {};
     virtual void setQualityLevel(int level) {};
+    virtual void setFineQualityLevel(int quality, JPEG_SUBSAMP subsampling) {};
     virtual int getNumRects(const Rect &r) { return 1; }
 
     // writeRect() tries to write the given rectangle.  If it is unable to
index 7a870b0dd5756f8499d92f515b79c769de2837cf..33f6c418b504eb1dea41dc7207579987ac250726 100644 (file)
@@ -194,6 +194,8 @@ void JpegCompressor::compress(rdr::U8 *buf, int pitch, const Rect& r,
     cinfo.comp_info[0].h_samp_factor = 2;
     cinfo.comp_info[0].v_samp_factor = 1;
     break;
+  case SUBSAMP_GRAY:
+    jpeg_set_colorspace(&cinfo, JCS_GRAYSCALE);
   default:
     cinfo.comp_info[0].h_samp_factor = 1;
     cinfo.comp_info[0].v_samp_factor = 1;
index 6860b415d0bbd4ade6385fe65256ae409aae5215..668c9a00946049ee747f5dadfc24c17d154c74cf 100644 (file)
@@ -51,9 +51,11 @@ namespace rfb {
   } JPEG_DEST_MGR;
 
   enum JPEG_SUBSAMP {
-    SUBSAMP_NONE,
+    SUBSAMP_UNDEFINED = -1,
+    SUBSAMP_NONE = 0,
+    SUBSAMP_420,
     SUBSAMP_422,
-    SUBSAMP_420
+    SUBSAMP_GRAY
   };
 
   class JpegCompressor : public rdr::MemOutStream {
index 07ae37d51efc255636cfac3252f32d4bef12a0fb..f47f3eeb7d05c9c8b884e75bf2e0017d69c97e6d 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright (C) 2011 D. R. Commander.  All Rights Reserved.
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -102,6 +103,8 @@ void SMsgWriter::setupCurrentEncoder()
 
   encoders[encoding]->setCompressLevel(cp->compressLevel);
   encoders[encoding]->setQualityLevel(cp->qualityLevel);
+  encoders[encoding]->setFineQualityLevel(cp->fineQualityLevel,
+                                          cp->subsampling);
 }
 
 int SMsgWriter::getNumRects(const Rect &r)
index e35bad623a83f7b4a305d5606597491d407a8857..b7ef2236ef0c9a1f362b8eb0b1453ba6bfb9b548 100644 (file)
@@ -117,9 +117,21 @@ void TightEncoder::setCompressLevel(int level)
 void TightEncoder::setQualityLevel(int level)
 {
   if (level >= 0 && level <= 9) {
-    pjconf = &conf[level];
+    jpegQuality = conf[level].jpegQuality;
+    jpegSubsampling = conf[level].jpegSubsampling;
   } else {
-    pjconf = NULL;
+    jpegQuality = -1;
+    jpegSubsampling = SUBSAMP_UNDEFINED;
+  }
+}
+
+void TightEncoder::setFineQualityLevel(int quality, JPEG_SUBSAMP subsampling)
+{
+  if (quality >= 1 && quality <= 100) {
+    jpegQuality = quality;
+  }
+  if (subsampling >= SUBSAMP_NONE && subsampling <= SUBSAMP_GRAY) {
+    jpegSubsampling = subsampling;
   }
 }
 
@@ -333,6 +345,14 @@ bool TightEncoder::writeRect(const Rect& _r, TransImageGetter* _ig,
       sr.setXYWH(dx, dy, dw, dh);
       if (checkSolidTile(sr, &colorValue, false)) {
 
+         if (jpegSubsampling == SUBSAMP_GRAY && jpegQuality != -1) {
+           Colour rgb;
+           serverpf.rgbFromPixel(colorValue, NULL, &rgb);
+           rdr::U32 lum = ((257 * rgb.r) + (504 * rgb.g) + (98 * rgb.b)
+                           + 16500) / 1000;
+           colorValue = lum + (lum << 8) + (lum << 16);
+         }
+
         // Get dimensions of solid-color area.
         sr.setXYWH(dx, dy, r.br.x - dx, r.br.y - dy);
         findBestSolidArea(sr, colorValue, bestr);
index ae9672c048e25fe2f7365a9c191ee5024a4771d5..755d8829fac056a0fb5ce53fbcc918e0fe293fff 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <rdr/MemOutStream.h>
 #include <rdr/ZlibOutStream.h>
-#include <rfb/JpegCompressor.h>
 #include <rfb/TransImageGetter.h>
 #include <rfb/Encoder.h>
 
@@ -40,7 +39,7 @@ namespace rfb {
     int idxMaxColorsDivisor;
     int palMaxColorsWithJPEG;
     int jpegQuality;
-    JPEG_SUBSAMP jpegSubSample;
+    JPEG_SUBSAMP jpegSubsampling;
   };
 
   //
@@ -81,6 +80,7 @@ namespace rfb {
     static Encoder* create(SMsgWriter* writer);
     virtual void setCompressLevel(int level);
     virtual void setQualityLevel(int level);
+    virtual void setFineQualityLevel(int quality, JPEG_SUBSAMP subsampling);
     virtual int getNumRects(const Rect &r);
     virtual bool writeRect(const Rect& r, TransImageGetter* ig, Rect* actual);
     virtual ~TightEncoder();
@@ -153,7 +153,8 @@ namespace rfb {
     static const TIGHT_CONF conf[];
 
     const TIGHT_CONF* pconf;
-    const TIGHT_CONF* pjconf;
+    int jpegQuality;
+    JPEG_SUBSAMP jpegSubsampling;
   };
 
 }
index 16cd73a45f92cf9884acde7582358e468cd6899f..40f5f1010951b2ab6919eaf8574af435c0241fab 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyeight (C) 2011 D. R. Commander.  All Rights Reserved.
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -43,6 +44,16 @@ namespace rfb {
   const int pseudoEncodingCompressLevel0 = -256;
   const int pseudoEncodingCompressLevel9 = -247;
 
+  // TurboVNC-specific
+  const int pseudoEncodingFineQualityLevel0 = -512;
+  const int pseudoEncodingFineQualityLevel100 = -412;
+  const int pseudoEncodingSubsamp1X = -768;
+  const int pseudoEncodingSubsamp4X = -767;
+  const int pseudoEncodingSubsamp2X = -766;
+  const int pseudoEncodingSubsampGray = -765;
+  const int pseudoEncodingSubsamp8X = -764;
+  const int pseudoEncodingSubsamp16X = -763;
+
   int encodingNum(const char* name);
   const char* encodingName(int num);
 }
index 9b2b29d1c7d878a6342793964d5e383a6b1ed835..7cabb0a7975fbfa8143a8ec3fc8cb598aac2391f 100644 (file)
@@ -200,9 +200,11 @@ void TIGHT_ENCODE (const Rect& r, rdr::OutStream *os, bool forceSolid)
 
   if (forceSolid)
     palNumColors = 1;
+  else if (jpegSubsampling == SUBSAMP_GRAY && jpegQuality != -1)
+    palNumColors = 0;
   else {
     palMaxColors = r.area() / pconf->idxMaxColorsDivisor;
-    if (pjconf != NULL) palMaxColors = pconf->palMaxColorsWithJPEG;
+    if (jpegQuality != -1) palMaxColors = pconf->palMaxColorsWithJPEG;
     if (palMaxColors < 2 && r.area() >= pconf->monoMinRectSize) {
       palMaxColors = 2;
     }
@@ -211,7 +213,7 @@ void TIGHT_ENCODE (const Rect& r, rdr::OutStream *os, bool forceSolid)
       // This is so we can avoid translating the pixels when compressing
       // with JPEG, since it is unnecessary
       FAST_FILL_PALETTE(r, pixels, stride);
-      if(palNumColors != 0 || pjconf == NULL) {
+      if(palNumColors != 0 || jpegQuality == -1) {
         pixels = (PIXEL_T *)writer->getImageBuf(r.area());
         stride = r.width();
         ig->getImage(pixels, r);
@@ -229,7 +231,7 @@ void TIGHT_ENCODE (const Rect& r, rdr::OutStream *os, bool forceSolid)
   case 0:
     // Truecolor image
 #if (BPP != 8)
-    if (pjconf != NULL) {
+    if (jpegQuality != -1) {
       ENCODE_JPEG_RECT(os, pixels, stride, r);
       break;
     }
@@ -396,7 +398,7 @@ void ENCODE_JPEG_RECT (rdr::OutStream *os, PIXEL_T *buf, int stride,
 {
   jc.clear();
   jc.compress((rdr::U8 *)buf, stride * serverpf.bpp / 8, r, serverpf,
-    pjconf->jpegQuality, pjconf->jpegSubSample);
+    jpegQuality, jpegSubsampling);
   os->writeU8(0x09 << 4);
   os->writeCompactLength(jc.length());
   os->writeBytes(jc.data(), jc.length());