diff options
author | dscho <dscho> | 2002-10-22 08:46:27 +0000 |
---|---|---|
committer | dscho <dscho> | 2002-10-22 08:46:27 +0000 |
commit | af85e5fee34f7998fe3f06c799b8364a9ddbebce (patch) | |
tree | 48cabfc42fb150d2a001042f8974b28b4287f436 /zrleDecode.h | |
parent | 5a5c22ffc98e4e44f7763256e3683cc390cd260b (diff) | |
download | libtdevnc-af85e5fee34f7998fe3f06c799b8364a9ddbebce.tar.gz libtdevnc-af85e5fee34f7998fe3f06c799b8364a9ddbebce.zip |
updated to vnc-3.3.4 (ZRLE encoding)
Diffstat (limited to 'zrleDecode.h')
-rw-r--r-- | zrleDecode.h | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/zrleDecode.h b/zrleDecode.h new file mode 100644 index 0000000..8ddb5c8 --- /dev/null +++ b/zrleDecode.h @@ -0,0 +1,241 @@ +// +// Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. +// +// This 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 software 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 software; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// +// zrleDecode.h - zrle decoding function. +// +// Before including this file, you must define a number of CPP macros. +// +// BPP should be 8, 16 or 32 depending on the bits per pixel. +// FILL_RECT +// IMAGE_RECT + +#include <rdr/ZlibInStream.h> +#include <rdr/InStream.h> +#include <assert.h> + +using namespace rdr; + +/* __RFB_CONCAT2 concatenates its two arguments. __RFB_CONCAT2E does the same + but also expands its arguments if they are macros */ + +#ifndef __RFB_CONCAT2E +#define __RFB_CONCAT2(a,b) a##b +#define __RFB_CONCAT2E(a,b) __RFB_CONCAT2(a,b) +#endif + +#ifdef CPIXEL +#define PIXEL_T __RFB_CONCAT2E(rdr::U,BPP) +#define READ_PIXEL __RFB_CONCAT2E(readOpaque,CPIXEL) +#define ZRLE_DECODE_BPP __RFB_CONCAT2E(zrleDecode,CPIXEL) +#else +#define PIXEL_T __RFB_CONCAT2E(rdr::U,BPP) +#define READ_PIXEL __RFB_CONCAT2E(readOpaque,BPP) +#define ZRLE_DECODE_BPP __RFB_CONCAT2E(zrleDecode,BPP) +#endif + +void ZRLE_DECODE_BPP (int x, int y, int w, int h, rdr::InStream* is, + rdr::ZlibInStream* zis, PIXEL_T* buf) +{ + int length = is->readU32(); + zis->setUnderlying(is, length); + + for (int ty = y; ty < y+h; ty += rfbZRLETileHeight) { + int th = rfbZRLETileHeight; + if (th > y+h-ty) th = y+h-ty; + for (int tx = x; tx < x+w; tx += rfbZRLETileWidth) { + int tw = rfbZRLETileWidth; + if (tw > x+w-tx) tw = x+w-tx; + + int mode = zis->readU8(); + bool rle = mode & 128; + int palSize = mode & 127; + PIXEL_T palette[128]; + + // fprintf(stderr,"rle %d palSize %d\n",rle,palSize); + + for (int i = 0; i < palSize; i++) { + palette[i] = zis->READ_PIXEL(); + } + + if (palSize == 1) { + PIXEL_T pix = palette[0]; + FILL_RECT(tx,ty,tw,th,pix); + continue; + } + + if (!rle) { + if (palSize == 0) { + + // raw + +#ifdef CPIXEL + for (PIXEL_T* ptr = buf; ptr < buf+tw*th; ptr++) { + *ptr = zis->READ_PIXEL(); + } +#else + zis->readBytes(buf, tw * th * (BPP / 8)); +#endif + + } else { + + // packed pixels + int bppp = ((palSize > 16) ? 8 : + ((palSize > 4) ? 4 : ((palSize > 2) ? 2 : 1))); + + PIXEL_T* ptr = buf; + + for (int i = 0; i < th; i++) { + PIXEL_T* eol = ptr + tw; + U8 byte = 0; + U8 nbits = 0; + + while (ptr < eol) { + if (nbits == 0) { + byte = zis->readU8(); + nbits = 8; + } + nbits -= bppp; + U8 index = (byte >> nbits) & ((1 << bppp) - 1) & 127; + *ptr++ = palette[index]; + } + } + } + +#ifdef FAVOUR_FILL_RECT + //fprintf(stderr,"copying data to screen %dx%d at %d,%d\n",tw,th,tx,ty); + IMAGE_RECT(tx,ty,tw,th,buf); +#endif + + } else { + + if (palSize == 0) { + + // plain RLE + + PIXEL_T* ptr = buf; + PIXEL_T* end = ptr + th * tw; + while (ptr < end) { + PIXEL_T pix = zis->READ_PIXEL(); + int len = 1; + int b; + do { + b = zis->readU8(); + len += b; + } while (b == 255); + + assert(len <= end - ptr); + +#ifdef FAVOUR_FILL_RECT + int i = ptr - buf; + ptr += len; + + int runX = i % tw; + int runY = i / tw; + + if (runX + len > tw) { + if (runX != 0) { + FILL_RECT(tx+runX, ty+runY, tw-runX, 1, pix); + len -= tw-runX; + runX = 0; + runY++; + } + + if (len > tw) { + FILL_RECT(tx, ty+runY, tw, len/tw, pix); + runY += len / tw; + len = len % tw; + } + } + + if (len != 0) { + FILL_RECT(tx+runX, ty+runY, len, 1, pix); + } +#else + while (len-- > 0) *ptr++ = pix; +#endif + + } + } else { + + // palette RLE + + PIXEL_T* ptr = buf; + PIXEL_T* end = ptr + th * tw; + while (ptr < end) { + int index = zis->readU8(); + int len = 1; + if (index & 128) { + int b; + do { + b = zis->readU8(); + len += b; + } while (b == 255); + + assert(len <= end - ptr); + } + + index &= 127; + + PIXEL_T pix = palette[index]; + +#ifdef FAVOUR_FILL_RECT + int i = ptr - buf; + ptr += len; + + int runX = i % tw; + int runY = i / tw; + + if (runX + len > tw) { + if (runX != 0) { + FILL_RECT(tx+runX, ty+runY, tw-runX, 1, pix); + len -= tw-runX; + runX = 0; + runY++; + } + + if (len > tw) { + FILL_RECT(tx, ty+runY, tw, len/tw, pix); + runY += len / tw; + len = len % tw; + } + } + + if (len != 0) { + FILL_RECT(tx+runX, ty+runY, len, 1, pix); + } +#else + while (len-- > 0) *ptr++ = pix; +#endif + } + } + } + +#ifndef FAVOUR_FILL_RECT + //fprintf(stderr,"copying data to screen %dx%d at %d,%d\n",tw,th,tx,ty); + IMAGE_RECT(tx,ty,tw,th,buf); +#endif + } + } + + zis->reset(); +} + +#undef ZRLE_DECODE_BPP +#undef READ_PIXEL +#undef PIXEL_T |