summaryrefslogtreecommitdiffstats
path: root/java/com/tigervnc/rfb/ZRLEDecoder.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/tigervnc/rfb/ZRLEDecoder.java')
-rw-r--r--java/com/tigervnc/rfb/ZRLEDecoder.java166
1 files changed, 166 insertions, 0 deletions
diff --git a/java/com/tigervnc/rfb/ZRLEDecoder.java b/java/com/tigervnc/rfb/ZRLEDecoder.java
new file mode 100644
index 00000000..4f740f9d
--- /dev/null
+++ b/java/com/tigervnc/rfb/ZRLEDecoder.java
@@ -0,0 +1,166 @@
+/* Copyright (C) 2002-2005 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.
+ */
+
+package com.tigervnc.rfb;
+
+import com.tigervnc.rdr.*;
+
+public class ZRLEDecoder extends Decoder {
+
+ public ZRLEDecoder(CMsgReader reader_) {
+ reader = reader_;
+ zis = new ZlibInStream();
+ }
+
+ public void readRect(Rect r, CMsgHandler handler) {
+ InStream is = reader.getInStream();
+ int[] buf = reader.getImageBuf(64 * 64 * 4);
+ int bytesPerPixel = handler.cp.pf().bpp / 8;
+ boolean bigEndian = handler.cp.pf().bigEndian;
+
+ int length = is.readU32();
+ zis.setUnderlying(is, length);
+ Rect t = new Rect();
+
+ for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 64) {
+
+ t.br.y = Math.min(r.br.y, t.tl.y + 64);
+
+ for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 64) {
+
+ t.br.x = Math.min(r.br.x, t.tl.x + 64);
+
+ int mode = zis.readU8();
+ boolean rle = (mode & 128) != 0;
+ int palSize = mode & 127;
+ int[] palette = new int[128];
+
+ if (bytesPerPixel > 1) {
+ zis.readPixels(palette, palSize, 3, bigEndian);
+ } else {
+ for (int i = 0; i < palSize; i++) {
+ palette[i] = zis.readPixel(bytesPerPixel, bigEndian);
+ }
+ }
+
+ if (palSize == 1) {
+ int pix = palette[0];
+ handler.fillRect(t, pix);
+ continue;
+ }
+
+ if (!rle) {
+ if (palSize == 0) {
+
+ // raw
+
+ if (bytesPerPixel > 1) {
+ zis.readPixels(buf, t.area(), 3, bigEndian);
+ } else {
+ zis.readPixels(buf, t.area(), bytesPerPixel, bigEndian);
+ }
+
+ } else {
+
+ // packed pixels
+ int bppp = ((palSize > 16) ? 8 :
+ ((palSize > 4) ? 4 : ((palSize > 2) ? 2 : 1)));
+
+ int ptr = 0;
+
+ for (int i = 0; i < t.height(); i++) {
+ int eol = ptr + t.width();
+ int b = 0;
+ int nbits = 0;
+
+ while (ptr < eol) {
+ if (nbits == 0) {
+ b = zis.readU8();
+ nbits = 8;
+ }
+ nbits -= bppp;
+ int index = (b >> nbits) & ((1 << bppp) - 1) & 127;
+ buf[ptr++] = palette[index];
+ }
+ }
+ }
+
+ } else {
+
+ if (palSize == 0) {
+
+ // plain RLE
+
+ int ptr = 0;
+ int end = ptr + t.area();
+ while (ptr < end) {
+ int pix = (bytesPerPixel > 1 ? zis.readPixel(3, bigEndian) :
+ zis.readPixel(bytesPerPixel, bigEndian));
+ int len = 1;
+ int b;
+ do {
+ b = zis.readU8();
+ len += b;
+ } while (b == 255);
+
+ if (!(len <= end - ptr))
+ throw new Exception("ZRLEDecoder: assertion (len <= end - ptr)"
+ +" failed");
+
+ while (len-- > 0) buf[ptr++] = pix;
+ }
+ } else {
+
+ // palette RLE
+
+ int ptr = 0;
+ int end = ptr + t.area();
+ while (ptr < end) {
+ int index = zis.readU8();
+ int len = 1;
+ if ((index & 128) != 0) {
+ int b;
+ do {
+ b = zis.readU8();
+ len += b;
+ } while (b == 255);
+
+ if (!(len <= end - ptr))
+ throw new Exception("ZRLEDecoder: assertion "
+ +"(len <= end - ptr) failed");
+ }
+
+ index &= 127;
+
+ int pix = palette[index];
+
+ while (len-- > 0) buf[ptr++] = pix;
+ }
+ }
+ }
+
+ handler.imageRect(t, buf);
+ }
+ }
+
+ zis.reset();
+ }
+
+ CMsgReader reader;
+ ZlibInStream zis;
+}