📄 vncencodecorre.cpp
字号:
return EncodeSmallRect(source, dest, rect);
}
void
vncEncodeCoRRE::SetCoRREMax(BYTE width, BYTE height)
{
m_maxwidth = width;
m_maxheight = height;
}
/*
* EncodeSmallRect - send a small (guaranteed < 256x256)
* rectangle using CoRRE encoding.
*/
UINT
vncEncodeCoRRE::EncodeSmallRect(BYTE *source, BYTE *dest, const RECT &rect)
{
int subrects = -1;
const UINT rectW = rect.right - rect.left;
const UINT rectH = rect.bottom - rect.top;
// Create the rectangle header
rfbFramebufferUpdateRectHeader *surh=(rfbFramebufferUpdateRectHeader *)dest;
surh->r.x = (CARD16) rect.left;
surh->r.y = (CARD16) rect.top;
surh->r.w = (CARD16) (rectW);
surh->r.h = (CARD16) (rectH);
surh->r.x = Swap16IfLE(surh->r.x - offsetx);
surh->r.y = Swap16IfLE(surh->r.y - offsety);
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
size_t rectSize = rectW * rectH * (m_remoteformat.bitsPerPixel / 8);
if (m_bufflen < rectSize)
{
if (m_buffer != NULL)
{
delete [] m_buffer;
m_buffer = NULL;
}
m_buffer = new BYTE [rectSize + 1];
if (m_buffer == NULL)
return vncEncoder::EncodeRect(source, dest, rect, offsetx, offsety);
m_bufflen = rectSize;
}
// 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, offsetx, offsety);
// Send the RREHeader
rfbRREHeader *rreh=(rfbRREHeader *)(dest+sz_rfbFramebufferUpdateRectHeader);
rreh->nSubrects = Swap32IfLE(subrects);
// Update the statistics for this rectangle.
encodedSize += sz_rfbRREHeader + rreAfterBufLen;
rectangleOverhead += sz_rfbFramebufferUpdateRectHeader;
dataSize += ( rectW * rectH * m_remoteformat.bitsPerPixel) / 8;
transmittedSize += sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader + rreAfterBufLen;
// 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 CARD32
getBgColour(
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 + -