1 /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. 2 * Copyright (C) 2019 Brian P. Hinz 3 * 4 * This is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This software is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this software; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 17 * USA. 18 */ 19 20 package com.tigervnc.rfb; 21 22 import java.awt.image.*; 23 import java.nio.*; 24 import java.util.*; 25 26 import com.tigervnc.rdr.*; 27 28 public class ZRLEDecoder extends Decoder { 29 readOpaque24A(InStream is)30 private static ByteBuffer readOpaque24A(InStream is) 31 { 32 is.check(3); 33 ByteBuffer r = ByteBuffer.allocate(4); 34 r.put(0, (byte)is.readU8()); 35 r.put(1, (byte)is.readU8()); 36 r.put(2, (byte)is.readU8()); 37 return r; 38 } 39 readOpaque24B(InStream is)40 private static ByteBuffer readOpaque24B(InStream is) 41 { 42 is.check(3); 43 ByteBuffer r = ByteBuffer.allocate(4); 44 r.put(1, (byte)is.readU8()); 45 r.put(2, (byte)is.readU8()); 46 r.put(3, (byte)is.readU8()); 47 return r; 48 } 49 ZRLEDecoder()50 public ZRLEDecoder() { 51 super(DecoderFlags.DecoderOrdered); 52 zis = new ZlibInStream(); 53 } 54 readRect(Rect r, InStream is, ServerParams server, OutStream os)55 public void readRect(Rect r, InStream is, 56 ServerParams server, OutStream os) 57 { 58 int len; 59 60 len = is.readU32(); 61 os.writeU32(len); 62 os.copyBytes(is, len); 63 } 64 decodeRect(Rect r, Object buffer, int buflen, ServerParams server, ModifiablePixelBuffer pb)65 public void decodeRect(Rect r, Object buffer, 66 int buflen, ServerParams server, 67 ModifiablePixelBuffer pb) 68 { 69 MemInStream is = new MemInStream((byte[])buffer, 0, buflen); 70 PixelFormat pf = server.pf(); 71 switch (pf.bpp) { 72 case 8: zrleDecode8(r, is, zis, pf, pb); break; 73 case 16: zrleDecode16(r, is, zis, pf, pb); break; 74 case 32: 75 { 76 if (pf.depth <= 24) { 77 int maxPixel = pf.pixelFromRGB(-1, -1, -1, pf.getColorModel()); 78 boolean fitsInLS3Bytes = maxPixel < (1<<24); 79 boolean fitsInMS3Bytes = (maxPixel & 0xff) == 0; 80 81 if ((fitsInLS3Bytes && pf.isLittleEndian()) || 82 (fitsInMS3Bytes && pf.isBigEndian())) 83 { 84 zrleDecode24A(r, is, zis, pf, pb); 85 break; 86 } 87 88 if ((fitsInLS3Bytes && pf.isBigEndian()) || 89 (fitsInMS3Bytes && pf.isLittleEndian())) 90 { 91 zrleDecode24B(r, is, zis, pf, pb); 92 break; 93 } 94 } 95 96 zrleDecode32(r, is, zis, pf, pb); 97 break; 98 } 99 } 100 } 101 102 private static enum PIXEL_T { U8, U16, U24A, U24B, U32 }; 103 104 private static ByteBuffer READ_PIXEL(InStream is, PIXEL_T type) { 105 switch (type) { 106 case U8: 107 return ByteBuffer.allocate(1).put(0, (byte)is.readOpaque8()); 108 case U16: 109 return ByteBuffer.allocate(2).putShort(0, (short)is.readOpaque16()); 110 case U24A: 111 return readOpaque24A(is); 112 case U24B: 113 return readOpaque24B(is); 114 default: 115 return ByteBuffer.allocate(4).putInt(0, is.readOpaque32()); 116 } 117 } 118 119 private void zrleDecode8(Rect r, InStream is, 120 ZlibInStream zis, 121 PixelFormat pf, ModifiablePixelBuffer pb) 122 { 123 ZRLE_DECODE(r, is, zis, pf, pb, PIXEL_T.U8); 124 } 125 126 private void zrleDecode16(Rect r, InStream is, 127 ZlibInStream zis, 128 PixelFormat pf, ModifiablePixelBuffer pb) 129 { 130 ZRLE_DECODE(r, is, zis, pf, pb, PIXEL_T.U16); 131 } 132 133 private void zrleDecode24A(Rect r, InStream is, 134 ZlibInStream zis, 135 PixelFormat pf, ModifiablePixelBuffer pb) 136 { 137 ZRLE_DECODE(r, is, zis, pf, pb, PIXEL_T.U24A); 138 } 139 140 private void zrleDecode24B(Rect r, InStream is, 141 ZlibInStream zis, 142 PixelFormat pf, ModifiablePixelBuffer pb) 143 { 144 ZRLE_DECODE(r, is, zis, pf, pb, PIXEL_T.U24B); 145 } 146 147 private void zrleDecode32(Rect r, InStream is, 148 ZlibInStream zis, 149 PixelFormat pf, ModifiablePixelBuffer pb) 150 { 151 ZRLE_DECODE(r, is, zis, pf, pb, PIXEL_T.U32); 152 } 153 154 private void ZRLE_DECODE(Rect r, InStream is, 155 ZlibInStream zis, 156 PixelFormat pf, ModifiablePixelBuffer pb, 157 PIXEL_T pix_t) 158 { 159 int length = is.readU32(); 160 zis.setUnderlying(is, length); 161 Rect t = new Rect(); 162 ByteBuffer buf = ByteBuffer.allocate(64 * 64 * pf.bpp/8); 163 164 for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 64) { 165 166 t.br.y = Math.min(r.br.y, t.tl.y + 64); 167 168 for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 64) { 169 170 t.br.x = Math.min(r.br.x, t.tl.x + 64); 171 172 int mode = zis.readU8(); 173 boolean rle = (mode & 128) != 0; 174 int palSize = mode & 127; 175 ByteBuffer palette = ByteBuffer.allocate(128 * pf.bpp/8); 176 177 for (int i = 0; i < palSize; i++) { 178 palette.put(READ_PIXEL(zis, pix_t)); 179 } 180 palette.flip(); 181 182 if (palSize == 1) { 183 byte[] pix = new byte[pf.bpp/8]; 184 palette.get(pix); 185 pb.fillRect(pf, t, pix); 186 continue; 187 } 188 189 if (!rle) { 190 if (palSize == 0) { 191 192 // raw 193 switch (pix_t) { 194 case U24A: 195 case U24B: 196 ByteBuffer ptr = buf.duplicate(); 197 for (int i=0; i < t.area(); i++) { 198 ptr.put(READ_PIXEL(zis, pix_t)); 199 } 200 break; 201 default: 202 zis.readBytes(buf.duplicate(), t.area() * (pf.bpp/8)); 203 } 204 205 } else { 206 207 // packed pixels 208 int bppp = ((palSize > 16) ? 8 : 209 ((palSize > 4) ? 4 : ((palSize > 2) ? 2 : 1))); 210 211 ByteBuffer ptr = buf.duplicate(); 212 213 for (int i = 0; i < t.height(); i++) { 214 int eol = ptr.position() + t.width()*pf.bpp/8; 215 int b = 0; 216 int nbits = 0; 217 218 while (ptr.position() < eol) { 219 if (nbits == 0) { 220 b = zis.readU8(); 221 nbits = 8; 222 } 223 nbits -= bppp; 224 int index = (b >> nbits) & ((1 << bppp) - 1) & 127; 225 ptr.put(palette.array(), index*pf.bpp/8, pf.bpp/8); 226 } 227 } 228 } 229 230 } else { 231 232 if (palSize == 0) { 233 234 // plain RLE 235 236 ByteBuffer ptr = buf.duplicate(); 237 int end = ptr.position() + t.area()*pf.bpp/8; 238 while (ptr.position() < end) { 239 ByteBuffer pix = READ_PIXEL(zis, pix_t); 240 int len = 1; 241 int b; 242 do { 243 b = zis.readU8(); 244 len += b; 245 } while (b == 255); 246 247 if (end - ptr.position() < len*pf.bpp/8) { 248 System.err.println("ZRLE decode error\n"); 249 throw new Exception("ZRLE decode error"); 250 } 251 252 while (len-- > 0) ptr.put(pix.array()); 253 254 } 255 } else { 256 257 // palette RLE 258 259 ByteBuffer ptr = buf.duplicate(); 260 int end = ptr.position() + t.area()*pf.bpp/8; 261 while (ptr.position() < end) { 262 int index = zis.readU8(); 263 int len = 1; 264 if ((index & 128) != 0) { 265 int b; 266 do { 267 b = zis.readU8(); 268 len += b; 269 } while (b == 255); 270 271 if (end - ptr.position() < len*pf.bpp/8) { 272 System.err.println("ZRLE decode error\n"); 273 throw new Exception("ZRLE decode error"); 274 } 275 } 276 277 index &= 127; 278 279 ByteBuffer pix = ByteBuffer.allocate(pf.bpp/8); 280 pix.put(palette.array(), index*pf.bpp/8, pf.bpp/8); 281 282 while (len-- > 0) ptr.put(pix.array()); 283 } 284 } 285 } 286 287 pb.imageRect(pf, t, buf.array()); 288 } 289 } 290 291 zis.flushUnderlying(); 292 zis.setUnderlying(null, 0); 293 } 294 295 private ZlibInStream zis; 296 } 297