Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

RREEncoder.cxx 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. * Copyright 2014-2022 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/encodings.h>
  24. #include <rfb/SConnection.h>
  25. #include <rfb/PixelFormat.h>
  26. #include <rfb/PixelBuffer.h>
  27. #include <rfb/Palette.h>
  28. #include <rfb/RREEncoder.h>
  29. using namespace rfb;
  30. RREEncoder::RREEncoder(SConnection* conn) :
  31. Encoder(conn, encodingRRE, EncoderPlain)
  32. {
  33. }
  34. RREEncoder::~RREEncoder()
  35. {
  36. }
  37. bool RREEncoder::isSupported()
  38. {
  39. return conn->client.supportsEncoding(encodingRRE);
  40. }
  41. void RREEncoder::writeRect(const PixelBuffer* pb, const Palette& palette)
  42. {
  43. uint8_t* imageBuf;
  44. int stride;
  45. uint32_t bg;
  46. int w = pb->width();
  47. int h = pb->height();
  48. if (palette.size() == 1) {
  49. Encoder::writeSolidRect(pb, palette);
  50. return;
  51. }
  52. // We have to have our own copy of the data as we modify it as
  53. // we find subrects.
  54. bufferCopy.setPF(pb->getPF());
  55. bufferCopy.setSize(w, h);
  56. imageBuf = bufferCopy.getBufferRW(pb->getRect(), &stride);
  57. pb->getImage(imageBuf, pb->getRect());
  58. if (palette.size() > 0)
  59. bg = palette.getColour(0);
  60. else {
  61. // Some crazy person is using this encoder for high colour
  62. // data. Just pick the first pixel as the background colour.
  63. bg = 0;
  64. memcpy(&bg, imageBuf, pb->getPF().bpp/8);
  65. }
  66. int nSubrects = -1;
  67. switch (pb->getPF().bpp) {
  68. case 8:
  69. nSubrects = rreEncode<uint8_t>((uint8_t*)imageBuf, w, h, &mos, bg);
  70. break;
  71. case 16:
  72. nSubrects = rreEncode<uint16_t>((uint16_t*)imageBuf, w, h, &mos, bg);
  73. break;
  74. case 32:
  75. nSubrects = rreEncode<uint32_t>((uint32_t*)imageBuf, w, h, &mos, bg);
  76. break;
  77. }
  78. bufferCopy.commitBufferRW(pb->getRect());
  79. rdr::OutStream* os = conn->getOutStream();
  80. os->writeU32(nSubrects);
  81. os->writeBytes(mos.data(), mos.length());
  82. mos.clear();
  83. }
  84. void RREEncoder::writeSolidRect(int /*width*/, int /*height*/,
  85. const PixelFormat& pf,
  86. const uint8_t* colour)
  87. {
  88. rdr::OutStream* os;
  89. os = conn->getOutStream();
  90. os->writeU32(0);
  91. os->writeBytes(colour, pf.bpp/8);
  92. }
  93. template<class T>
  94. inline void RREEncoder::writePixel(rdr::OutStream* os, T pixel)
  95. {
  96. if (sizeof(T) == 1)
  97. os->writeOpaque8(pixel);
  98. else if (sizeof(T) == 2)
  99. os->writeOpaque16(pixel);
  100. else if (sizeof(T) == 4)
  101. os->writeOpaque32(pixel);
  102. }
  103. template<class T>
  104. int RREEncoder::rreEncode(T* data, int w, int h,
  105. rdr::OutStream* os, T bg)
  106. {
  107. writePixel(os, bg);
  108. int nSubrects = 0;
  109. for (int y = 0; y < h; y++)
  110. {
  111. int x = 0;
  112. while (x < w) {
  113. if (*data == bg) {
  114. x++;
  115. data++;
  116. continue;
  117. }
  118. // Find horizontal subrect first
  119. T* ptr = data+1;
  120. T* eol = data+w-x;
  121. while (ptr < eol && *ptr == *data) ptr++;
  122. int sw = ptr - data;
  123. ptr = data + w;
  124. int sh = 1;
  125. while (sh < h-y) {
  126. eol = ptr + sw;
  127. while (ptr < eol)
  128. if (*ptr++ != *data) goto endOfHorizSubrect;
  129. ptr += w - sw;
  130. sh++;
  131. }
  132. endOfHorizSubrect:
  133. // Find vertical subrect
  134. int vh;
  135. for (vh = sh; vh < h-y; vh++)
  136. if (data[vh*w] != *data) break;
  137. if (vh != sh) {
  138. ptr = data+1;
  139. int vw;
  140. for (vw = 1; vw < sw; vw++) {
  141. for (int i = 0; i < vh; i++)
  142. if (ptr[i*w] != *data) goto endOfVertSubrect;
  143. ptr++;
  144. }
  145. endOfVertSubrect:
  146. // If vertical subrect bigger than horizontal then use that.
  147. if (sw*sh < vw*vh) {
  148. sw = vw;
  149. sh = vh;
  150. }
  151. }
  152. nSubrects++;
  153. writePixel(os, *data);
  154. os->writeU16(x);
  155. os->writeU16(y);
  156. os->writeU16(sw);
  157. os->writeU16(sh);
  158. ptr = data+w;
  159. T* eor = data+w*sh;
  160. while (ptr < eor) {
  161. eol = ptr + sw;
  162. while (ptr < eol) *ptr++ = bg;
  163. ptr += w - sw;
  164. }
  165. x += sw;
  166. data += sw;
  167. }
  168. }
  169. return nSubrects;
  170. }