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.

ZRLEEncoder.cxx 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. * Copyright 2014 Pierre Ossman for Cendio AB
  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  17. * USA.
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. #include <config.h>
  21. #endif
  22. #include <rdr/OutStream.h>
  23. #include <rfb/Exception.h>
  24. #include <rfb/encodings.h>
  25. #include <rfb/Palette.h>
  26. #include <rfb/SConnection.h>
  27. #include <rfb/ZRLEEncoder.h>
  28. #include <rfb/Configuration.h>
  29. using namespace rfb;
  30. IntParameter zlibLevel("ZlibLevel","Zlib compression level",-1);
  31. ZRLEEncoder::ZRLEEncoder(SConnection* conn)
  32. : Encoder(conn, encodingZRLE, EncoderPlain, 127),
  33. zos(0,zlibLevel), mos(129*1024)
  34. {
  35. zos.setUnderlying(&mos);
  36. }
  37. ZRLEEncoder::~ZRLEEncoder()
  38. {
  39. zos.setUnderlying(NULL);
  40. }
  41. bool ZRLEEncoder::isSupported()
  42. {
  43. return conn->client.supportsEncoding(encodingZRLE);
  44. }
  45. void ZRLEEncoder::writeRect(const PixelBuffer* pb, const Palette& palette)
  46. {
  47. int x, y;
  48. Rect tile;
  49. rdr::OutStream* os;
  50. // A bit of a special case
  51. if (palette.size() == 1) {
  52. Encoder::writeSolidRect(pb, palette);
  53. return;
  54. }
  55. for (y = 0;y < pb->height();y += 64) {
  56. tile.tl.y = y;
  57. tile.br.y = y + 64;
  58. if (tile.br.y > pb->height())
  59. tile.br.y = pb->height();
  60. for (x = 0;x < pb->width();x += 64) {
  61. tile.tl.x = x;
  62. tile.br.x = x + 64;
  63. if (tile.br.x > pb->width())
  64. tile.br.x = pb->width();
  65. if (palette.size() == 0)
  66. writeRawTile(tile, pb, palette);
  67. else if (palette.size() <= 16)
  68. writePaletteTile(tile, pb, palette);
  69. else
  70. writePaletteRLETile(tile, pb, palette);
  71. }
  72. }
  73. zos.flush();
  74. os = conn->getOutStream();
  75. os->writeU32(mos.length());
  76. os->writeBytes(mos.data(), mos.length());
  77. mos.clear();
  78. }
  79. void ZRLEEncoder::writeSolidRect(int width, int height,
  80. const PixelFormat& pf,
  81. const rdr::U8* colour)
  82. {
  83. int tiles;
  84. rdr::OutStream* os;
  85. tiles = ((width + 63)/64) * ((height + 63)/64);
  86. while (tiles--) {
  87. zos.writeU8(1);
  88. writePixels(colour, pf, 1);
  89. }
  90. zos.flush();
  91. os = conn->getOutStream();
  92. os->writeU32(mos.length());
  93. os->writeBytes(mos.data(), mos.length());
  94. mos.clear();
  95. }
  96. void ZRLEEncoder::writePaletteTile(const Rect& tile, const PixelBuffer* pb,
  97. const Palette& palette)
  98. {
  99. const rdr::U8* buffer;
  100. int stride;
  101. buffer = pb->getBuffer(tile, &stride);
  102. switch (pb->getPF().bpp) {
  103. case 32:
  104. writePaletteTile(tile.width(), tile.height(),
  105. (rdr::U32*)buffer, stride,
  106. pb->getPF(), palette);
  107. break;
  108. case 16:
  109. writePaletteTile(tile.width(), tile.height(),
  110. (rdr::U16*)buffer, stride,
  111. pb->getPF(), palette);
  112. break;
  113. default:
  114. writePaletteTile(tile.width(), tile.height(),
  115. (rdr::U8*)buffer, stride,
  116. pb->getPF(), palette);
  117. }
  118. }
  119. void ZRLEEncoder::writePaletteRLETile(const Rect& tile, const PixelBuffer* pb,
  120. const Palette& palette)
  121. {
  122. const rdr::U8* buffer;
  123. int stride;
  124. buffer = pb->getBuffer(tile, &stride);
  125. switch (pb->getPF().bpp) {
  126. case 32:
  127. writePaletteRLETile(tile.width(), tile.height(),
  128. (rdr::U32*)buffer, stride,
  129. pb->getPF(), palette);
  130. break;
  131. case 16:
  132. writePaletteRLETile(tile.width(), tile.height(),
  133. (rdr::U16*)buffer, stride,
  134. pb->getPF(), palette);
  135. break;
  136. default:
  137. writePaletteRLETile(tile.width(), tile.height(),
  138. (rdr::U8*)buffer, stride,
  139. pb->getPF(), palette);
  140. }
  141. }
  142. void ZRLEEncoder::writeRawTile(const Rect& tile, const PixelBuffer* pb,
  143. const Palette& palette)
  144. {
  145. const rdr::U8* buffer;
  146. int stride;
  147. int w, h, stride_bytes;
  148. buffer = pb->getBuffer(tile, &stride);
  149. zos.writeU8(0); // Empty palette (i.e. raw pixels)
  150. w = tile.width();
  151. h = tile.height();
  152. stride_bytes = stride * pb->getPF().bpp/8;
  153. while (h--) {
  154. writePixels(buffer, pb->getPF(), w);
  155. buffer += stride_bytes;
  156. }
  157. }
  158. void ZRLEEncoder::writePalette(const PixelFormat& pf, const Palette& palette)
  159. {
  160. rdr::U8 buffer[256*4];
  161. int i;
  162. if (pf.bpp == 32) {
  163. rdr::U32* buf;
  164. buf = (rdr::U32*)buffer;
  165. for (i = 0;i < palette.size();i++)
  166. *buf++ = palette.getColour(i);
  167. } else if (pf.bpp == 16) {
  168. rdr::U16* buf;
  169. buf = (rdr::U16*)buffer;
  170. for (i = 0;i < palette.size();i++)
  171. *buf++ = palette.getColour(i);
  172. } else {
  173. rdr::U8* buf;
  174. buf = (rdr::U8*)buffer;
  175. for (i = 0;i < palette.size();i++)
  176. *buf++ = palette.getColour(i);
  177. }
  178. writePixels(buffer, pf, palette.size());
  179. }
  180. void ZRLEEncoder::writePixels(const rdr::U8* buffer, const PixelFormat& pf,
  181. unsigned int count)
  182. {
  183. Pixel maxPixel;
  184. rdr::U8 pixBuf[4];
  185. maxPixel = pf.pixelFromRGB((rdr::U16)-1, (rdr::U16)-1, (rdr::U16)-1);
  186. pf.bufferFromPixel(pixBuf, maxPixel);
  187. if ((pf.bpp != 32) || ((pixBuf[0] != 0) && (pixBuf[3] != 0))) {
  188. zos.writeBytes(buffer, count * (pf.bpp/8));
  189. return;
  190. }
  191. if (pixBuf[0] == 0)
  192. buffer++;
  193. while (count--) {
  194. zos.writeBytes(buffer, 3);
  195. buffer += 4;
  196. }
  197. }
  198. //
  199. // Including BPP-dependent implementation of the encoder.
  200. //
  201. #define BPP 8
  202. #include <rfb/ZRLEEncoderBPP.cxx>
  203. #undef BPP
  204. #define BPP 16
  205. #include <rfb/ZRLEEncoderBPP.cxx>
  206. #undef BPP
  207. #define BPP 32
  208. #include <rfb/ZRLEEncoderBPP.cxx>
  209. #undef BPP