rre.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. #include "vnc.h"
  2. #include "vncs.h"
  3. /*
  4. * rise and run length encoding, aka rre.
  5. *
  6. * the pixel contained in r are subdivided into
  7. * rectangles of uniform color, each of which
  8. * is encoded by <color, x, y, w, h>.
  9. *
  10. * use raw encoding if it's shorter.
  11. *
  12. * for compact rre, use limited size rectangles,
  13. * which are shorter to encode and therefor give better compression.
  14. *
  15. * hextile encoding uses rre encoding on at most 16x16 rectangles tiled
  16. * across and then down the screen.
  17. */
  18. static int encrre(uchar *raw, int stride, int w, int h, int back, int pixb, uchar *buf, int maxr, uchar *done, int (*eqpix)(uchar*, int, int), uchar *(putr)(uchar*, uchar*, int, int, int, int, int, int));
  19. static int eqpix16(uchar *raw, int p1, int p2);
  20. static int eqpix32(uchar *raw, int p1, int p2);
  21. static int eqpix8(uchar *raw, int p1, int p2);
  22. static int findback(uchar *raw, int stride, int w, int h, int (*eqpix)(uchar*, int, int));
  23. static uchar* putcorre(uchar *buf, uchar *raw, int p, int pixb, int x, int y, int w, int h);
  24. static uchar* putrre(uchar *buf, uchar *raw, int p, int pixb, int x, int y, int w, int h);
  25. static void putpix(Vnc *v, uchar *raw, int p, int pixb);
  26. static int hexcolors(uchar *raw, int stride, int w, int h, int (*eqpix)(uchar*, int, int), int back, int *fore);
  27. static uchar *puthexfore(uchar *buf, uchar*, int, int, int x, int y, int w, int h);
  28. static uchar *puthexcol(uchar *buf, uchar*, int, int, int x, int y, int w, int h);
  29. static void sendtraw(Vnc *v, uchar *raw, int pixb, int stride, int w, int h);
  30. /*
  31. * default routine, no compression, just the pixels
  32. */
  33. void
  34. sendraw(Vncs *v, Rectangle r)
  35. {
  36. int pixb, stride;
  37. uchar *raw;
  38. if(!rectinrect(r, v->clientimage->r))
  39. sysfatal("sending bad rectangle");
  40. pixb = v->bpp >> 3;
  41. if((pixb << 3) != v->bpp)
  42. sysfatal("bad pixel math in sendraw");
  43. stride = v->clientimage->width*sizeof(ulong);
  44. if(((stride / pixb) * pixb) != stride)
  45. sysfatal("bad pixel math in sendraw");
  46. stride /= pixb;
  47. raw = byteaddr(v->clientimage, r.min);
  48. vncwrrect(v, r);
  49. vncwrlong(v, EncRaw);
  50. sendtraw(v, raw, pixb, stride, Dx(r), Dy(r));
  51. }
  52. /*
  53. * grab the image for the entire rectangle,
  54. * then encode each tile
  55. */
  56. void
  57. sendhextile(Vncs *v, Rectangle r)
  58. {
  59. uchar *(*putr)(uchar*, uchar*, int, int, int, int, int, int);
  60. int (*eq)(uchar*, int, int);
  61. uchar *raw, *buf, *done, *traw;
  62. int w, h, stride, pixb, pixlg, nr, bpr, back, fore;
  63. int sy, sx, th, tw, oback, ofore, k, nc;
  64. h = Dy(r);
  65. w = Dx(r);
  66. if(h == 0 || w == 0 || !rectinrect(r, v->clientimage->r))
  67. sysfatal("bad rectangle in sendhextile");
  68. switch(v->bpp){
  69. case 8: pixlg = 0; eq = eqpix8; break;
  70. case 16: pixlg = 1; eq = eqpix16; break;
  71. case 32: pixlg = 2; eq = eqpix32; break;
  72. default:
  73. sendraw(v, r);
  74. return;
  75. }
  76. pixb = 1 << pixlg;
  77. stride = v->clientimage->width*sizeof(ulong);
  78. if(((stride >> pixlg) << pixlg) != stride){
  79. sendraw(v, r);
  80. return;
  81. }
  82. stride >>= pixlg;
  83. buf = malloc(HextileDim * HextileDim * pixb);
  84. done = malloc(HextileDim * HextileDim);
  85. if(buf == nil || done == nil){
  86. free(buf);
  87. free(done);
  88. sendraw(v, r);
  89. return;
  90. }
  91. raw = byteaddr(v->clientimage, r.min);
  92. vncwrrect(v, r);
  93. vncwrlong(v, EncHextile);
  94. oback = -1;
  95. ofore = -1;
  96. for(sy = 0; sy < h; sy += HextileDim){
  97. th = h - sy;
  98. if(th > HextileDim)
  99. th = HextileDim;
  100. for(sx = 0; sx < w; sx += HextileDim){
  101. tw = w - sx;
  102. if(tw > HextileDim)
  103. tw = HextileDim;
  104. traw = raw + ((sy * stride + sx) << pixlg);
  105. back = findback(traw, stride, tw, th, eq);
  106. nc = hexcolors(traw, stride, tw, th, eq, back, &fore);
  107. k = 0;
  108. if(oback < 0 || !(*eq)(raw, back + ((traw - raw) >> pixlg), oback))
  109. k |= HextileBack;
  110. if(nc == 1){
  111. vncwrchar(v, k);
  112. if(k & HextileBack){
  113. oback = back + ((traw - raw) >> pixlg);
  114. putpix(v, raw, oback, pixb);
  115. }
  116. continue;
  117. }
  118. k |= HextileRects;
  119. if(nc == 2){
  120. putr = puthexfore;
  121. bpr = 2;
  122. if(ofore < 0 || !(*eq)(raw, fore + ((traw - raw) >> pixlg), ofore))
  123. k |= HextileFore;
  124. }else{
  125. putr = puthexcol;
  126. bpr = 2 + pixb;
  127. k |= HextileCols;
  128. /* stupid vnc clients smash foreground in this case */
  129. ofore = -1;
  130. }
  131. nr = th * tw << pixlg;
  132. if(k & HextileBack)
  133. nr -= pixb;
  134. if(k & HextileFore)
  135. nr -= pixb;
  136. nr /= bpr;
  137. memset(done, 0, HextileDim * HextileDim);
  138. nr = encrre(traw, stride, tw, th, back, pixb, buf, nr, done, eq, putr);
  139. if(nr < 0){
  140. vncwrchar(v, HextileRaw);
  141. sendtraw(v, traw, pixb, stride, tw, th);
  142. /* stupid vnc clients smash colors in this case */
  143. ofore = -1;
  144. oback = -1;
  145. }else{
  146. vncwrchar(v, k);
  147. if(k & HextileBack){
  148. oback = back + ((traw - raw) >> pixlg);
  149. putpix(v, raw, oback, pixb);
  150. }
  151. if(k & HextileFore){
  152. ofore = fore + ((traw - raw) >> pixlg);
  153. putpix(v, raw, ofore, pixb);
  154. }
  155. vncwrchar(v, nr);
  156. vncwrbytes(v, buf, nr * bpr);
  157. }
  158. }
  159. }
  160. free(buf);
  161. free(done);
  162. }
  163. static int
  164. hexcolors(uchar *raw, int stride, int w, int h, int (*eqpix)(uchar*, int, int), int back, int *rfore)
  165. {
  166. int s, es, sx, esx, fore;
  167. *rfore = -1;
  168. fore = -1;
  169. es = stride * h;
  170. for(s = 0; s < es; s += stride){
  171. esx = s + w;
  172. for(sx = s; sx < esx; sx++){
  173. if((*eqpix)(raw, back, sx))
  174. continue;
  175. if(fore < 0){
  176. fore = sx;
  177. *rfore = fore;
  178. }else if(!(*eqpix)(raw, fore, sx))
  179. return 3;
  180. }
  181. }
  182. if(fore < 0)
  183. return 1;
  184. return 2;
  185. }
  186. static uchar*
  187. puthexcol(uchar *buf, uchar *raw, int p, int pixb, int x, int y, int w, int h)
  188. {
  189. raw += p * pixb;
  190. while(pixb--)
  191. *buf++ = *raw++;
  192. *buf++ = (x << 4) | y;
  193. *buf++ = (w - 1) << 4 | (h - 1);
  194. return buf;
  195. }
  196. static uchar*
  197. puthexfore(uchar *buf, uchar*, int, int, int x, int y, int w, int h)
  198. {
  199. *buf++ = (x << 4) | y;
  200. *buf++ = (w - 1) << 4 | (h - 1);
  201. return buf;
  202. }
  203. static void
  204. sendtraw(Vnc *v, uchar *raw, int pixb, int stride, int w, int h)
  205. {
  206. int y;
  207. for(y = 0; y < h; y++)
  208. vncwrbytes(v, &raw[y * stride * pixb], w * pixb);
  209. }
  210. int
  211. rrerects(Rectangle r, int split)
  212. {
  213. return ((Dy(r) + split - 1) / split) * ((Dx(r) + split - 1) / split);
  214. }
  215. int
  216. sendrre(Vncs *v, Rectangle r, int split, int compact)
  217. {
  218. uchar *raw, *buf, *done;
  219. int w, h, stride, pixb, pixlg, nraw, nr, bpr, back, totr;
  220. int (*eq)(uchar*, int, int);
  221. totr = 0;
  222. h = Dy(r);
  223. while(h > split){
  224. h = r.max.y;
  225. r.max.y = r.min.y + split;
  226. totr += sendrre(v, r, split, compact);
  227. r.min.y = r.max.y;
  228. r.max.y = h;
  229. h = Dy(r);
  230. }
  231. w = Dx(r);
  232. while(w > split){
  233. w = r.max.x;
  234. r.max.x = r.min.x + split;
  235. totr += sendrre(v, r, split, compact);
  236. r.min.x = r.max.x;
  237. r.max.x = w;
  238. w = Dx(r);
  239. }
  240. if(h == 0 || w == 0 || !rectinrect(r, v->clientimage->r))
  241. sysfatal("bad rectangle in sendrre");
  242. switch(v->bpp){
  243. case 8: pixlg = 0; eq = eqpix8; break;
  244. case 16: pixlg = 1; eq = eqpix16; break;
  245. case 32: pixlg = 2; eq = eqpix32; break;
  246. default:
  247. sendraw(v, r);
  248. return totr + 1;
  249. }
  250. pixb = 1 << pixlg;
  251. stride = v->clientimage->width*sizeof(ulong);
  252. if(((stride >> pixlg) << pixlg) != stride){
  253. sendraw(v, r);
  254. return totr + 1;
  255. }
  256. stride >>= pixlg;
  257. nraw = w * pixb * h;
  258. buf = malloc(nraw);
  259. done = malloc(w * h);
  260. if(buf == nil || done == nil){
  261. free(buf);
  262. free(done);
  263. sendraw(v, r);
  264. return totr + 1;
  265. }
  266. memset(done, 0, w * h);
  267. raw = byteaddr(v->clientimage, r.min);
  268. if(compact)
  269. bpr = 4 * 1 + pixb;
  270. else
  271. bpr = 4 * 2 + pixb;
  272. nr = (nraw - 4 - pixb) / bpr;
  273. back = findback(raw, stride, w, h, eq);
  274. if(compact)
  275. nr = encrre(raw, stride, w, h, back, pixb, buf, nr, done, eq, putcorre);
  276. else
  277. nr = encrre(raw, stride, w, h, back, pixb, buf, nr, done, eq, putrre);
  278. if(nr < 0){
  279. vncwrrect(v, r);
  280. vncwrlong(v, EncRaw);
  281. sendtraw(v, raw, pixb, stride, w, h);
  282. }else{
  283. vncwrrect(v, r);
  284. if(compact)
  285. vncwrlong(v, EncCorre);
  286. else
  287. vncwrlong(v, EncRre);
  288. vncwrlong(v, nr);
  289. putpix(v, raw, back, pixb);
  290. vncwrbytes(v, buf, nr * bpr);
  291. }
  292. free(buf);
  293. free(done);
  294. return totr + 1;
  295. }
  296. static int
  297. encrre(uchar *raw, int stride, int w, int h, int back, int pixb, uchar *buf, int maxr, uchar *done, int (*eqpix)(uchar*, int, int), uchar *(*putr)(uchar*, uchar*, int, int, int, int, int, int))
  298. {
  299. int s, es, sx, esx, sy, syx, esyx, rh, rw, y, nr, dsy, dp;
  300. es = stride * h;
  301. y = 0;
  302. nr = 0;
  303. dp = 0;
  304. for(s = 0; s < es; s += stride){
  305. esx = s + w;
  306. for(sx = s; sx < esx; ){
  307. rw = done[dp];
  308. if(rw){
  309. sx += rw;
  310. dp += rw;
  311. continue;
  312. }
  313. if((*eqpix)(raw, back, sx)){
  314. sx++;
  315. dp++;
  316. continue;
  317. }
  318. if(nr >= maxr)
  319. return -1;
  320. /*
  321. * find the tallest maximally wide uniform colored rectangle
  322. * with p at the upper left.
  323. * this isn't an optimal parse, but it's pretty good for text
  324. */
  325. rw = esx - sx;
  326. rh = 0;
  327. for(sy = sx; sy < es; sy += stride){
  328. if(!(*eqpix)(raw, sx, sy))
  329. break;
  330. esyx = sy + rw;
  331. for(syx = sy + 1; syx < esyx; syx++){
  332. if(!(*eqpix)(raw, sx, syx)){
  333. if(sy == sx)
  334. break;
  335. goto breakout;
  336. }
  337. }
  338. if(sy == sx)
  339. rw = syx - sy;
  340. rh++;
  341. }
  342. breakout:;
  343. nr++;
  344. buf = (*putr)(buf, raw, sx, pixb, sx - s, y, rw, rh);
  345. /*
  346. * mark all pixels done
  347. */
  348. dsy = dp;
  349. while(rh--){
  350. esyx = dsy + rw;
  351. for(syx = dsy; syx < esyx; syx++)
  352. done[syx] = esyx - syx;
  353. dsy += w;
  354. }
  355. sx += rw;
  356. dp += rw;
  357. }
  358. y++;
  359. }
  360. return nr;
  361. }
  362. /*
  363. * estimate the background color
  364. * by finding the most frequent character in a small sample
  365. */
  366. static int
  367. findback(uchar *raw, int stride, int w, int h, int (*eqpix)(uchar*, int, int))
  368. {
  369. enum{
  370. NCol = 6,
  371. NExamine = 4
  372. };
  373. int ccount[NCol], col[NCol], i, wstep, hstep, x, y, pix, c, max, maxc;
  374. wstep = w / NExamine;
  375. if(wstep < 1)
  376. wstep = 1;
  377. hstep = h / NExamine;
  378. if(hstep < 1)
  379. hstep = 1;
  380. for(i = 0; i< NCol; i++)
  381. ccount[i] = 0;
  382. for(y = 0; y < h; y += hstep){
  383. for(x = 0; x < w; x += wstep){
  384. pix = y * stride + x;
  385. for(i = 0; i < NCol; i++){
  386. if(ccount[i] == 0){
  387. ccount[i] = 1;
  388. col[i] = pix;
  389. break;
  390. }
  391. if((*eqpix)(raw, pix, col[i])){
  392. ccount[i]++;
  393. break;
  394. }
  395. }
  396. }
  397. }
  398. maxc = ccount[0];
  399. max = 0;
  400. for(i = 1; i < NCol; i++){
  401. c = ccount[i];
  402. if(!c)
  403. break;
  404. if(c > maxc){
  405. max = i;
  406. maxc = c;
  407. }
  408. }
  409. return col[max];
  410. }
  411. static uchar*
  412. putrre(uchar *buf, uchar *raw, int p, int pixb, int x, int y, int w, int h)
  413. {
  414. raw += p * pixb;
  415. while(pixb--)
  416. *buf++ = *raw++;
  417. *buf++ = x >> 8;
  418. *buf++ = x;
  419. *buf++ = y >> 8;
  420. *buf++ = y;
  421. *buf++ = w >> 8;
  422. *buf++ = w;
  423. *buf++ = h >> 8;
  424. *buf++ = h;
  425. return buf;
  426. }
  427. static uchar*
  428. putcorre(uchar *buf, uchar *raw, int p, int pixb, int x, int y, int w, int h)
  429. {
  430. raw += p * pixb;
  431. while(pixb--)
  432. *buf++ = *raw++;
  433. *buf++ = x;
  434. *buf++ = y;
  435. *buf++ = w;
  436. *buf++ = h;
  437. return buf;
  438. }
  439. static int
  440. eqpix8(uchar *raw, int p1, int p2)
  441. {
  442. return raw[p1] == raw[p2];
  443. }
  444. static int
  445. eqpix16(uchar *raw, int p1, int p2)
  446. {
  447. return ((ushort*)raw)[p1] == ((ushort*)raw)[p2];
  448. }
  449. static int
  450. eqpix32(uchar *raw, int p1, int p2)
  451. {
  452. return ((ulong*)raw)[p1] == ((ulong*)raw)[p2];
  453. }
  454. static void
  455. putpix(Vnc *v, uchar *raw, int p, int pixb)
  456. {
  457. vncwrbytes(v, raw + p * pixb, pixb);
  458. }