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

📄 clientconnectiontight.cpp

📁 teamviewer source code vc++
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//  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 + -