You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ZRLEDecoder.java 8.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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. package com.tigervnc.rfb;
  20. import java.awt.image.*;
  21. import java.nio.*;
  22. import java.util.*;
  23. import com.tigervnc.rdr.*;
  24. public class ZRLEDecoder extends Decoder {
  25. private static ByteBuffer readOpaque24A(InStream is)
  26. {
  27. is.check(3);
  28. ByteBuffer r = ByteBuffer.allocate(4);
  29. r.put(0, (byte)is.readU8());
  30. r.put(1, (byte)is.readU8());
  31. r.put(2, (byte)is.readU8());
  32. return r;
  33. }
  34. private static ByteBuffer readOpaque24B(InStream is)
  35. {
  36. is.check(3);
  37. ByteBuffer r = ByteBuffer.allocate(4);
  38. r.put(1, (byte)is.readU8());
  39. r.put(2, (byte)is.readU8());
  40. r.put(3, (byte)is.readU8());
  41. return r;
  42. }
  43. public ZRLEDecoder() {
  44. super(DecoderFlags.DecoderOrdered);
  45. zis = new ZlibInStream();
  46. }
  47. public void readRect(Rect r, InStream is,
  48. ServerParams server, OutStream os)
  49. {
  50. int len;
  51. len = is.readU32();
  52. os.writeU32(len);
  53. os.copyBytes(is, len);
  54. }
  55. public void decodeRect(Rect r, Object buffer,
  56. int buflen, ServerParams server,
  57. ModifiablePixelBuffer pb)
  58. {
  59. MemInStream is = new MemInStream((byte[])buffer, 0, buflen);
  60. PixelFormat pf = server.pf();
  61. switch (pf.bpp) {
  62. case 8: zrleDecode8(r, is, zis, pf, pb); break;
  63. case 16: zrleDecode16(r, is, zis, pf, pb); break;
  64. case 32:
  65. {
  66. if (pf.depth <= 24) {
  67. int maxPixel = pf.pixelFromRGB(-1, -1, -1, pf.getColorModel());
  68. boolean fitsInLS3Bytes = maxPixel < (1<<24);
  69. boolean fitsInMS3Bytes = (maxPixel & 0xff) == 0;
  70. if ((fitsInLS3Bytes && pf.isLittleEndian()) ||
  71. (fitsInMS3Bytes && pf.isBigEndian()))
  72. {
  73. zrleDecode24A(r, is, zis, pf, pb);
  74. break;
  75. }
  76. if ((fitsInLS3Bytes && pf.isBigEndian()) ||
  77. (fitsInMS3Bytes && pf.isLittleEndian()))
  78. {
  79. zrleDecode24B(r, is, zis, pf, pb);
  80. break;
  81. }
  82. }
  83. zrleDecode32(r, is, zis, pf, pb);
  84. break;
  85. }
  86. }
  87. }
  88. private static enum PIXEL_T { U8, U16, U24A, U24B, U32 };
  89. private static ByteBuffer READ_PIXEL(InStream is, PIXEL_T type) {
  90. switch (type) {
  91. case U8:
  92. return ByteBuffer.allocate(1).put(0, (byte)is.readOpaque8());
  93. case U16:
  94. return ByteBuffer.allocate(2).putShort(0, (short)is.readOpaque16());
  95. case U24A:
  96. return readOpaque24A(is);
  97. case U24B:
  98. return readOpaque24B(is);
  99. default:
  100. return ByteBuffer.allocate(4).putInt(0, is.readOpaque32());
  101. }
  102. }
  103. private void zrleDecode8(Rect r, InStream is,
  104. ZlibInStream zis,
  105. PixelFormat pf, ModifiablePixelBuffer pb)
  106. {
  107. ZRLE_DECODE(r, is, zis, pf, pb, PIXEL_T.U8);
  108. }
  109. private void zrleDecode16(Rect r, InStream is,
  110. ZlibInStream zis,
  111. PixelFormat pf, ModifiablePixelBuffer pb)
  112. {
  113. ZRLE_DECODE(r, is, zis, pf, pb, PIXEL_T.U16);
  114. }
  115. private void zrleDecode24A(Rect r, InStream is,
  116. ZlibInStream zis,
  117. PixelFormat pf, ModifiablePixelBuffer pb)
  118. {
  119. ZRLE_DECODE(r, is, zis, pf, pb, PIXEL_T.U24A);
  120. }
  121. private void zrleDecode24B(Rect r, InStream is,
  122. ZlibInStream zis,
  123. PixelFormat pf, ModifiablePixelBuffer pb)
  124. {
  125. ZRLE_DECODE(r, is, zis, pf, pb, PIXEL_T.U24B);
  126. }
  127. private void zrleDecode32(Rect r, InStream is,
  128. ZlibInStream zis,
  129. PixelFormat pf, ModifiablePixelBuffer pb)
  130. {
  131. ZRLE_DECODE(r, is, zis, pf, pb, PIXEL_T.U32);
  132. }
  133. private void ZRLE_DECODE(Rect r, InStream is,
  134. ZlibInStream zis,
  135. PixelFormat pf, ModifiablePixelBuffer pb,
  136. PIXEL_T pix_t)
  137. {
  138. int length = is.readU32();
  139. zis.setUnderlying(is, length);
  140. Rect t = new Rect();
  141. ByteBuffer buf = ByteBuffer.allocate(64 * 64 * pf.bpp/8);
  142. for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 64) {
  143. t.br.y = Math.min(r.br.y, t.tl.y + 64);
  144. for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 64) {
  145. t.br.x = Math.min(r.br.x, t.tl.x + 64);
  146. int mode = zis.readU8();
  147. boolean rle = (mode & 128) != 0;
  148. int palSize = mode & 127;
  149. ByteBuffer palette = ByteBuffer.allocate(128 * pf.bpp/8);
  150. for (int i = 0; i < palSize; i++) {
  151. palette.put(READ_PIXEL(zis, pix_t));
  152. }
  153. palette.flip();
  154. if (palSize == 1) {
  155. byte[] pix = new byte[pf.bpp/8];
  156. palette.get(pix);
  157. pb.fillRect(pf, t, pix);
  158. continue;
  159. }
  160. if (!rle) {
  161. if (palSize == 0) {
  162. // raw
  163. switch (pix_t) {
  164. case U24A:
  165. case U24B:
  166. ByteBuffer ptr = buf.duplicate();
  167. for (int i=0; i < t.area(); i++) {
  168. ptr.put(READ_PIXEL(zis, pix_t));
  169. }
  170. break;
  171. default:
  172. zis.readBytes(buf.duplicate(), t.area() * (pf.bpp/8));
  173. }
  174. } else {
  175. // packed pixels
  176. int bppp = ((palSize > 16) ? 8 :
  177. ((palSize > 4) ? 4 : ((palSize > 2) ? 2 : 1)));
  178. ByteBuffer ptr = buf.duplicate();
  179. for (int i = 0; i < t.height(); i++) {
  180. int eol = ptr.position() + t.width()*pf.bpp/8;
  181. int b = 0;
  182. int nbits = 0;
  183. while (ptr.position() < eol) {
  184. if (nbits == 0) {
  185. b = zis.readU8();
  186. nbits = 8;
  187. }
  188. nbits -= bppp;
  189. int index = (b >> nbits) & ((1 << bppp) - 1) & 127;
  190. ptr.put(palette.array(), index*pf.bpp/8, pf.bpp/8);
  191. }
  192. }
  193. }
  194. } else {
  195. if (palSize == 0) {
  196. // plain RLE
  197. ByteBuffer ptr = buf.duplicate();
  198. int end = ptr.position() + t.area()*pf.bpp/8;
  199. while (ptr.position() < end) {
  200. ByteBuffer pix = READ_PIXEL(zis, pix_t);
  201. int len = 1;
  202. int b;
  203. do {
  204. b = zis.readU8();
  205. len += b;
  206. } while (b == 255);
  207. if (end - ptr.position() < len*pf.bpp/8) {
  208. System.err.println("ZRLE decode error\n");
  209. throw new Exception("ZRLE decode error");
  210. }
  211. while (len-- > 0) ptr.put(pix.array());
  212. }
  213. } else {
  214. // palette RLE
  215. ByteBuffer ptr = buf.duplicate();
  216. int end = ptr.position() + t.area()*pf.bpp/8;
  217. while (ptr.position() < end) {
  218. int index = zis.readU8();
  219. int len = 1;
  220. if ((index & 128) != 0) {
  221. int b;
  222. do {
  223. b = zis.readU8();
  224. len += b;
  225. } while (b == 255);
  226. if (end - ptr.position() < len*pf.bpp/8) {
  227. System.err.println("ZRLE decode error\n");
  228. throw new Exception("ZRLE decode error");
  229. }
  230. }
  231. index &= 127;
  232. ByteBuffer pix = ByteBuffer.allocate(pf.bpp/8);
  233. pix.put(palette.array(), index*pf.bpp/8, pf.bpp/8);
  234. while (len-- > 0) ptr.put(pix.array());
  235. }
  236. }
  237. }
  238. pb.imageRect(pf, t, buf.array());
  239. }
  240. }
  241. zis.flushUnderlying();
  242. zis.setUnderlying(null, 0);
  243. }
  244. private ZlibInStream zis;
  245. }