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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. * Copyright (C) 2005 Constantin Kaplinsky. All Rights Reserved.
  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. //
  20. // Hextile encoding function.
  21. //
  22. // This file is #included after having set the following macro:
  23. // BPP - 8, 16 or 32
  24. #include <rdr/OutStream.h>
  25. #include <rfb/hextileConstants.h>
  26. namespace rfb {
  27. // CONCAT2E concatenates its arguments, expanding them if they are macros
  28. #ifndef CONCAT2E
  29. #define CONCAT2(a,b) a##b
  30. #define CONCAT2E(a,b) CONCAT2(a,b)
  31. #endif
  32. #define PIXEL_T rdr::CONCAT2E(U,BPP)
  33. #define WRITE_PIXEL CONCAT2E(writeOpaque,BPP)
  34. #define HEXTILE_ENCODE CONCAT2E(hextileEncode,BPP)
  35. #define HEXTILE_ENCODE_TILE CONCAT2E(hextileEncodeTile,BPP)
  36. #define TEST_TILE_TYPE CONCAT2E(hextileTestTileType,BPP)
  37. int TEST_TILE_TYPE (PIXEL_T* data, int w, int h, PIXEL_T* bg, PIXEL_T* fg);
  38. int HEXTILE_ENCODE_TILE (PIXEL_T* data, int w, int h, int tileType,
  39. rdr::U8* encoded, PIXEL_T bg);
  40. void HEXTILE_ENCODE(const Rect& r, rdr::OutStream* os,
  41. const PixelFormat& pf, PixelBuffer* pb)
  42. {
  43. Rect t;
  44. PIXEL_T buf[256];
  45. PIXEL_T oldBg = 0, oldFg = 0;
  46. bool oldBgValid = false;
  47. bool oldFgValid = false;
  48. rdr::U8 encoded[256*(BPP/8)];
  49. for (t.tl.y = r.tl.y; t.tl.y < r.br.y; t.tl.y += 16) {
  50. t.br.y = __rfbmin(r.br.y, t.tl.y + 16);
  51. for (t.tl.x = r.tl.x; t.tl.x < r.br.x; t.tl.x += 16) {
  52. t.br.x = __rfbmin(r.br.x, t.tl.x + 16);
  53. pb->getImage(pf, buf, t);
  54. PIXEL_T bg = 0, fg = 0;
  55. int tileType = TEST_TILE_TYPE(buf, t.width(), t.height(), &bg, &fg);
  56. if (!oldBgValid || oldBg != bg) {
  57. tileType |= hextileBgSpecified;
  58. oldBg = bg;
  59. oldBgValid = true;
  60. }
  61. int encodedLen = 0;
  62. if (tileType & hextileAnySubrects) {
  63. if (tileType & hextileSubrectsColoured) {
  64. oldFgValid = false;
  65. } else {
  66. if (!oldFgValid || oldFg != fg) {
  67. tileType |= hextileFgSpecified;
  68. oldFg = fg;
  69. oldFgValid = true;
  70. }
  71. }
  72. encodedLen = HEXTILE_ENCODE_TILE(buf, t.width(), t.height(), tileType,
  73. encoded, bg);
  74. if (encodedLen < 0) {
  75. pb->getImage(pf, buf, t);
  76. os->writeU8(hextileRaw);
  77. os->writeBytes(buf, t.width() * t.height() * (BPP/8));
  78. oldBgValid = oldFgValid = false;
  79. continue;
  80. }
  81. }
  82. os->writeU8(tileType);
  83. if (tileType & hextileBgSpecified) os->WRITE_PIXEL(bg);
  84. if (tileType & hextileFgSpecified) os->WRITE_PIXEL(fg);
  85. if (tileType & hextileAnySubrects) os->writeBytes(encoded, encodedLen);
  86. }
  87. }
  88. }
  89. int HEXTILE_ENCODE_TILE (PIXEL_T* data, int w, int h, int tileType,
  90. rdr::U8* encoded, PIXEL_T bg)
  91. {
  92. rdr::U8* nSubrectsPtr = encoded;
  93. *nSubrectsPtr = 0;
  94. encoded++;
  95. for (int y = 0; y < h; y++)
  96. {
  97. int x = 0;
  98. while (x < w) {
  99. if (*data == bg) {
  100. x++;
  101. data++;
  102. continue;
  103. }
  104. // Find horizontal subrect first
  105. PIXEL_T* ptr = data+1;
  106. PIXEL_T* eol = data+w-x;
  107. while (ptr < eol && *ptr == *data) ptr++;
  108. int sw = ptr - data;
  109. ptr = data + w;
  110. int sh = 1;
  111. while (sh < h-y) {
  112. eol = ptr + sw;
  113. while (ptr < eol)
  114. if (*ptr++ != *data) goto endOfSubrect;
  115. ptr += w - sw;
  116. sh++;
  117. }
  118. endOfSubrect:
  119. (*nSubrectsPtr)++;
  120. if (tileType & hextileSubrectsColoured) {
  121. if (encoded - nSubrectsPtr + (BPP/8) > w*h*(BPP/8)) return -1;
  122. #if (BPP == 8)
  123. *encoded++ = *data;
  124. #elif (BPP == 16)
  125. *encoded++ = ((rdr::U8*)data)[0];
  126. *encoded++ = ((rdr::U8*)data)[1];
  127. #elif (BPP == 32)
  128. *encoded++ = ((rdr::U8*)data)[0];
  129. *encoded++ = ((rdr::U8*)data)[1];
  130. *encoded++ = ((rdr::U8*)data)[2];
  131. *encoded++ = ((rdr::U8*)data)[3];
  132. #endif
  133. }
  134. if (encoded - nSubrectsPtr + 2 > w*h*(BPP/8)) return -1;
  135. *encoded++ = (x << 4) | y;
  136. *encoded++ = ((sw-1) << 4) | (sh-1);
  137. ptr = data+w;
  138. PIXEL_T* eor = data+w*sh;
  139. while (ptr < eor) {
  140. eol = ptr + sw;
  141. while (ptr < eol) *ptr++ = bg;
  142. ptr += w - sw;
  143. }
  144. x += sw;
  145. data += sw;
  146. }
  147. }
  148. return encoded - nSubrectsPtr;
  149. }
  150. int TEST_TILE_TYPE (PIXEL_T* data, int w, int h, PIXEL_T* bg, PIXEL_T* fg)
  151. {
  152. PIXEL_T pix1 = *data;
  153. PIXEL_T* end = data + w * h;
  154. PIXEL_T* ptr = data + 1;
  155. while (ptr < end && *ptr == pix1)
  156. ptr++;
  157. if (ptr == end) {
  158. *bg = pix1;
  159. return 0; // solid-color tile
  160. }
  161. int count1 = ptr - data;
  162. int count2 = 1;
  163. PIXEL_T pix2 = *ptr++;
  164. int tileType = hextileAnySubrects;
  165. for (; ptr < end; ptr++) {
  166. if (*ptr == pix1) {
  167. count1++;
  168. } else if (*ptr == pix2) {
  169. count2++;
  170. } else {
  171. tileType |= hextileSubrectsColoured;
  172. break;
  173. }
  174. }
  175. if (count1 >= count2) {
  176. *bg = pix1; *fg = pix2;
  177. } else {
  178. *bg = pix2; *fg = pix1;
  179. }
  180. return tileType;
  181. }
  182. #undef PIXEL_T
  183. #undef WRITE_PIXEL
  184. #undef HEXTILE_ENCODE
  185. #undef HEXTILE_ENCODE_TILE
  186. #undef TEST_TILE_TYPE
  187. }