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.

hextileEncode.h 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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(rdr::OutStream* os, const PixelBuffer* pb)
  41. {
  42. Rect t;
  43. PIXEL_T buf[256];
  44. PIXEL_T oldBg = 0, oldFg = 0;
  45. bool oldBgValid = false;
  46. bool oldFgValid = false;
  47. rdr::U8 encoded[256*(BPP/8)];
  48. for (t.tl.y = 0; t.tl.y < pb->height(); t.tl.y += 16) {
  49. t.br.y = __rfbmin(pb->height(), t.tl.y + 16);
  50. for (t.tl.x = 0; t.tl.x < pb->width(); t.tl.x += 16) {
  51. t.br.x = __rfbmin(pb->width(), t.tl.x + 16);
  52. pb->getImage(buf, t);
  53. PIXEL_T bg = 0, fg = 0;
  54. int tileType = TEST_TILE_TYPE(buf, t.width(), t.height(), &bg, &fg);
  55. if (!oldBgValid || oldBg != bg) {
  56. tileType |= hextileBgSpecified;
  57. oldBg = bg;
  58. oldBgValid = true;
  59. }
  60. int encodedLen = 0;
  61. if (tileType & hextileAnySubrects) {
  62. if (tileType & hextileSubrectsColoured) {
  63. oldFgValid = false;
  64. } else {
  65. if (!oldFgValid || oldFg != fg) {
  66. tileType |= hextileFgSpecified;
  67. oldFg = fg;
  68. oldFgValid = true;
  69. }
  70. }
  71. encodedLen = HEXTILE_ENCODE_TILE(buf, t.width(), t.height(), tileType,
  72. encoded, bg);
  73. if (encodedLen < 0) {
  74. pb->getImage(buf, t);
  75. os->writeU8(hextileRaw);
  76. os->writeBytes(buf, t.width() * t.height() * (BPP/8));
  77. oldBgValid = oldFgValid = false;
  78. continue;
  79. }
  80. }
  81. os->writeU8(tileType);
  82. if (tileType & hextileBgSpecified) os->WRITE_PIXEL(bg);
  83. if (tileType & hextileFgSpecified) os->WRITE_PIXEL(fg);
  84. if (tileType & hextileAnySubrects) os->writeBytes(encoded, encodedLen);
  85. }
  86. }
  87. }
  88. int HEXTILE_ENCODE_TILE (PIXEL_T* data, int w, int h, int tileType,
  89. rdr::U8* encoded, PIXEL_T bg)
  90. {
  91. rdr::U8* nSubrectsPtr = encoded;
  92. *nSubrectsPtr = 0;
  93. encoded++;
  94. for (int y = 0; y < h; y++)
  95. {
  96. int x = 0;
  97. while (x < w) {
  98. if (*data == bg) {
  99. x++;
  100. data++;
  101. continue;
  102. }
  103. // Find horizontal subrect first
  104. PIXEL_T* ptr = data+1;
  105. PIXEL_T* eol = data+w-x;
  106. while (ptr < eol && *ptr == *data) ptr++;
  107. int sw = ptr - data;
  108. ptr = data + w;
  109. int sh = 1;
  110. while (sh < h-y) {
  111. eol = ptr + sw;
  112. while (ptr < eol)
  113. if (*ptr++ != *data) goto endOfSubrect;
  114. ptr += w - sw;
  115. sh++;
  116. }
  117. endOfSubrect:
  118. (*nSubrectsPtr)++;
  119. if (tileType & hextileSubrectsColoured) {
  120. if (encoded - nSubrectsPtr + (BPP/8) > w*h*(BPP/8)) return -1;
  121. #if (BPP == 8)
  122. *encoded++ = *data;
  123. #elif (BPP == 16)
  124. *encoded++ = ((rdr::U8*)data)[0];
  125. *encoded++ = ((rdr::U8*)data)[1];
  126. #elif (BPP == 32)
  127. *encoded++ = ((rdr::U8*)data)[0];
  128. *encoded++ = ((rdr::U8*)data)[1];
  129. *encoded++ = ((rdr::U8*)data)[2];
  130. *encoded++ = ((rdr::U8*)data)[3];
  131. #endif
  132. }
  133. if (encoded - nSubrectsPtr + 2 > w*h*(BPP/8)) return -1;
  134. *encoded++ = (x << 4) | y;
  135. *encoded++ = ((sw-1) << 4) | (sh-1);
  136. ptr = data+w;
  137. PIXEL_T* eor = data+w*sh;
  138. while (ptr < eor) {
  139. eol = ptr + sw;
  140. while (ptr < eol) *ptr++ = bg;
  141. ptr += w - sw;
  142. }
  143. x += sw;
  144. data += sw;
  145. }
  146. }
  147. return encoded - nSubrectsPtr;
  148. }
  149. int TEST_TILE_TYPE (PIXEL_T* data, int w, int h, PIXEL_T* bg, PIXEL_T* fg)
  150. {
  151. PIXEL_T pix1 = *data;
  152. PIXEL_T* end = data + w * h;
  153. PIXEL_T* ptr = data + 1;
  154. while (ptr < end && *ptr == pix1)
  155. ptr++;
  156. if (ptr == end) {
  157. *bg = pix1;
  158. return 0; // solid-color tile
  159. }
  160. int count1 = ptr - data;
  161. int count2 = 1;
  162. PIXEL_T pix2 = *ptr++;
  163. int tileType = hextileAnySubrects;
  164. for (; ptr < end; ptr++) {
  165. if (*ptr == pix1) {
  166. count1++;
  167. } else if (*ptr == pix2) {
  168. count2++;
  169. } else {
  170. tileType |= hextileSubrectsColoured;
  171. break;
  172. }
  173. }
  174. if (count1 >= count2) {
  175. *bg = pix1; *fg = pix2;
  176. } else {
  177. *bg = pix2; *fg = pix1;
  178. }
  179. return tileType;
  180. }
  181. #undef PIXEL_T
  182. #undef WRITE_PIXEL
  183. #undef HEXTILE_ENCODE
  184. #undef HEXTILE_ENCODE_TILE
  185. #undef TEST_TILE_TYPE
  186. }