⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vncencodecorre.cpp

📁 realvnc是一个非常流行的远程控制程序
💻 CPP
字号:
//  Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved.//  Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.////  This file is part of the VNC system.////  The VNC system is free software; you can redistribute it and/or modify//  it under the terms of the GNU General Public License as published by//  the Free Software Foundation; either version 2 of the License, or//  (at your option) any later version.////  This program is distributed in the hope that it will be useful,//  but WITHOUT ANY WARRANTY; without even the implied warranty of//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the//  GNU General Public License for more details.////  You should have received a copy of the GNU General Public License//  along with this program; if not, write to the Free Software//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,//  USA.//// If the source code for the VNC system is not available from the place // whence you received this file, check http://www.uk.research.att.com/vnc or contact// the authors on vnc@uk.research.att.com for information on obtaining it.// vncEncodeCoRRE// This file implements the vncEncoder-derived vncEncodeCoRRE class.// This class overrides some vncEncoder functions to produce a// Compact RRE encoder.  Compact RRE (CoRRE) uses fewer bytes to// encode each subrect, which makes it faster in general.  It also// splits large rectangles up into ones of at most 256 pixels width// & height.  This results in better granularity to use for deciding// whether to send RAW or CoRRE/RRE. #include "vncEncodeCoRRE.h"#include "rfb.h"#include "rfbMisc.h"#include <stdlib.h>#include <time.h>vncEncodeCoRRE::vncEncodeCoRRE(){	m_buffer = NULL;	m_bufflen = 0;	// Set some sensible defaults	m_maxwidth = 24;	m_maxheight = 24;	m_maxadjust = 1;	// Set the threshold up/down probability	m_threshold = 50;	// Seed the random number generator	srand((unsigned)time(NULL));	m_statsready = FALSE;	m_encodedbytes = 0;	m_rectbytes = 0;}vncEncodeCoRRE::~vncEncodeCoRRE(){	if (m_buffer != NULL)	{		delete [] m_buffer;		m_buffer = NULL;	}}void vncEncodeCoRRE::Init(){	vncEncoder::Init();}UINT vncEncodeCoRRE::RequiredBuffSize(UINT width, UINT height){	rfb::Rect fullscreen = rfb::Rect(0, 0, width, height);	UINT codedrects;	// Work out how many rectangles the entire screen would	// be re-encoded to...	codedrects = NumCodedRects(fullscreen);	// The buffer size required is the size of raw data for the whole	// screen plus enough space for the required number of rectangle	// headers.	// This is inherently always greater than the RAW encoded size of	// the whole screen!	return (codedrects * sz_rfbFramebufferUpdateRectHeader) +			(width * height * m_remoteformat.bitsPerPixel)/8;}UINTvncEncodeCoRRE::NumCodedRects(const rfb::Rect &rect){	// If we have any statistical data handy then adjust the CoRRE sizes	if (m_statsready)	{		m_statsready = FALSE;		UINT newscore = m_encodedbytes * m_lastrectbytes;		UINT oldscore = m_lastencodedbytes * m_rectbytes;		if (newscore <= oldscore)		{			// The change was a good one, so adjust the threshold accordingly!			m_threshold = max(5, min(95, m_threshold + m_maxadjust));			m_maxwidth = max(8, min(255, m_maxwidth + m_maxadjust));			m_maxheight = max(8, min(255, m_maxheight + m_maxadjust));		}		else		{			// The change was a bad one, so adjust the threshold accordingly!			// m_threshold = Max(5, Min(95, m_threshold - m_maxadjust));		}		// Now calculate a new adjustment and apply it		m_maxadjust = ((rand() % 99)<m_threshold) ? 1 : -1;				// Prepare the stats data for next time...		m_lastencodedbytes = m_encodedbytes;		m_lastrectbytes = m_rectbytes;		m_encodedbytes = 0;		m_rectbytes = 0;	}	// Now return the number of rects that this one would encode to    if ((rect.br.y-rect.tl.y) > m_maxheight)	{		rfb::Rect subrect1, subrect2;		// Find how many rects the two subrects would take		subrect1.tl.x = rect.tl.x;		subrect1.br.x = rect.br.x;		subrect1.tl.y = rect.tl.y;		subrect1.br.y = rect.tl.y + m_maxheight;		subrect2.tl.x = rect.tl.x;		subrect2.br.x = rect.br.x;		subrect2.tl.y = rect.tl.y + m_maxheight;		subrect2.br.y = rect.br.y;		return NumCodedRects(subrect1) + NumCodedRects(subrect2);	}    if ((rect.br.x-rect.tl.x) > m_maxwidth)	{		rfb::Rect subrect1, subrect2;		// Find how many rects the two subrects would take		subrect1.tl.x = rect.tl.x;		subrect1.br.x = rect.tl.x + m_maxwidth;		subrect1.tl.y = rect.tl.y;		subrect1.br.y = rect.br.y;		subrect2.tl.x = rect.tl.x + m_maxwidth;		subrect2.br.x = rect.br.x;		subrect2.tl.y = rect.tl.y;		subrect2.br.y = rect.br.y;		return NumCodedRects(subrect1) + NumCodedRects(subrect2);	}	// This rectangle is small enough not to require splitting	return 1;}/* * corre.c * * Routines to implement Compact Rise-and-Run-length Encoding (CoRRE).  This * code is based on krw's original javatel rfbserver. *//* * This version modified for WinVNC by jnw. */static int rreAfterBufLen;static int subrectEncode8 (CARD8 *source, CARD8 *dest, int w, int h, int max);static int subrectEncode16 (CARD16 *source, CARD8 *dest, int w, int h, int max);static int subrectEncode32 (CARD32 *source, CARD8 *dest, int w, int h, int max);static CARD32 getBgColour (char *data, int size, int bpp);/* * vncEncodeCoRRE::EncodeRect - send an arbitrary size rectangle using CoRRE * encoding. */UINTvncEncodeCoRRE::EncodeRect(BYTE *source, BYTE *dest, const rfb::Rect &rect){	// Do the encoding	UINT size = InternalEncodeRect(source, dest, rect);	const UINT rectW = rect.br.x - rect.tl.x;	const UINT rectH = rect.br.y - rect.tl.y;	// Will this rectangle have been split for encoding?	if ((rectW>m_maxwidth) || (rectH>m_maxheight))	{		// Yes : Once we return, the stats will be valid!		m_statsready = TRUE;		// Update the stats		m_encodedbytes += size;		m_rectbytes += sz_rfbFramebufferUpdateRectHeader +			(rectW*rectH*m_remoteformat.bitsPerPixel/8);	}	return size;}UINTvncEncodeCoRRE::InternalEncodeRect(BYTE *source, BYTE *dest, const rfb::Rect &rect){	int size = 0;    if ((rect.br.y-rect.tl.y) > m_maxheight)	{		rfb::Rect subrect;		// Rectangle is too high - split it into two subrects to send		subrect.tl.x = rect.tl.x;		subrect.br.x = rect.br.x;		subrect.tl.y = rect.tl.y;		subrect.br.y = rect.tl.y + m_maxheight;		size += InternalEncodeRect(source, dest + size, subrect);		subrect.tl.x = rect.tl.x;		subrect.br.x = rect.br.x;		subrect.tl.y = rect.tl.y + m_maxheight;		subrect.br.y = rect.br.y;		size += InternalEncodeRect(source, dest + size, subrect);		return size;    }    if ((rect.br.x-rect.tl.x) > m_maxwidth)	{		rfb::Rect subrect;		// Rectangle is too high - split it into two subrects to send		subrect.tl.x = rect.tl.x;		subrect.br.x = rect.tl.x + m_maxwidth;		subrect.tl.y = rect.tl.y;		subrect.br.y = rect.br.y;		size += InternalEncodeRect(source, dest + size, subrect);		subrect.tl.x = rect.tl.x + m_maxwidth;		subrect.br.x = rect.br.x;		subrect.tl.y = rect.tl.y;		subrect.br.y = rect.br.y;		size += InternalEncodeRect(source, dest + size, subrect);		return size;	}    return EncodeSmallRect(source, dest, rect);}voidvncEncodeCoRRE::SetCoRREMax(BYTE width, BYTE height){	m_maxwidth = width;	m_maxheight = height;}/* * EncodeSmallRect - send a small (guaranteed < 256x256) * rectangle using CoRRE encoding. */UINTvncEncodeCoRRE::EncodeSmallRect(BYTE *source, BYTE *dest, const rfb::Rect &rect){	int subrects = -1;	const UINT rectW = rect.br.x - rect.tl.x;	const UINT rectH = rect.br.y - rect.tl.y;	// Create the rectangle header	rfbFramebufferUpdateRectHeader *surh=(rfbFramebufferUpdateRectHeader *)dest;	surh->r.x = (CARD16) rect.tl.x;	surh->r.y = (CARD16) rect.tl.y;	surh->r.w = (CARD16) (rectW);	surh->r.h = (CARD16) (rectH);	surh->r.x = Swap16IfLE(surh->r.x);	surh->r.y = Swap16IfLE(surh->r.y);	surh->r.w = Swap16IfLE(surh->r.w);	surh->r.h = Swap16IfLE(surh->r.h);	surh->encoding = Swap32IfLE(rfbEncodingCoRRE);		// create a space big enough for the CoRRE encoded pixels	if (m_bufflen < (rectW*rectH*m_remoteformat.bitsPerPixel / 8))	{		if (m_buffer != NULL)		{			delete [] m_buffer;			m_buffer = NULL;		}		m_buffer = new BYTE [rectW*rectH*m_remoteformat.bitsPerPixel/8+1];		if (m_buffer == NULL)			return vncEncoder::EncodeRect(source, dest, rect);		m_bufflen = rectW*rectH*m_remoteformat.bitsPerPixel/8;	}		// Translate the data into our new buffer	Translate(source, m_buffer, rect);	// The Buffer object will have ensured that the destination buffer is	// big enough using RequiredBuffSize	// Choose the appropriate encoding routine (for speed...)	switch(m_remoteformat.bitsPerPixel)	{	case 8:		subrects = subrectEncode8(			m_buffer,			dest+sz_rfbFramebufferUpdateRectHeader+sz_rfbRREHeader,			rectW,			rectH,			m_bufflen-sz_rfbFramebufferUpdateRectHeader-sz_rfbRREHeader			);		break;	case 16:		subrects = subrectEncode16(			(CARD16 *)m_buffer,			(CARD8 *)(dest+sz_rfbFramebufferUpdateRectHeader+sz_rfbRREHeader),			rectW,			rectH,			m_bufflen-sz_rfbFramebufferUpdateRectHeader-sz_rfbRREHeader			);		break;	case 32:		subrects = subrectEncode32(			(CARD32 *)m_buffer,			(CARD8 *)(dest+sz_rfbFramebufferUpdateRectHeader+sz_rfbRREHeader),			rectW,			rectH,			m_bufflen-sz_rfbFramebufferUpdateRectHeader-sz_rfbRREHeader			);		break;	}	// If we couldn't encode the rectangles then just send the data raw	if (subrects < 0)		return vncEncoder::EncodeRect(source, dest, rect);	// Send the RREHeader	rfbRREHeader *rreh=(rfbRREHeader *)(dest+sz_rfbFramebufferUpdateRectHeader);	rreh->nSubrects = Swap32IfLE(subrects);	// Calculate the size of the buffer produced	return sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader + rreAfterBufLen;}/* * subrectEncode() encodes the given multicoloured rectangle as a background  * colour overwritten by single-coloured rectangles.  It returns the number  * of subrectangles in the encoded buffer, or -1 if subrect encoding won't * fit in the buffer.  It puts the encoded rectangles in rreAfterBuf.  The * single-colour rectangle partition is not optimal, but does find the biggest * horizontal or vertical rectangle top-left anchored to each consecutive  * coordinate position. * * The coding scheme is simply [<bgcolour><subrect><subrect>...] where each  * <subrect> is [<colour><x><y><w><h>]. */#define DEFINE_SUBRECT_ENCODE(bpp)							\static int													\subrectEncode##bpp(											\	CARD##bpp *source,										\    CARD8 *dest,											\	int w,													\	int h,													\	int maxbytes)											\{															\    CARD##bpp cl;											\    rfbCoRRERectangle subrect;								\    int x,y;												\    int i,j;												\    int hx=0,hy,vx=0,vy;									\    int hyflag;												\    CARD##bpp *seg;											\    CARD##bpp *line;										\    int hw,hh,vw,vh;										\    int thex,they,thew,theh;								\    int numsubs = 0;										\    int newLen;												\    CARD##bpp bg = (CARD##bpp)getBgColour((char*)source,w*h,bpp);	\															\    *((CARD##bpp*)dest) = bg;								\															\    rreAfterBufLen = (bpp/8);								\															\    for (y=0; y<h; y++) {									\      line = source+(y*w);									\      for (x=0; x<w; x++) {									\        if (line[x] != bg) {								\          cl = line[x];										\          hy = y-1;											\          hyflag = 1;										\          for (j=y; j<h; j++) {								\            seg = source+(j*w);								\            if (seg[x] != cl) {break;}					    \            i = x;											\            while ((seg[i] == cl) && (i < w)) i += 1;		\            i -= 1;											\            if (j == y) vx = hx = i;					    \            if (i < vx) vx = i;								\            if ((hyflag > 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;}      \          }													\          vy = j-1;											\															\          /*  We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy)  \           *  We'll choose the bigger of the two.			\           */												\          hw = hx-x+1;										\          hh = hy-y+1;										\          vw = vx-x+1;										\          vh = vy-y+1;										\															\          thex = x;											\          they = y;											\															\          if ((hw*hh) > (vw*vh)) {							\            thew = hw;										\            theh = hh;										\          } else {											\            thew = vw;										\            theh = vh;										\          }													\															\          subrect.x = thex;									\          subrect.y = they;									\          subrect.w = thew;									\          subrect.h = theh;									\															\	  newLen = rreAfterBufLen + (bpp/8) + sz_rfbCoRRERectangle;			\          if ((newLen > (w * h * (bpp/8))) || (newLen > maxbytes))		\	    return -1;											\															\	  numsubs += 1;											\	  *((CARD##bpp*)(dest + rreAfterBufLen)) = cl;			\	  rreAfterBufLen += (bpp/8);							\	  memcpy(&dest[rreAfterBufLen],&subrect,sz_rfbCoRRERectangle);		\	  rreAfterBufLen += sz_rfbCoRRERectangle;			    \															\		  /*												\           * Now mark the subrect as done.				    \           */												\          for (j=they; j < (they+theh); j++) {				\            for (i=thex; i < (thex+thew); i++) {			\              source[j*w+i] = bg;								\            }												\          }													\        }													\      }														\    }														\															\    return numsubs;											\}DEFINE_SUBRECT_ENCODE(8)DEFINE_SUBRECT_ENCODE(16)DEFINE_SUBRECT_ENCODE(32)/* * getBgColour() gets the most prevalent colour in a byte array. */static CARD32getBgColour(	char *data,	int size,	int bpp){    #define NUMCLRS 256    static int counts[NUMCLRS];  int i,j,k;  int maxcount = 0;  CARD8 maxclr = 0;  if (bpp != 8) {    if (bpp == 16) {      return ((CARD16 *)data)[0];    } else if (bpp == 32) {      return ((CARD32 *)data)[0];    } else {      fprintf(stderr,"getBgColour: bpp %d?\n",bpp);      exit(1);    }  }  for (i=0; i<NUMCLRS; i++) {    counts[i] = 0;  }  for (j=0; j<size; j++) {    k = (int)(((CARD8 *)data)[j]);    if (k >= NUMCLRS) {      fprintf(stderr, "%s: unusual colour = %d\n", "getBgColour",k);      exit(1);    }    counts[k] += 1;    if (counts[k] > maxcount) {      maxcount = counts[k];      maxclr = ((CARD8 *)data)[j];    }  }    return maxclr;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -