📄 clientconnectiontight.cpp
字号:
// Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
//
// This file is part of TeamViewer.
//
// TeamViewer 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.
//
// TightVNC distribution homepage on the Web: http://www.tightvnc.com/
//
// If the source code for TeamViewer is not available from the place
// whence you received this file, check http://www.teamviewer.com
// for information on obtaining it.
// Tight Encoding
//
// The bits of the ClientConnection object to do with Tight.
#include "stdhdrs.h"
#include "ClientConnection.h"
#define TIGHT_MIN_TO_COMPRESS 12
#define TIGHT_BUFFER_SIZE (2048 * 200)
void ClientConnection::ReadTightRect(rfbFramebufferUpdateRectHeader *pfburh)
{
if (m_myFormat.bitsPerPixel != 8 &&
m_myFormat.bitsPerPixel != 16 &&
m_myFormat.bitsPerPixel != 32) {
vnclog.Print(0, VNCLOG(_T("Invalid number of bits per pixel: %d")),
m_myFormat.bitsPerPixel);
return;
}
CARD8 comp_ctl;
ReadExact((char *)&comp_ctl, 1);
/* Flush zlib streams if we are told by the server to do so. */
for (int i = 0; i < 4; i++) {
if ((comp_ctl & 1) && m_tightZlibStreamActive[i]) {
int err = inflateEnd (&m_tightZlibStream[i]);
if (err != Z_OK) {
if (m_tightZlibStream[i].msg != NULL) {
vnclog.Print(0, VNCLOG(_T("zlib inflateEnd() error: %s")),
m_tightZlibStream[i].msg);
} else {
vnclog.Print(0, VNCLOG(_T("zlib inflateEnd() error: %d")), err);
}
return;
}
m_tightZlibStreamActive[i] = FALSE;
}
comp_ctl >>= 1;
}
/* Handle solid rectangles. */
if (comp_ctl == rfbTightFill) {
COLORREF fillColour;
if (m_myFormat.depth == 24 && m_myFormat.redMax == 0xFF &&
m_myFormat.greenMax == 0xFF && m_myFormat.blueMax == 0xFF) {
CARD8 fillColourBuf[3];
ReadExact((char *)&fillColourBuf, 3);
fillColour = COLOR_FROM_PIXEL24_ADDRESS(fillColourBuf);
} else {
CARD32 fillColourBuf;
ReadExact((char *)&fillColourBuf, m_myFormat.bitsPerPixel / 8);
SETUP_COLOR_SHORTCUTS;
switch (m_myFormat.bitsPerPixel) {
case 8:
fillColour = COLOR_FROM_PIXEL8_ADDRESS(&fillColourBuf);
break;
case 16:
fillColour = COLOR_FROM_PIXEL16_ADDRESS(&fillColourBuf);
break;
default:
fillColour = COLOR_FROM_PIXEL32_ADDRESS(&fillColourBuf);
}
}
omni_mutex_lock l(m_bitmapdcMutex);
ObjectSelector b(m_hBitmapDC, m_hBitmap);
PaletteSelector p(m_hBitmapDC, m_hPalette);
FillSolidRect(pfburh->r.x, pfburh->r.y, pfburh->r.w, pfburh->r.h,
fillColour);
return;
}
if (comp_ctl == rfbTightJpeg) {
DecompressJpegRect(pfburh->r.x, pfburh->r.y, pfburh->r.w, pfburh->r.h);
return;
}
/* Quit on unsupported subencoding value. */
if (comp_ctl >= rfbTightMaxSubencoding) {
vnclog.Print(0, VNCLOG(_T("Tight encoding: bad subencoding value received.")));
return;
}
/*
* Here primary compression mode handling begins.
* Data was processed with optional filter + zlib compression.
*/
/* First, we should identify a filter to use. */
int bitsPixel;
if ((comp_ctl & rfbTightExplicitFilter) != 0) {
CARD8 filter_id;
ReadExact((char *)&filter_id, 1);
switch (filter_id) {
case rfbTightFilterCopy:
bitsPixel = InitFilterCopy(pfburh->r.w, pfburh->r.h);
break;
case rfbTightFilterPalette:
bitsPixel = InitFilterPalette(pfburh->r.w, pfburh->r.h);
break;
case rfbTightFilterGradient:
bitsPixel = InitFilterGradient(pfburh->r.w, pfburh->r.h);
break;
default:
vnclog.Print(0, VNCLOG(_T("Tight encoding: unknown filter code received.")));
return;
}
} else {
bitsPixel = InitFilterCopy(pfburh->r.w, pfburh->r.h);
}
if (bitsPixel == 0) {
vnclog.Print(0, VNCLOG(_T("Tight encoding: error receiving palette.")));
return;
}
/* Determine if the data should be decompressed or just copied. */
int rowSize = (pfburh->r.w * bitsPixel + 7) / 8;
if (pfburh->r.h * rowSize < TIGHT_MIN_TO_COMPRESS) {
CheckBufferSize(pfburh->r.h * rowSize);
ReadExact(m_netbuf, pfburh->r.h * rowSize);
CheckZlibBufferSize(pfburh->r.w * pfburh->r.h * 4);
(this->*m_tightCurrentFilter)(pfburh->r.h);
omni_mutex_lock l(m_bitmapdcMutex);
ObjectSelector b(m_hBitmapDC, m_hBitmap);
PaletteSelector p(m_hBitmapDC, m_hPalette);
SETPIXELS_NOCONV(m_zlibbuf, pfburh->r.x, pfburh->r.y,
pfburh->r.w, pfburh->r.h);
return;
}
/* Read the length (1..3 bytes) of compressed data following. */
int compressedLen = ReadCompactLen();
if (compressedLen <= 0) {
vnclog.Print(0, VNCLOG(_T("Tight encoding: bad data received from server.")));
return;
}
/* Now let's initialize compression stream if needed. */
int stream_id = comp_ctl & 0x03;
z_streamp zs = &m_tightZlibStream[stream_id];
if (!m_tightZlibStreamActive[stream_id]) {
zs->zalloc = Z_NULL;
zs->zfree = Z_NULL;
zs->opaque = Z_NULL;
int err = inflateInit(zs);
if (err != Z_OK) {
if (zs->msg != NULL) {
vnclog.Print(0, VNCLOG(_T("zlib inflateInit() error: %s.")), zs->msg);
} else {
vnclog.Print(0, VNCLOG(_T("zlib inflateInit() error: %d.")), err);
}
return;
}
m_tightZlibStreamActive[stream_id] = TRUE;
}
/* Read, decode and draw actual pixel data in a loop. */
int beforeBufferSize =
TIGHT_BUFFER_SIZE * bitsPixel / (bitsPixel + sizeof(COLORREF) * 8)
& 0xFFFFFFFC;
CheckBufferSize(beforeBufferSize);
int afterBufferSize = TIGHT_BUFFER_SIZE - beforeBufferSize;
CheckZlibBufferSize(afterBufferSize);
int rowsProcessed = 0, extraBytes = 0;
int err, numRows, portionLen;
while (compressedLen > 0) {
if (compressedLen > TIGHT_ZLIB_BUFFER_SIZE)
portionLen = TIGHT_ZLIB_BUFFER_SIZE;
else
portionLen = compressedLen;
ReadExact(m_tightbuf, portionLen);
compressedLen -= portionLen;
zs->next_in = (Bytef *)m_tightbuf;
zs->avail_in = portionLen;
do {
zs->next_out = (Bytef *)&m_netbuf[extraBytes];
zs->avail_out = beforeBufferSize - extraBytes;
err = inflate(zs, Z_SYNC_FLUSH);
if (err == Z_BUF_ERROR) // Input exhausted -- no problem
break;
if (err != Z_OK && err != Z_STREAM_END) {
if (zs->msg != NULL) {
vnclog.Print(0, VNCLOG(_T("zlib inflate() error: %s.")), zs->msg);
} else {
vnclog.Print(0, VNCLOG(_T("zlib inflate() error: %d.")), err);
}
return;
}
numRows = (beforeBufferSize - zs->avail_out) / rowSize;
(this->*m_tightCurrentFilter)(numRows);
extraBytes = beforeBufferSize - zs->avail_out - numRows * rowSize;
if (extraBytes > 0)
memcpy(m_netbuf, &m_netbuf[numRows * rowSize], extraBytes);
omni_mutex_lock l(m_bitmapdcMutex);
ObjectSelector b(m_hBitmapDC, m_hBitmap);
PaletteSelector p(m_hBitmapDC, m_hPalette);
SETPIXELS_NOCONV(m_zlibbuf, pfburh->r.x, pfburh->r.y + rowsProcessed,
pfburh->r.w, numRows);
rowsProcessed += numRows;
}
while (zs->avail_out == 0);
}
if (rowsProcessed != pfburh->r.h) {
vnclog.Print(0, VNCLOG(_T("Tight encoding: wrong number of scan lines.")));
}
}
int ClientConnection::ReadCompactLen() {
CARD8 len_byte;
ReadExact((char *)&len_byte, 1);
int compressedLen = (int)len_byte & 0x7F;
if (len_byte & 0x80) {
ReadExact((char *)&len_byte, 1);
compressedLen |= ((int)len_byte & 0x7F) << 7;
if (len_byte & 0x80) {
ReadExact((char *)&len_byte, 1);
compressedLen |= ((int)len_byte & 0xFF) << 14;
}
}
return compressedLen;
}
//----------------------------------------------------------------------------
//
// Filter stuff.
//
// The following variables are defined in the class declaration:
// tightFilterFunc m_tightCurrentFilter;
// Bool m_tightCutZeros;
// int m_tightRectWidth, m_tightRectColors;
// COLORREF m_tightPalette[256];
// CARD8 m_tightPrevRow[2048*3*sizeof(CARD16)];
int ClientConnection::InitFilterCopy (int rw, int rh)
{
tightFilterFunc funcArray[3] = {
&ClientConnection::FilterCopy8,
&ClientConnection::FilterCopy16,
&ClientConnection::FilterCopy32
};
m_tightCurrentFilter = funcArray[m_myFormat.bitsPerPixel/16];
m_tightRectWidth = rw;
if (m_myFormat.depth == 24 && m_myFormat.redMax == 0xFF &&
m_myFormat.greenMax == 0xFF && m_myFormat.blueMax == 0xFF) {
m_tightCutZeros = TRUE;
m_tightCurrentFilter = &ClientConnection::FilterCopy24;
return 24;
}
m_tightCutZeros = FALSE;
return m_myFormat.bitsPerPixel;
}
int ClientConnection::InitFilterGradient (int rw, int rh)
{
int bits = InitFilterCopy(rw, rh);
tightFilterFunc funcArray[3] = {
&ClientConnection::FilterGradient8,
&ClientConnection::FilterGradient16,
&ClientConnection::FilterGradient32
};
m_tightCurrentFilter = funcArray[m_myFormat.bitsPerPixel/16];
if (m_tightCutZeros) {
m_tightCurrentFilter = &ClientConnection::FilterGradient24;
memset(m_tightPrevRow, 0, rw * 3);
} else
memset(m_tightPrevRow, 0, rw * 3 * sizeof(CARD16));
return bits;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -