vncEncodeRRE.cpp
上传用户:sbftbdw
上传日期:2007-01-03
资源大小:379k
文件大小:10k
源码类别:

远程控制编程

开发平台:

Visual C++

  1. //  Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory
  2. //
  3. //  This file is part of the VNC system.
  4. //
  5. //  The VNC system is free software; you can redistribute it and/or modify
  6. //  it under the terms of the GNU General Public License as published by
  7. //  the Free Software Foundation; either version 2 of the License, or
  8. //  (at your option) any later version.
  9. //
  10. //  This program is distributed in the hope that it will be useful,
  11. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //  GNU General Public License for more details.
  14. //
  15. //  You should have received a copy of the GNU General Public License
  16. //  along with this program; if not, write to the Free Software
  17. //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
  18. //  USA.
  19. //
  20. // If the source code for the VNC system is not available from the place 
  21. // whence you received this file, check http://www.orl.co.uk/vnc or contact
  22. // the authors on vnc@orl.co.uk for information on obtaining it.
  23. // vncEncodeRRE
  24. // This file implements the vncEncoder-derived vncEncodeRRE class.
  25. // This class overrides some vncEncoder functions to produce a bitmap
  26. // to RRE encoder.  RRE is much more efficient than RAW format on
  27. // most screen data.
  28. #include "vncEncodeRRE.h"
  29. vncEncodeRRE::vncEncodeRRE()
  30. {
  31. m_buffer = NULL;
  32. m_bufflen = 0;
  33. }
  34. vncEncodeRRE::~vncEncodeRRE()
  35. {
  36. if (m_buffer != NULL)
  37. {
  38. delete [] m_buffer;
  39. m_buffer = NULL;
  40. }
  41. }
  42. void
  43. vncEncodeRRE::Init()
  44. {
  45. vncEncoder::Init();
  46. }
  47. UINT
  48. vncEncodeRRE::RequiredBuffSize(UINT width, UINT height)
  49. {
  50. return vncEncoder::RequiredBuffSize(width, height);
  51. }
  52. UINT
  53. vncEncodeRRE::NumCodedRects(RECT &rect)
  54. {
  55. return 1;
  56. }
  57. /*****************************************************************************
  58.  *
  59.  * Routines to implement Rise-and-Run-length Encoding (RRE).  This code is
  60.  * based on krw's original javatel rfbserver.
  61.  * This code courtesy of tjr
  62.  */
  63. /*
  64.  * rreBeforeBuf contains pixel data in the client's format.
  65.  * rreAfterBuf contains the RRE encoded version.  If the RRE encoded version is
  66.  * larger than the raw data or if it exceeds rreAfterBufSize then
  67.  * normal encoding is used instead.
  68.  */
  69. static int rreAfterBufLen;
  70. static int subrectEncode8 (CARD8 *data, CARD8 *buf, int w, int h, int maxBytes);
  71. static int subrectEncode16 (CARD16 *data, CARD8 *buf, int w, int h, int maxBytes);
  72. static int subrectEncode32 (CARD32 *data, CARD8 *buf, int w, int h, int maxBytes);
  73. static CARD32 getBgColour (char *data, int size, int bpp);
  74. /*
  75.  * subrectEncode() encodes the given multicoloured rectangle as a background 
  76.  * colour overwritten by single-coloured rectangles.  It returns the number 
  77.  * of subrectangles in the encoded buffer, or -1 if subrect encoding won't
  78.  * fit in the buffer.  It puts the encoded rectangles in rreAfterBuf.  The
  79.  * single-colour rectangle partition is not optimal, but does find the biggest
  80.  * horizontal or vertical rectangle top-left anchored to each consecutive 
  81.  * coordinate position.
  82.  *
  83.  * The coding scheme is simply [<bgcolour><subrect><subrect>...] where each 
  84.  * <subrect> is [<colour><x><y><w><h>].
  85.  *
  86.  * This code has been modified from tjr's original by Wez(jnw)
  87.  */
  88. #define DEFINE_SUBRECT_ENCODE(bpp)
  89. static int
  90. subrectEncode##bpp(
  91. CARD##bpp *data,
  92. CARD8 *buf,
  93. int w,
  94. int h,
  95. int maxBytes
  96. )
  97. {
  98.     CARD##bpp cl;
  99.     rfbRectangle subrect;
  100.     int x,y;
  101.     int i,j;
  102.     int hx,hy,vx,vy;
  103.     int hyflag;
  104.     CARD##bpp *seg;
  105.     CARD##bpp *line;
  106.     int hw,hh,vw,vh;
  107.     int thex,they,thew,theh;
  108.     int numsubs = 0;
  109.     int newLen;
  110.     CARD##bpp bg = (CARD##bpp)getBgColour((char*)data,w*h,bpp);
  111. /* Set the background colour value */
  112. *((CARD##bpp *)buf) = bg;
  113.     rreAfterBufLen = (bpp/8);
  114.     for (y=0; y<h; y++) {
  115.       line = data+(y*w);
  116.       for (x=0; x<w; x++) {
  117.         if (line[x] != bg) {
  118.           cl = line[x];
  119.           hy = y-1;
  120.           hyflag = 1;
  121.           for (j=y; j<h; j++) {
  122.             seg = data+(j*w);
  123.             if (seg[x] != cl) {break;}
  124.             i = x;
  125.             while ((i < w) && (seg[i] == cl)) i += 1;
  126.             i -= 1;
  127.             if (j == y) vx = hx = i;
  128.             if (i < vx) vx = i;
  129.             if ((hyflag > 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;}
  130.           }
  131.           vy = j-1;
  132.           /*  We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy)
  133.            *  We'll choose the bigger of the two.
  134.            */
  135.           hw = hx-x+1;
  136.           hh = hy-y+1;
  137.           vw = vx-x+1;
  138.           vh = vy-y+1;
  139.           thex = x;
  140.           they = y;
  141.           if ((hw*hh) > (vw*vh)) {
  142.             thew = hw;
  143.             theh = hh;
  144.           } else {
  145.             thew = vw;
  146.             theh = vh;
  147.           }
  148.           subrect.x = Swap16IfLE(thex);
  149.           subrect.y = Swap16IfLE(they);
  150.           subrect.w = Swap16IfLE(thew);
  151.           subrect.h = Swap16IfLE(theh);
  152. newLen = rreAfterBufLen + (bpp/8) + sz_rfbRectangle;
  153. if ((newLen > (w * h * (bpp/8))) || (newLen > maxBytes))
  154.     return -1;
  155.   numsubs += 1;
  156.   *((CARD##bpp *)(buf + rreAfterBufLen)) = cl;
  157.   rreAfterBufLen += (bpp/8);
  158.   memcpy(&buf[rreAfterBufLen],&subrect, sz_rfbRectangle);
  159.   rreAfterBufLen += sz_rfbRectangle;
  160.           /*
  161.            * Now mark the subrect as done.
  162.            */
  163.           for (j=they; j < (they+theh); j++) {
  164.             for (i=thex; i < (thex+thew); i++) {
  165.               data[j*w+i] = bg;
  166.             }
  167.           }
  168.         }
  169.       }
  170.     }
  171.     return numsubs;
  172. }
  173. DEFINE_SUBRECT_ENCODE(8)
  174. DEFINE_SUBRECT_ENCODE(16)
  175. DEFINE_SUBRECT_ENCODE(32)
  176. /*
  177.  * getBgColour() gets the most prevalent colour in a byte array.
  178.  */
  179. static CARD32
  180. getBgColour(char *data, int size, int bpp)
  181. {
  182.     
  183. #define NUMCLRS 256
  184.   
  185.   static int counts[NUMCLRS];
  186.   int i,j,k;
  187.   int maxcount = 0;
  188.   CARD8 maxclr = 0;
  189.   if (bpp != 8) {
  190.     if (bpp == 16) {
  191.       return ((CARD16 *)data)[0];
  192.     } else if (bpp == 32) {
  193.       return ((CARD32 *)data)[0];
  194.     } else {
  195.       fprintf(stderr,"getBgColour: bpp %d?n",bpp);
  196.       exit(1);
  197.     }
  198.   }
  199.   for (i=0; i<NUMCLRS; i++) {
  200.     counts[i] = 0;
  201.   }
  202.   for (j=0; j<size; j++) {
  203.     k = (int)(((CARD8 *)data)[j]);
  204.     if (k >= NUMCLRS) {
  205.       fprintf(stderr, "%s: unusual colour = %dn", "getBgColour",k);
  206.       exit(1);
  207.     }
  208.     counts[k] += 1;
  209.     if (counts[k] > maxcount) {
  210.       maxcount = counts[k];
  211.       maxclr = ((CARD8 *)data)[j];
  212.     }
  213.   }
  214.   
  215.   return maxclr;
  216. }
  217. // Encode the rectangle using RRE
  218. inline UINT
  219. vncEncodeRRE::EncodeRect(BYTE *source, BYTE *dest, const RECT &rect)
  220. {
  221. int subrects = -1;
  222. const rectW = rect.right - rect.left;
  223. const rectH = rect.bottom - rect.top;
  224. // Create the rectangle header
  225. rfbFramebufferUpdateRectHeader *surh=(rfbFramebufferUpdateRectHeader *)dest;
  226. surh->r.x = (CARD16) rect.left;
  227. surh->r.y = (CARD16) rect.top;
  228. surh->r.w = (CARD16) (rectW);
  229. surh->r.h = (CARD16) (rectH);
  230. surh->r.x = Swap16IfLE(surh->r.x);
  231. surh->r.y = Swap16IfLE(surh->r.y);
  232. surh->r.w = Swap16IfLE(surh->r.w);
  233. surh->r.h = Swap16IfLE(surh->r.h);
  234. surh->encoding = Swap32IfLE(rfbEncodingRRE);
  235. // create a space big enough for the RRE encoded pixels
  236. if (m_bufflen < (rectW*rectH*m_remoteformat.bitsPerPixel / 8))
  237. {
  238. if (m_buffer != NULL)
  239. {
  240. delete [] m_buffer;
  241. m_buffer = NULL;
  242. }
  243. m_buffer = new BYTE [rectW*rectH*m_remoteformat.bitsPerPixel/8+1];
  244. if (m_buffer == NULL)
  245. return vncEncoder::EncodeRect(source, dest, rect);
  246. m_bufflen = rectW*rectH*m_remoteformat.bitsPerPixel/8;
  247. }
  248. // Translate the data into our new buffer
  249. Translate(source, m_buffer, rect);
  250. // Choose the appropriate encoding routine (for speed...)
  251. switch(m_remoteformat.bitsPerPixel)
  252. {
  253. case 8:
  254. subrects = subrectEncode8(
  255. m_buffer,
  256. dest+sz_rfbFramebufferUpdateRectHeader+sz_rfbRREHeader,
  257. rectW,
  258. rectH,
  259. m_bufflen-sz_rfbFramebufferUpdateRectHeader-sz_rfbRREHeader
  260. );
  261. break;
  262. case 16:
  263. subrects = subrectEncode16(
  264. (CARD16 *)m_buffer,
  265. (CARD8 *)(dest+sz_rfbFramebufferUpdateRectHeader+sz_rfbRREHeader),
  266. rectW,
  267. rectH,
  268. m_bufflen-sz_rfbFramebufferUpdateRectHeader-sz_rfbRREHeader
  269. );
  270. break;
  271. case 32:
  272. subrects = subrectEncode32(
  273. (CARD32 *)m_buffer,
  274. (CARD8 *)(dest+sz_rfbFramebufferUpdateRectHeader+sz_rfbRREHeader),
  275. rectW,
  276. rectH,
  277. m_bufflen-sz_rfbFramebufferUpdateRectHeader-sz_rfbRREHeader
  278. );
  279. break;
  280. }
  281. // If we couldn't encode the rectangles then just send the data raw
  282. if (subrects < 0)
  283. return vncEncoder::EncodeRect(source, dest, rect);
  284. // Send the RREHeader
  285. rfbRREHeader *rreh=(rfbRREHeader *)(dest+sz_rfbFramebufferUpdateRectHeader);
  286. rreh->nSubrects = Swap32IfLE(subrects);
  287. // Return the amount of data sent
  288. return sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader +
  289. (m_remoteformat.bitsPerPixel / 8) +
  290. (subrects * (sz_rfbRectangle + m_remoteformat.bitsPerPixel / 8));
  291. }