comparison src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java @ 0:4689cc86d6cb

create TreeViewer2 Repository
author Yu Taninari <you@cr.ie.u-ryukyu.ac.jp>
date Tue, 03 Jul 2012 13:20:49 +0900
parents
children e7ce2b2ffed8 17b702648079
comparison
equal deleted inserted replaced
-1:000000000000 0:4689cc86d6cb
1 // Copyright (C) 2010, 2011 GlavSoft LLC.
2 // All rights reserved.
3 //
4 //-------------------------------------------------------------------------
5 // This file is part of the TightVNC software. Please visit our Web site:
6 //
7 // http://www.tightvnc.com/
8 //
9 // This program is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License along
20 // with this program; if not, write to the Free Software Foundation, Inc.,
21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 //-------------------------------------------------------------------------
23 //
24
25 package com.glavsoft.rfb.encoding.decoder;
26
27 import com.glavsoft.drawing.Renderer;
28 import com.glavsoft.exceptions.TransportException;
29 import com.glavsoft.transport.Reader;
30
31 public class ZRLEDecoder extends ZlibDecoder {
32 private static final int DEFAULT_TILE_SIZE = 64;
33
34 @Override
35 public void decode(Reader reader, Renderer renderer,
36 FramebufferUpdateRectangle rect) throws TransportException {
37 int zippedLength = (int) reader.readUInt32();
38 if (0 == zippedLength) return;
39 int length = rect.width * rect.height * renderer.getBytesPerPixel();
40 byte[] bytes = unzip(reader, zippedLength, length);
41 int offset = zippedLength;
42 int maxX = rect.x + rect.width;
43 int maxY = rect.y + rect.height;
44 int [] palette = new int [128];
45 for (int tileY = rect.y; tileY < maxY; tileY += DEFAULT_TILE_SIZE) {
46 int tileHeight = Math.min(maxY - tileY, DEFAULT_TILE_SIZE);
47
48 for (int tileX = rect.x; tileX < maxX; tileX += DEFAULT_TILE_SIZE) {
49 int tileWidth = Math.min(maxX - tileX, DEFAULT_TILE_SIZE);
50 int subencoding = bytes[offset++] & 0x0ff;
51 // 128 -plain RLE, 130-255 - Palette RLE
52 boolean isRle = (subencoding & 128) != 0;
53 // 2 to 16 for raw packed palette data, 130 to 255 for Palette RLE (subencoding - 128)
54 int paletteSize = subencoding & 127;
55 offset += readPalette(bytes, offset, renderer, palette, paletteSize);
56 if (1 == subencoding) { // A solid tile consisting of a single colour
57 renderer.fillRect(palette[0], tileX, tileY, tileWidth, tileHeight);
58 continue;
59 }
60 if (isRle) {
61 if (0 == paletteSize) { // subencoding == 128 (or paletteSize == 0) - Plain RLE
62 offset += decodePlainRle(bytes, offset, renderer, tileX, tileY, tileWidth, tileHeight);
63 } else {
64 offset += decodePaletteRle(bytes, offset, renderer, palette, tileX, tileY, tileWidth, tileHeight, paletteSize);
65 }
66 } else {
67 if (0 == paletteSize) { // subencoding == 0 (or paletteSize == 0) - raw CPIXEL data
68 offset += decodeRaw(bytes, offset, renderer, tileX, tileY, tileWidth, tileHeight);
69 } else {
70 offset += decodePacked(bytes, offset, renderer, palette, paletteSize, tileX, tileY, tileWidth, tileHeight);
71 }
72 }
73 }
74 }
75
76 }
77
78 private int decodePlainRle(byte[] bytes, int offset, Renderer renderer,
79 int tileX, int tileY, int tileWidth, int tileHeight) {
80 int bytesPerCPixel = renderer.getBytesPerPixelSignificant();
81 int [] decodedBitmap = new int[tileWidth * tileHeight];
82 int decodedOffset = 0;
83 int decodedEnd = tileWidth * tileHeight;
84 int index = offset;
85 while (decodedOffset < decodedEnd) {
86 int color = renderer.getCompactPixelColor(bytes, index);
87 index += bytesPerCPixel;
88 int rlength = 1;
89 do {
90 rlength += bytes[index] & 0x0ff;
91 } while ((bytes[index++] & 0x0ff) == 255);
92 assert rlength <= decodedEnd - decodedOffset;
93 renderer.fillColorBitmapWithColor(decodedBitmap, decodedOffset, rlength, color);
94 decodedOffset += rlength;
95 }
96 renderer.drawColoredBitmap(decodedBitmap, tileX, tileY, tileWidth, tileHeight);
97 return index - offset;
98 }
99
100 private int decodePaletteRle(byte[] bytes, int offset, Renderer renderer,
101 int[] palette, int tileX, int tileY, int tileWidth, int tileHeight, int paletteSize) {
102 int [] decodedBitmap = new int[tileWidth * tileHeight];
103 int decodedOffset = 0;
104 int decodedEnd = tileWidth * tileHeight;
105 int index = offset;
106 while (decodedOffset < decodedEnd) {
107 int colorIndex = bytes[index++];
108 int color = palette[colorIndex & 127];
109 int rlength = 1;
110 if ((colorIndex & 128) != 0) {
111 do {
112 rlength += bytes[index] & 0x0ff;
113 } while (bytes[index++] == (byte) 255);
114 }
115 assert rlength <= decodedEnd - decodedOffset;
116 renderer.fillColorBitmapWithColor(decodedBitmap, decodedOffset, rlength, color);
117 decodedOffset += rlength;
118 }
119 renderer.drawColoredBitmap(decodedBitmap, tileX, tileY, tileWidth, tileHeight);
120 return index - offset;
121 }
122
123 private int decodePacked(byte[] bytes, int offset, Renderer renderer,
124 int[] palette, int paletteSize, int tileX, int tileY, int tileWidth, int tileHeight) {
125 int [] decodedBytes = new int[tileWidth * tileHeight];
126 int bitsPerPalletedPixel = paletteSize > 16 ? 8 : paletteSize > 4 ? 4
127 : paletteSize > 2 ? 2 : 1;
128 int packedOffset = offset;
129 int decodedOffset = 0;
130 for (int i = 0; i < tileHeight; ++i) {
131 int decodedRowEnd = decodedOffset + tileWidth;
132 int byteProcessed = 0;
133 int bitsRemain = 0;
134
135 while (decodedOffset < decodedRowEnd) {
136 if (bitsRemain == 0) {
137 byteProcessed = bytes[packedOffset++];
138 bitsRemain = 8;
139 }
140 bitsRemain -= bitsPerPalletedPixel;
141 int index = byteProcessed >> bitsRemain & (1 << bitsPerPalletedPixel) - 1 & 127;
142 int color = palette[index];
143 renderer.fillColorBitmapWithColor(decodedBytes, decodedOffset, 1, color);
144 ++decodedOffset;
145 }
146 }
147 renderer.drawColoredBitmap(decodedBytes, tileX, tileY, tileWidth, tileHeight);
148 return packedOffset - offset;
149 }
150
151 private int decodeRaw(byte[] bytes, int offset, Renderer renderer,
152 int tileX, int tileY, int tileWidth, int tileHeight) throws TransportException {
153 return renderer.drawCompactBytes(bytes, offset, tileX, tileY, tileWidth, tileHeight);
154 }
155
156 private int readPalette(byte[] bytes, int offset, Renderer renderer,
157 int[] palette, int paletteSize) {
158 for (int i=0; i<paletteSize; ++i) {
159 palette[i] = renderer.getCompactPixelColor(bytes,
160 offset + i*renderer.getBytesPerPixelSignificant());
161 }
162 return paletteSize * renderer.getBytesPerPixelSignificant();
163 }
164
165 }