1 /*
2  * tight.c
3  *
4  * Routines to implement Tight Encoding
5  */
6 
7 /*
8  *  Copyright (C) 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
9  *  Copyright (C) 2004 Landmark Graphics Corporation.  All Rights Reserved.
10  *  Copyright (C) 2000, 2001 Const Kaplinsky.  All Rights Reserved.
11  *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
12  *
13  *  This is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 2 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This software is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this software; if not, write to the Free Software
25  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
26  *  USA.
27  */
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include "rfb.h"
33 #include "turbojpeg.h"
34 
35 /* Note: The following constant should not be changed. */
36 #define TIGHT_MIN_TO_COMPRESS 12
37 
38 /* The parameters below may be adjusted. */
39 #define MIN_SPLIT_RECT_SIZE     4096
40 #define MIN_SOLID_SUBRECT_SIZE  2048
41 #define MAX_SPLIT_TILE_SIZE       16
42 
43 /* This variable is set on every rfbSendRectEncodingTight() call. */
44 static Bool usePixelFormat24;
45 
46 
47 /* Compression level stuff. The following array contains various
48    encoder parameters for each of 10 compression levels (0..9).
49    Last three parameters correspond to JPEG quality levels (0..9). */
50 
51 typedef struct TIGHT_CONF_s {
52     int maxRectSize, maxRectWidth;
53     int monoMinRectSize;
54     int idxZlibLevel, monoZlibLevel, rawZlibLevel;
55     int idxMaxColorsDivisor;
56 } TIGHT_CONF;
57 
58 static TIGHT_CONF tightConf[2] = {
59     { 65536, 2048,   6, 0, 0, 0,   4 },
60 #if 0
61     {  2048,  128,   6, 1, 1, 1,   8 },
62     {  6144,  256,   8, 3, 3, 2,  24 },
63     { 10240, 1024,  12, 5, 5, 3,  32 },
64     { 16384, 2048,  12, 6, 6, 4,  32 },
65     { 32768, 2048,  12, 7, 7, 5,  32 },
66     { 65536, 2048,  16, 7, 7, 6,  48 },
67     { 65536, 2048,  16, 8, 8, 7,  64 },
68     { 65536, 2048,  32, 9, 9, 8,  64 },
69 #endif
70     { 65536, 2048,  32, 1, 1, 1,  96 }
71 };
72 
73 static int compressLevel;
74 static int qualityLevel;
75 static int subsampLevel;
76 
77 static const int subsampLevel2tjsubsamp[4] = {
78     TJ_444, TJ_411, TJ_422, TJ_GRAYSCALE
79 };
80 
81 /* Stuff dealing with palettes. */
82 
83 typedef struct COLOR_LIST_s {
84     struct COLOR_LIST_s *next;
85     int idx;
86     CARD32 rgb;
87 } COLOR_LIST;
88 
89 typedef struct PALETTE_ENTRY_s {
90     COLOR_LIST *listNode;
91     int numPixels;
92 } PALETTE_ENTRY;
93 
94 typedef struct PALETTE_s {
95     PALETTE_ENTRY entry[256];
96     COLOR_LIST *hash[256];
97     COLOR_LIST list[256];
98 } PALETTE;
99 
100 static int paletteNumColors, paletteMaxColors;
101 static CARD32 monoBackground, monoForeground;
102 static PALETTE palette;
103 
104 /* Pointers to dynamically-allocated buffers. */
105 
106 static int tightBeforeBufSize = 0;
107 static char *tightBeforeBuf = NULL;
108 
109 static int tightAfterBufSize = 0;
110 static char *tightAfterBuf = NULL;
111 
112 static int *prevRowBuf = NULL;
113 
114 
115 /* Prototypes for static functions. */
116 
117 static void FindBestSolidArea (int x, int y, int w, int h,
118                                CARD32 colorValue, int *w_ptr, int *h_ptr);
119 static void ExtendSolidArea   (int x, int y, int w, int h,
120                                CARD32 colorValue,
121                                int *x_ptr, int *y_ptr, int *w_ptr, int *h_ptr);
122 static Bool CheckSolidTile    (int x, int y, int w, int h,
123                                CARD32 *colorPtr, Bool needSameColor);
124 static Bool CheckSolidTile8   (int x, int y, int w, int h,
125                                CARD32 *colorPtr, Bool needSameColor);
126 static Bool CheckSolidTile16  (int x, int y, int w, int h,
127                                CARD32 *colorPtr, Bool needSameColor);
128 static Bool CheckSolidTile32  (int x, int y, int w, int h,
129                                CARD32 *colorPtr, Bool needSameColor);
130 
131 static Bool SendRectSimple    (rfbClientPtr cl, int x, int y, int w, int h);
132 static Bool SendSubrect       (rfbClientPtr cl, int x, int y, int w, int h);
133 static Bool SendTightHeader   (rfbClientPtr cl, int x, int y, int w, int h);
134 
135 static Bool SendSolidRect     (rfbClientPtr cl);
136 static Bool SendMonoRect      (rfbClientPtr cl, int w, int h);
137 static Bool SendIndexedRect   (rfbClientPtr cl, int w, int h);
138 static Bool SendFullColorRect (rfbClientPtr cl, int w, int h);
139 
140 static Bool CompressData(rfbClientPtr cl, int streamId, int dataLen,
141                          int zlibLevel, int zlibStrategy);
142 static Bool SendCompressedData(rfbClientPtr cl, char *buf, int compressedLen);
143 
144 static void FillPalette8(int count);
145 static void FillPalette16(int count);
146 static void FillPalette32(int count);
147 static void FastFillPalette16(rfbClientPtr cl, CARD16 *data, int w, int pitch,
148                               int h);
149 static void FastFillPalette32(rfbClientPtr cl, CARD32 *data, int w, int pitch,
150                               int h);
151 
152 static void PaletteReset(void);
153 static int PaletteInsert(CARD32 rgb, int numPixels, int bpp);
154 
155 static void Pack24(char *buf, rfbPixelFormat *fmt, int count);
156 
157 static void EncodeIndexedRect16(CARD8 *buf, int count);
158 static void EncodeIndexedRect32(CARD8 *buf, int count);
159 
160 static void EncodeMonoRect8(CARD8 *buf, int w, int h);
161 static void EncodeMonoRect16(CARD8 *buf, int w, int h);
162 static void EncodeMonoRect32(CARD8 *buf, int w, int h);
163 
164 static Bool SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h,
165                          int quality);
166 
167 /*
168  * Tight encoding implementation.
169  */
170 
171 int
rfbNumCodedRectsTight(cl,x,y,w,h)172 rfbNumCodedRectsTight(cl, x, y, w, h)
173     rfbClientPtr cl;
174     int x, y, w, h;
175 {
176     int maxRectSize, maxRectWidth;
177     int subrectMaxWidth, subrectMaxHeight;
178 
179     /* No matter how many rectangles we will send if LastRect markers
180        are used to terminate rectangle stream. */
181     if (cl->enableLastRectEncoding && w * h >= MIN_SPLIT_RECT_SIZE)
182       return 0;
183 
184     maxRectSize = tightConf[compressLevel].maxRectSize;
185     maxRectWidth = tightConf[compressLevel].maxRectWidth;
186 
187     if (w > maxRectWidth || w * h > maxRectSize) {
188         subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w;
189         subrectMaxHeight = maxRectSize / subrectMaxWidth;
190         return (((w - 1) / maxRectWidth + 1) *
191                 ((h - 1) / subrectMaxHeight + 1));
192     } else {
193         return 1;
194     }
195 }
196 
197 Bool
rfbSendRectEncodingTight(cl,x,y,w,h)198 rfbSendRectEncodingTight(cl, x, y, w, h)
199     rfbClientPtr cl;
200     int x, y, w, h;
201 {
202     int nMaxRows;
203     CARD32 colorValue;
204     int dx, dy, dw, dh;
205     int x_best, y_best, w_best, h_best;
206     char *fbptr;
207 
208     compressLevel = cl->tightCompressLevel > 0 ? 1 : 0;
209     qualityLevel = cl->tightQualityLevel;
210     if (qualityLevel != -1) {
211         compressLevel = 1;
212         tightConf[compressLevel].idxZlibLevel = 1;
213         tightConf[compressLevel].monoZlibLevel = 1;
214         tightConf[compressLevel].rawZlibLevel = 1;
215     } else {
216         tightConf[compressLevel].idxZlibLevel = cl->tightCompressLevel;
217         tightConf[compressLevel].monoZlibLevel = cl->tightCompressLevel;
218         tightConf[compressLevel].rawZlibLevel = cl->tightCompressLevel;
219     }
220     subsampLevel = cl->tightSubsampLevel;
221 
222     if ( cl->format.depth == 24 && cl->format.redMax == 0xFF &&
223          cl->format.greenMax == 0xFF && cl->format.blueMax == 0xFF ) {
224         usePixelFormat24 = TRUE;
225     } else {
226         usePixelFormat24 = FALSE;
227     }
228 
229     if (!cl->enableLastRectEncoding || w * h < MIN_SPLIT_RECT_SIZE)
230         return SendRectSimple(cl, x, y, w, h);
231 
232     /* Make sure we can write at least one pixel into tightBeforeBuf. */
233 
234     if (tightBeforeBufSize < 4) {
235         tightBeforeBufSize = 4;
236         if (tightBeforeBuf == NULL)
237             tightBeforeBuf = (char *)xalloc(tightBeforeBufSize);
238         else
239             tightBeforeBuf = (char *)xrealloc(tightBeforeBuf,
240                                               tightBeforeBufSize);
241     }
242 
243     /* Calculate maximum number of rows in one non-solid rectangle. */
244 
245     {
246         int maxRectSize, maxRectWidth, nMaxWidth;
247 
248         maxRectSize = tightConf[compressLevel].maxRectSize;
249         maxRectWidth = tightConf[compressLevel].maxRectWidth;
250         nMaxWidth = (w > maxRectWidth) ? maxRectWidth : w;
251         nMaxRows = maxRectSize / nMaxWidth;
252     }
253 
254     /* Try to find large solid-color areas and send them separately. */
255 
256     for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) {
257 
258         /* If a rectangle becomes too large, send its upper part now. */
259 
260         if (dy - y >= nMaxRows) {
261             if (!SendRectSimple(cl, x, y, w, nMaxRows))
262                 return 0;
263             y += nMaxRows;
264             h -= nMaxRows;
265         }
266 
267         dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ?
268             MAX_SPLIT_TILE_SIZE : (y + h - dy);
269 
270         for (dx = x; dx < x + w; dx += MAX_SPLIT_TILE_SIZE) {
271 
272             dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w) ?
273                 MAX_SPLIT_TILE_SIZE : (x + w - dx);
274 
275             if (CheckSolidTile(dx, dy, dw, dh, &colorValue, FALSE)) {
276 
277                 if (subsampLevel == TJ_GRAYSCALE && qualityLevel != -1) {
278 		    CARD32 r=(colorValue>>16)&0xFF;
279 		    CARD32 g=(colorValue>>8)&0xFF;
280 		    CARD32 b=(colorValue)&0xFF;
281 		    double y=(0.257*(double)r)+(0.504*(double)g)
282 		        +(0.098*(double)b)+16.;
283 		    colorValue=(int)y+(((int)y)<<8)+(((int)y)<<16);
284 		}
285 
286                 /* Get dimensions of solid-color area. */
287 
288                 FindBestSolidArea(dx, dy, w - (dx - x), h - (dy - y),
289 				  colorValue, &w_best, &h_best);
290 
291                 /* Make sure a solid rectangle is large enough
292                    (or the whole rectangle is of the same color). */
293 
294                 if ( w_best * h_best != w * h &&
295                      w_best * h_best < MIN_SOLID_SUBRECT_SIZE )
296                     continue;
297 
298                 /* Try to extend solid rectangle to maximum size. */
299 
300                 x_best = dx; y_best = dy;
301                 ExtendSolidArea(x, y, w, h, colorValue,
302                                 &x_best, &y_best, &w_best, &h_best);
303 
304                 /* Send rectangles at top and left to solid-color area. */
305 
306                 if ( y_best != y &&
307                      !SendRectSimple(cl, x, y, w, y_best-y) )
308                     return FALSE;
309                 if ( x_best != x &&
310                      !rfbSendRectEncodingTight(cl, x, y_best,
311                                                x_best-x, h_best) )
312                     return FALSE;
313 
314                 /* Send solid-color rectangle. */
315 
316                 if (!SendTightHeader(cl, x_best, y_best, w_best, h_best))
317                     return FALSE;
318 
319                 fbptr = (rfbScreen.pfbMemory +
320                          (rfbScreen.paddedWidthInBytes * y_best) +
321                          (x_best * (rfbScreen.bitsPerPixel / 8)));
322 
323                 (*cl->translateFn)(cl->translateLookupTable, &rfbServerFormat,
324                                    &cl->format, fbptr, tightBeforeBuf,
325                                    rfbScreen.paddedWidthInBytes, 1, 1);
326 
327                 if (!SendSolidRect(cl))
328                     return FALSE;
329 
330                 /* Send remaining rectangles (at right and bottom). */
331 
332                 if ( x_best + w_best != x + w &&
333                      !rfbSendRectEncodingTight(cl, x_best+w_best, y_best,
334                                                w-(x_best-x)-w_best, h_best) )
335                     return FALSE;
336                 if ( y_best + h_best != y + h &&
337                      !rfbSendRectEncodingTight(cl, x, y_best+h_best,
338                                                w, h-(y_best-y)-h_best) )
339                     return FALSE;
340 
341                 /* Return after all recursive calls are done. */
342 
343                 return TRUE;
344             }
345 
346         }
347 
348     }
349 
350     /* No suitable solid-color rectangles found. */
351 
352     return SendRectSimple(cl, x, y, w, h);
353 }
354 
355 static void
FindBestSolidArea(x,y,w,h,colorValue,w_ptr,h_ptr)356 FindBestSolidArea(x, y, w, h, colorValue, w_ptr, h_ptr)
357     int x, y, w, h;
358     CARD32 colorValue;
359     int *w_ptr, *h_ptr;
360 {
361     int dx, dy, dw, dh;
362     int w_prev;
363     int w_best = 0, h_best = 0;
364 
365     w_prev = w;
366 
367     for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) {
368 
369         dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ?
370             MAX_SPLIT_TILE_SIZE : (y + h - dy);
371         dw = (w_prev > MAX_SPLIT_TILE_SIZE) ?
372             MAX_SPLIT_TILE_SIZE : w_prev;
373 
374         if (!CheckSolidTile(x, dy, dw, dh, &colorValue, TRUE))
375             break;
376 
377         for (dx = x + dw; dx < x + w_prev;) {
378             dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w_prev) ?
379                 MAX_SPLIT_TILE_SIZE : (x + w_prev - dx);
380             if (!CheckSolidTile(dx, dy, dw, dh, &colorValue, TRUE))
381                 break;
382 	    dx += dw;
383         }
384 
385         w_prev = dx - x;
386         if (w_prev * (dy + dh - y) > w_best * h_best) {
387             w_best = w_prev;
388             h_best = dy + dh - y;
389         }
390     }
391 
392     *w_ptr = w_best;
393     *h_ptr = h_best;
394 }
395 
396 static void
ExtendSolidArea(x,y,w,h,colorValue,x_ptr,y_ptr,w_ptr,h_ptr)397 ExtendSolidArea(x, y, w, h, colorValue, x_ptr, y_ptr, w_ptr, h_ptr)
398     int x, y, w, h;
399     CARD32 colorValue;
400     int *x_ptr, *y_ptr, *w_ptr, *h_ptr;
401 {
402     int cx, cy;
403 
404     /* Try to extend the area upwards. */
405     for ( cy = *y_ptr - 1;
406           cy >= y && CheckSolidTile(*x_ptr, cy, *w_ptr, 1, &colorValue, TRUE);
407           cy-- );
408     *h_ptr += *y_ptr - (cy + 1);
409     *y_ptr = cy + 1;
410 
411     /* ... downwards. */
412     for ( cy = *y_ptr + *h_ptr;
413           cy < y + h &&
414               CheckSolidTile(*x_ptr, cy, *w_ptr, 1, &colorValue, TRUE);
415           cy++ );
416     *h_ptr += cy - (*y_ptr + *h_ptr);
417 
418     /* ... to the left. */
419     for ( cx = *x_ptr - 1;
420           cx >= x && CheckSolidTile(cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE);
421           cx-- );
422     *w_ptr += *x_ptr - (cx + 1);
423     *x_ptr = cx + 1;
424 
425     /* ... to the right. */
426     for ( cx = *x_ptr + *w_ptr;
427           cx < x + w &&
428               CheckSolidTile(cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE);
429           cx++ );
430     *w_ptr += cx - (*x_ptr + *w_ptr);
431 }
432 
433 /*
434  * Check if a rectangle is all of the same color. If needSameColor is
435  * set to non-zero, then also check that its color equals to the
436  * *colorPtr value. The result is 1 if the test is successfull, and in
437  * that case new color will be stored in *colorPtr.
438  */
439 
440 static Bool
CheckSolidTile(x,y,w,h,colorPtr,needSameColor)441 CheckSolidTile(x, y, w, h, colorPtr, needSameColor)
442     int x, y, w, h;
443     CARD32 *colorPtr;
444     Bool needSameColor;
445 {
446     switch(rfbServerFormat.bitsPerPixel) {
447     case 32:
448         return CheckSolidTile32(x, y, w, h, colorPtr, needSameColor);
449     case 16:
450         return CheckSolidTile16(x, y, w, h, colorPtr, needSameColor);
451     default:
452         return CheckSolidTile8(x, y, w, h, colorPtr, needSameColor);
453     }
454 }
455 
456 #define DEFINE_CHECK_SOLID_FUNCTION(bpp)                                      \
457                                                                               \
458 static Bool                                                                   \
459 CheckSolidTile##bpp(x, y, w, h, colorPtr, needSameColor)                      \
460     int x, y, w, h;                                                           \
461     CARD32 *colorPtr;                                                         \
462     Bool needSameColor;                                                       \
463 {                                                                             \
464     CARD##bpp *fbptr;                                                         \
465     CARD##bpp colorValue;                                                     \
466     int dx, dy;                                                               \
467                                                                               \
468     fbptr = (CARD##bpp *)                                                     \
469         &rfbScreen.pfbMemory[y * rfbScreen.paddedWidthInBytes + x * (bpp/8)]; \
470                                                                               \
471     colorValue = *fbptr;                                                      \
472     if (needSameColor && (CARD32)colorValue != *colorPtr)                     \
473         return FALSE;                                                         \
474                                                                               \
475     for (dy = 0; dy < h; dy++) {                                              \
476         for (dx = 0; dx < w; dx++) {                                          \
477             if (colorValue != fbptr[dx])                                      \
478                 return FALSE;                                                 \
479         }                                                                     \
480         fbptr = (CARD##bpp *)((CARD8 *)fbptr + rfbScreen.paddedWidthInBytes); \
481     }                                                                         \
482                                                                               \
483     *colorPtr = (CARD32)colorValue;                                           \
484     return TRUE;                                                              \
485 }
486 
487 DEFINE_CHECK_SOLID_FUNCTION(8)
488 DEFINE_CHECK_SOLID_FUNCTION(16)
489 DEFINE_CHECK_SOLID_FUNCTION(32)
490 
491 static Bool
492 SendRectSimple(cl, x, y, w, h)
493     rfbClientPtr cl;
494     int x, y, w, h;
495 {
496     int maxBeforeSize, maxAfterSize;
497     int maxRectSize, maxRectWidth;
498     int subrectMaxWidth, subrectMaxHeight;
499     int dx, dy;
500     int rw, rh;
501 
502     maxRectSize = tightConf[compressLevel].maxRectSize;
503     maxRectWidth = tightConf[compressLevel].maxRectWidth;
504 
505     maxBeforeSize = maxRectSize * (cl->format.bitsPerPixel / 8);
506     maxAfterSize = maxBeforeSize + (maxBeforeSize + 99) / 100 + 12;
507 
508     if (tightBeforeBufSize < maxBeforeSize) {
509         tightBeforeBufSize = maxBeforeSize;
510         if (tightBeforeBuf == NULL)
511             tightBeforeBuf = (char *)xalloc(tightBeforeBufSize);
512         else
513             tightBeforeBuf = (char *)xrealloc(tightBeforeBuf,
514                                               tightBeforeBufSize);
515     }
516 
517     if (tightAfterBufSize < maxAfterSize) {
518         tightAfterBufSize = maxAfterSize;
519         if (tightAfterBuf == NULL)
520             tightAfterBuf = (char *)xalloc(tightAfterBufSize);
521         else
522             tightAfterBuf = (char *)xrealloc(tightAfterBuf,
523                                              tightAfterBufSize);
524     }
525 
526     if (w > maxRectWidth || w * h > maxRectSize) {
527         subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w;
528         subrectMaxHeight = maxRectSize / subrectMaxWidth;
529 
530         for (dy = 0; dy < h; dy += subrectMaxHeight) {
531             for (dx = 0; dx < w; dx += maxRectWidth) {
532                 rw = (dx + maxRectWidth < w) ? maxRectWidth : w - dx;
533                 rh = (dy + subrectMaxHeight < h) ? subrectMaxHeight : h - dy;
534                 if (!SendSubrect(cl, x+dx, y+dy, rw, rh))
535                     return FALSE;
536             }
537         }
538     } else {
539         if (!SendSubrect(cl, x, y, w, h))
540             return FALSE;
541     }
542 
543     return TRUE;
544 }
545 
546 static Bool
SendSubrect(cl,x,y,w,h)547 SendSubrect(cl, x, y, w, h)
548     rfbClientPtr cl;
549     int x, y, w, h;
550 {
551     char *fbptr;
552     Bool success = FALSE;
553 
554     /* Send pending data if there is more than 128 bytes. */
555     if (ublen > 128) {
556         if (!rfbSendUpdateBuf(cl))
557             return FALSE;
558     }
559 
560     if (!SendTightHeader(cl, x, y, w, h))
561         return FALSE;
562 
563     fbptr = (rfbScreen.pfbMemory + (rfbScreen.paddedWidthInBytes * y)
564              + (x * (rfbScreen.bitsPerPixel / 8)));
565 
566     if (subsampLevel == TJ_GRAYSCALE && qualityLevel != -1)
567         return SendJpegRect(cl, x, y, w, h, qualityLevel);
568 
569     paletteMaxColors = w * h / tightConf[compressLevel].idxMaxColorsDivisor;
570     if(qualityLevel != -1)
571         paletteMaxColors = 24;
572     if ( paletteMaxColors < 2 &&
573          w * h >= tightConf[compressLevel].monoMinRectSize ) {
574         paletteMaxColors = 2;
575     }
576 
577     if (cl->format.bitsPerPixel == rfbServerFormat.bitsPerPixel &&
578         cl->format.redMax == rfbServerFormat.redMax &&
579         cl->format.greenMax == rfbServerFormat.greenMax &&
580         cl->format.blueMax == rfbServerFormat.blueMax &&
581         cl->format.bitsPerPixel >= 16) {
582 
583         /* This is so we can avoid translating the pixels when compressing
584            with JPEG, since it is unnecessary */
585         switch (cl->format.bitsPerPixel) {
586         case 16:
587             FastFillPalette16(cl, (CARD16 *)fbptr, w,
588                               rfbScreen.paddedWidthInBytes/2, h);
589             break;
590         default:
591             FastFillPalette32(cl, (CARD32 *)fbptr, w,
592                               rfbScreen.paddedWidthInBytes/4, h);
593         }
594 
595         if(paletteNumColors != 0 || qualityLevel == -1) {
596             (*cl->translateFn)(cl->translateLookupTable, &rfbServerFormat,
597                                &cl->format, fbptr, tightBeforeBuf,
598                                rfbScreen.paddedWidthInBytes, w, h);
599         }
600     }
601     else {
602         (*cl->translateFn)(cl->translateLookupTable, &rfbServerFormat,
603                            &cl->format, fbptr, tightBeforeBuf,
604                            rfbScreen.paddedWidthInBytes, w, h);
605 
606         switch (cl->format.bitsPerPixel) {
607         case 8:
608             FillPalette8(w * h);
609             break;
610         case 16:
611             FillPalette16(w * h);
612             break;
613         default:
614             FillPalette32(w * h);
615         }
616     }
617 
618     switch (paletteNumColors) {
619     case 0:
620         /* Truecolor image */
621         if (qualityLevel != -1) {
622             success = SendJpegRect(cl, x, y, w, h, qualityLevel);
623         } else {
624             success = SendFullColorRect(cl, w, h);
625         }
626         break;
627     case 1:
628         /* Solid rectangle */
629         success = SendSolidRect(cl);
630         break;
631     case 2:
632         /* Two-color rectangle */
633         success = SendMonoRect(cl, w, h);
634         break;
635     default:
636         /* Up to 256 different colors */
637         success = SendIndexedRect(cl, w, h);
638     }
639     return success;
640 }
641 
642 static Bool
SendTightHeader(cl,x,y,w,h)643 SendTightHeader(cl, x, y, w, h)
644     rfbClientPtr cl;
645     int x, y, w, h;
646 {
647     rfbFramebufferUpdateRectHeader rect;
648 
649     if (ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
650         if (!rfbSendUpdateBuf(cl))
651             return FALSE;
652     }
653 
654     rect.r.x = Swap16IfLE(x);
655     rect.r.y = Swap16IfLE(y);
656     rect.r.w = Swap16IfLE(w);
657     rect.r.h = Swap16IfLE(h);
658     rect.encoding = Swap32IfLE(rfbEncodingTight);
659 
660     memcpy(&updateBuf[ublen], (char *)&rect,
661            sz_rfbFramebufferUpdateRectHeader);
662     ublen += sz_rfbFramebufferUpdateRectHeader;
663 
664     cl->rfbRectanglesSent[rfbEncodingTight]++;
665     cl->rfbBytesSent[rfbEncodingTight] += sz_rfbFramebufferUpdateRectHeader;
666 
667     return TRUE;
668 }
669 
670 /*
671  * Subencoding implementations.
672  */
673 
674 static Bool
SendSolidRect(cl)675 SendSolidRect(cl)
676     rfbClientPtr cl;
677 {
678     int len;
679 
680     if (usePixelFormat24) {
681         Pack24(tightBeforeBuf, &cl->format, 1);
682         len = 3;
683     } else
684         len = cl->format.bitsPerPixel / 8;
685 
686     if (ublen + 1 + len > UPDATE_BUF_SIZE) {
687         if (!rfbSendUpdateBuf(cl))
688             return FALSE;
689     }
690 
691     updateBuf[ublen++] = (char)(rfbTightFill << 4);
692     memcpy (&updateBuf[ublen], tightBeforeBuf, len);
693     ublen += len;
694 
695     cl->rfbBytesSent[rfbEncodingTight] += len + 1;
696 
697     return TRUE;
698 }
699 
700 static Bool
SendMonoRect(cl,w,h)701 SendMonoRect(cl, w, h)
702     rfbClientPtr cl;
703     int w, h;
704 {
705     int streamId = 1;
706     int paletteLen, dataLen;
707 
708     if ( (ublen + TIGHT_MIN_TO_COMPRESS + 6 +
709           2 * cl->format.bitsPerPixel / 8) > UPDATE_BUF_SIZE ) {
710         if (!rfbSendUpdateBuf(cl))
711             return FALSE;
712     }
713 
714     /* Prepare tight encoding header. */
715     dataLen = (w + 7) / 8;
716     dataLen *= h;
717 
718     if (tightConf[compressLevel].monoZlibLevel == 0)
719         updateBuf[ublen++] = (char)((rfbTightNoZlib | rfbTightExplicitFilter) << 4);
720     else
721         updateBuf[ublen++] = (streamId | rfbTightExplicitFilter) << 4;
722     updateBuf[ublen++] = rfbTightFilterPalette;
723     updateBuf[ublen++] = 1;
724 
725     /* Prepare palette, convert image. */
726     switch (cl->format.bitsPerPixel) {
727 
728     case 32:
729         EncodeMonoRect32((CARD8 *)tightBeforeBuf, w, h);
730 
731         ((CARD32 *)tightAfterBuf)[0] = monoBackground;
732         ((CARD32 *)tightAfterBuf)[1] = monoForeground;
733         if (usePixelFormat24) {
734             Pack24(tightAfterBuf, &cl->format, 2);
735             paletteLen = 6;
736         } else
737             paletteLen = 8;
738 
739         memcpy(&updateBuf[ublen], tightAfterBuf, paletteLen);
740         ublen += paletteLen;
741         cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteLen;
742         break;
743 
744     case 16:
745         EncodeMonoRect16((CARD8 *)tightBeforeBuf, w, h);
746 
747         ((CARD16 *)tightAfterBuf)[0] = (CARD16)monoBackground;
748         ((CARD16 *)tightAfterBuf)[1] = (CARD16)monoForeground;
749 
750         memcpy(&updateBuf[ublen], tightAfterBuf, 4);
751         ublen += 4;
752         cl->rfbBytesSent[rfbEncodingTight] += 7;
753         break;
754 
755     default:
756         EncodeMonoRect8((CARD8 *)tightBeforeBuf, w, h);
757 
758         updateBuf[ublen++] = (char)monoBackground;
759         updateBuf[ublen++] = (char)monoForeground;
760         cl->rfbBytesSent[rfbEncodingTight] += 5;
761     }
762 
763     return CompressData(cl, streamId, dataLen,
764                         tightConf[compressLevel].monoZlibLevel,
765                         Z_DEFAULT_STRATEGY);
766 }
767 
768 static Bool
SendIndexedRect(cl,w,h)769 SendIndexedRect(cl, w, h)
770     rfbClientPtr cl;
771     int w, h;
772 {
773     int streamId = 2;
774     int i, entryLen;
775 
776     if ( (ublen + TIGHT_MIN_TO_COMPRESS + 6 +
777           paletteNumColors * cl->format.bitsPerPixel / 8) > UPDATE_BUF_SIZE ) {
778         if (!rfbSendUpdateBuf(cl))
779             return FALSE;
780     }
781 
782     /* Prepare tight encoding header. */
783     if (tightConf[compressLevel].idxZlibLevel == 0)
784         updateBuf[ublen++] = (char)((rfbTightNoZlib | rfbTightExplicitFilter) << 4);
785     else
786         updateBuf[ublen++] = (streamId | rfbTightExplicitFilter) << 4;
787     updateBuf[ublen++] = rfbTightFilterPalette;
788     updateBuf[ublen++] = (char)(paletteNumColors - 1);
789 
790     /* Prepare palette, convert image. */
791     switch (cl->format.bitsPerPixel) {
792 
793     case 32:
794         EncodeIndexedRect32((CARD8 *)tightBeforeBuf, w * h);
795 
796         for (i = 0; i < paletteNumColors; i++) {
797             ((CARD32 *)tightAfterBuf)[i] =
798                 palette.entry[i].listNode->rgb;
799         }
800         if (usePixelFormat24) {
801             Pack24(tightAfterBuf, &cl->format, paletteNumColors);
802             entryLen = 3;
803         } else
804             entryLen = 4;
805 
806         memcpy(&updateBuf[ublen], tightAfterBuf, paletteNumColors * entryLen);
807         ublen += paletteNumColors * entryLen;
808         cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteNumColors * entryLen;
809         break;
810 
811     case 16:
812         EncodeIndexedRect16((CARD8 *)tightBeforeBuf, w * h);
813 
814         for (i = 0; i < paletteNumColors; i++) {
815             ((CARD16 *)tightAfterBuf)[i] =
816                 (CARD16)palette.entry[i].listNode->rgb;
817         }
818 
819         memcpy(&updateBuf[ublen], tightAfterBuf, paletteNumColors * 2);
820         ublen += paletteNumColors * 2;
821         cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteNumColors * 2;
822         break;
823 
824     default:
825         return FALSE;           /* Should never happen. */
826     }
827 
828     return CompressData(cl, streamId, w * h,
829                         tightConf[compressLevel].idxZlibLevel,
830                         Z_DEFAULT_STRATEGY);
831 }
832 
833 static Bool
SendFullColorRect(cl,w,h)834 SendFullColorRect(cl, w, h)
835     rfbClientPtr cl;
836     int w, h;
837 {
838     int streamId = 0;
839     int len;
840 
841     if (ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) {
842         if (!rfbSendUpdateBuf(cl))
843             return FALSE;
844     }
845 
846     if (tightConf[compressLevel].rawZlibLevel == 0)
847         updateBuf[ublen++] = (char)(rfbTightNoZlib << 4);
848     else
849         updateBuf[ublen++] = 0x00;  /* stream id = 0, no flushing, no filter */
850     cl->rfbBytesSent[rfbEncodingTight]++;
851 
852     if (usePixelFormat24) {
853         Pack24(tightBeforeBuf, &cl->format, w * h);
854         len = 3;
855     } else
856         len = cl->format.bitsPerPixel / 8;
857 
858     return CompressData(cl, streamId, w * h * len,
859                         tightConf[compressLevel].rawZlibLevel,
860                         Z_DEFAULT_STRATEGY);
861 }
862 
863 static Bool
CompressData(cl,streamId,dataLen,zlibLevel,zlibStrategy)864 CompressData(cl, streamId, dataLen, zlibLevel, zlibStrategy)
865     rfbClientPtr cl;
866     int streamId, dataLen, zlibLevel, zlibStrategy;
867 {
868     z_streamp pz;
869     int err, i;
870 
871     if (dataLen < TIGHT_MIN_TO_COMPRESS) {
872         memcpy(&updateBuf[ublen], tightBeforeBuf, dataLen);
873         ublen += dataLen;
874         cl->rfbBytesSent[rfbEncodingTight] += dataLen;
875         return TRUE;
876     }
877 
878     if (zlibLevel == 0)
879         return SendCompressedData (cl, tightBeforeBuf, dataLen);
880 
881     pz = &cl->zsStruct[streamId];
882 
883     /* Initialize compression stream if needed. */
884     if (!cl->zsActive[streamId]) {
885         pz->zalloc = Z_NULL;
886         pz->zfree = Z_NULL;
887         pz->opaque = Z_NULL;
888 
889         err = deflateInit2 (pz, zlibLevel, Z_DEFLATED, MAX_WBITS,
890                             MAX_MEM_LEVEL, zlibStrategy);
891         if (err != Z_OK)
892             return FALSE;
893 
894         cl->zsActive[streamId] = TRUE;
895         cl->zsLevel[streamId] = zlibLevel;
896     }
897 
898     /* Prepare buffer pointers. */
899     pz->next_in = (Bytef *)tightBeforeBuf;
900     pz->avail_in = dataLen;
901     pz->next_out = (Bytef *)tightAfterBuf;
902     pz->avail_out = tightAfterBufSize;
903 
904     /* Change compression parameters if needed. */
905     if (zlibLevel != cl->zsLevel[streamId]) {
906         if (deflateParams (pz, zlibLevel, zlibStrategy) != Z_OK) {
907             return FALSE;
908         }
909         cl->zsLevel[streamId] = zlibLevel;
910     }
911 
912     /* Actual compression. */
913     if ( deflate (pz, Z_SYNC_FLUSH) != Z_OK ||
914          pz->avail_in != 0 || pz->avail_out == 0 ) {
915         return FALSE;
916     }
917 
918     return SendCompressedData(cl, tightAfterBuf,
919         tightAfterBufSize - pz->avail_out);
920 }
921 
SendCompressedData(cl,buf,compressedLen)922 static Bool SendCompressedData(cl, buf, compressedLen)
923     rfbClientPtr cl;
924     char *buf;
925     int compressedLen;
926 {
927     int i, portionLen;
928 
929     updateBuf[ublen++] = compressedLen & 0x7F;
930     cl->rfbBytesSent[rfbEncodingTight]++;
931     if (compressedLen > 0x7F) {
932         updateBuf[ublen-1] |= 0x80;
933         updateBuf[ublen++] = compressedLen >> 7 & 0x7F;
934         cl->rfbBytesSent[rfbEncodingTight]++;
935         if (compressedLen > 0x3FFF) {
936             updateBuf[ublen-1] |= 0x80;
937             updateBuf[ublen++] = compressedLen >> 14 & 0xFF;
938             cl->rfbBytesSent[rfbEncodingTight]++;
939         }
940     }
941 
942     portionLen = UPDATE_BUF_SIZE;
943     for (i = 0; i < compressedLen; i += portionLen) {
944         if (i + portionLen > compressedLen) {
945             portionLen = compressedLen - i;
946         }
947         if (ublen + portionLen > UPDATE_BUF_SIZE) {
948             if (!rfbSendUpdateBuf(cl))
949                 return FALSE;
950         }
951         memcpy(&updateBuf[ublen], &buf[i], portionLen);
952         ublen += portionLen;
953     }
954     cl->rfbBytesSent[rfbEncodingTight] += compressedLen;
955     return TRUE;
956 }
957 
958 /*
959  * Code to determine how many different colors used in rectangle.
960  */
961 
962 static void
FillPalette8(count)963 FillPalette8(count)
964     int count;
965 {
966     CARD8 *data = (CARD8 *)tightBeforeBuf;
967     CARD8 c0, c1;
968     int i, n0, n1;
969 
970     paletteNumColors = 0;
971 
972     c0 = data[0];
973     for (i = 1; i < count && data[i] == c0; i++);
974     if (i == count) {
975         paletteNumColors = 1;
976         return;                 /* Solid rectangle */
977     }
978 
979     if (paletteMaxColors < 2)
980         return;
981 
982     n0 = i;
983     c1 = data[i];
984     n1 = 0;
985     for (i++; i < count; i++) {
986         if (data[i] == c0) {
987             n0++;
988         } else if (data[i] == c1) {
989             n1++;
990         } else
991             break;
992     }
993     if (i == count) {
994         if (n0 > n1) {
995             monoBackground = (CARD32)c0;
996             monoForeground = (CARD32)c1;
997         } else {
998             monoBackground = (CARD32)c1;
999             monoForeground = (CARD32)c0;
1000         }
1001         paletteNumColors = 2;   /* Two colors */
1002     }
1003 }
1004 
1005 #define DEFINE_FILL_PALETTE_FUNCTION(bpp)                               \
1006                                                                         \
1007 static void                                                             \
1008 FillPalette##bpp(count)                                                 \
1009     int count;                                                          \
1010 {                                                                       \
1011     CARD##bpp *data = (CARD##bpp *)tightBeforeBuf;                      \
1012     CARD##bpp c0, c1, ci;                                               \
1013     int i, n0, n1, ni;                                                  \
1014                                                                         \
1015     c0 = data[0];                                                       \
1016     for (i = 1; i < count && data[i] == c0; i++);                       \
1017     if (i >= count) {                                                   \
1018         paletteNumColors = 1;   /* Solid rectangle */                   \
1019         return;                                                         \
1020     }                                                                   \
1021                                                                         \
1022     if (paletteMaxColors < 2) {                                         \
1023         paletteNumColors = 0;   /* Full-color encoding preferred */     \
1024         return;                                                         \
1025     }                                                                   \
1026                                                                         \
1027     n0 = i;                                                             \
1028     c1 = data[i];                                                       \
1029     n1 = 0;                                                             \
1030     for (i++; i < count; i++) {                                         \
1031         ci = data[i];                                                   \
1032         if (ci == c0) {                                                 \
1033             n0++;                                                       \
1034         } else if (ci == c1) {                                          \
1035             n1++;                                                       \
1036         } else                                                          \
1037             break;                                                      \
1038     }                                                                   \
1039     if (i >= count) {                                                   \
1040         if (n0 > n1) {                                                  \
1041             monoBackground = (CARD32)c0;                                \
1042             monoForeground = (CARD32)c1;                                \
1043         } else {                                                        \
1044             monoBackground = (CARD32)c1;                                \
1045             monoForeground = (CARD32)c0;                                \
1046         }                                                               \
1047         paletteNumColors = 2;   /* Two colors */                        \
1048         return;                                                         \
1049     }                                                                   \
1050                                                                         \
1051     PaletteReset();                                                     \
1052     PaletteInsert (c0, (CARD32)n0, bpp);                                \
1053     PaletteInsert (c1, (CARD32)n1, bpp);                                \
1054                                                                         \
1055     ni = 1;                                                             \
1056     for (i++; i < count; i++) {                                         \
1057         if (data[i] == ci) {                                            \
1058             ni++;                                                       \
1059         } else {                                                        \
1060             if (!PaletteInsert (ci, (CARD32)ni, bpp))                   \
1061                 return;                                                 \
1062             ci = data[i];                                               \
1063             ni = 1;                                                     \
1064         }                                                               \
1065     }                                                                   \
1066     PaletteInsert (ci, (CARD32)ni, bpp);                                \
1067 }
1068 
1069 DEFINE_FILL_PALETTE_FUNCTION(16)
1070 DEFINE_FILL_PALETTE_FUNCTION(32)
1071 
1072 #define DEFINE_FAST_FILL_PALETTE_FUNCTION(bpp)                          \
1073                                                                         \
1074 static void                                                             \
1075 FastFillPalette##bpp(cl, data, w, pitch, h)                             \
1076     rfbClientPtr cl;                                                    \
1077     CARD##bpp *data;                                                    \
1078     int w, pitch, h;                                                    \
1079 {                                                                       \
1080     CARD##bpp c0, c1, ci, mask, c0t, c1t, cit;                          \
1081     int i, j, i2, j2, n0, n1, ni;                                       \
1082                                                                         \
1083     if (cl->translateFn != rfbTranslateNone) {                          \
1084         mask = rfbServerFormat.redMax << rfbServerFormat.redShift;      \
1085         mask |= rfbServerFormat.greenMax << rfbServerFormat.greenShift; \
1086         mask |= rfbServerFormat.blueMax << rfbServerFormat.blueShift;   \
1087     } else mask = ~0;                                                   \
1088                                                                         \
1089     c0 = data[0] & mask;                                                \
1090     for (j = 0; j < h; j++) {                                           \
1091         for (i = 0; i < w; i++) {                                       \
1092             if ((data[j * pitch + i] & mask) != c0)                     \
1093                 goto done;                                              \
1094         }                                                               \
1095     }                                                                   \
1096     done:                                                               \
1097     if (j >= h) {                                                       \
1098         paletteNumColors = 1;   /* Solid rectangle */                   \
1099         return;                                                         \
1100     }                                                                   \
1101     if (paletteMaxColors < 2) {                                         \
1102         paletteNumColors = 0;   /* Full-color encoding preferred */     \
1103         return;                                                         \
1104     }                                                                   \
1105                                                                         \
1106     n0 = j * w + i;                                                     \
1107     c1 = data[j * pitch + i] & mask;                                    \
1108     n1 = 0;                                                             \
1109     i++;  if (i >= w) {i = 0;  j++;}                                    \
1110     for (j2 = j; j2 < h; j2++) {                                        \
1111         for (i2 = i; i2 < w; i2++) {                                    \
1112             ci = data[j2 * pitch + i2] & mask;                          \
1113             if (ci == c0) {                                             \
1114                 n0++;                                                   \
1115             } else if (ci == c1) {                                      \
1116                 n1++;                                                   \
1117             } else                                                      \
1118                 goto done2;                                             \
1119         }                                                               \
1120         i = 0;                                                          \
1121     }                                                                   \
1122     done2:                                                              \
1123     (*cl->translateFn)(cl->translateLookupTable, &rfbServerFormat,      \
1124                        &cl->format, (char *)&c0, (char *)&c0t, bpp/8,   \
1125                        1, 1);                                           \
1126     (*cl->translateFn)(cl->translateLookupTable, &rfbServerFormat,      \
1127                        &cl->format, (char *)&c1, (char *)&c1t, bpp/8,   \
1128                        1, 1);                                           \
1129     if (j2 >= h) {                                                      \
1130         if (n0 > n1) {                                                  \
1131             monoBackground = (CARD32)c0t;                               \
1132             monoForeground = (CARD32)c1t;                               \
1133         } else {                                                        \
1134             monoBackground = (CARD32)c1t;                               \
1135             monoForeground = (CARD32)c0t;                               \
1136         }                                                               \
1137         paletteNumColors = 2;   /* Two colors */                        \
1138         return;                                                         \
1139     }                                                                   \
1140                                                                         \
1141     PaletteReset();                                                     \
1142     PaletteInsert (c0t, (CARD32)n0, bpp);                               \
1143     PaletteInsert (c1t, (CARD32)n1, bpp);                               \
1144                                                                         \
1145     ni = 1;                                                             \
1146     i2++;  if (i2 >= w) {i2 = 0;  j2++;}                                \
1147     for (j = j2; j < h; j++) {                                          \
1148         for (i = i2; i < w; i++) {                                      \
1149             if ((data[j * pitch + i] & mask) == ci) {                   \
1150                 ni++;                                                   \
1151             } else {                                                    \
1152                 (*cl->translateFn)(cl->translateLookupTable,            \
1153                                    &rfbServerFormat, &cl->format,       \
1154                                    (char *)&ci, (char *)&cit, bpp/8,    \
1155                                    1, 1);                               \
1156                 if (!PaletteInsert (cit, (CARD32)ni, bpp))              \
1157                     return;                                             \
1158                 ci = data[j * pitch + i] & mask;                        \
1159                 ni = 1;                                                 \
1160             }                                                           \
1161         }                                                               \
1162         i2 = 0;                                                         \
1163     }                                                                   \
1164                                                                         \
1165     (*cl->translateFn)(cl->translateLookupTable, &rfbServerFormat,      \
1166                        &cl->format, (char *)&ci, (char *)&cit, bpp/8,   \
1167                        1, 1);                                           \
1168     PaletteInsert (cit, (CARD32)ni, bpp);                               \
1169 }
1170 
1171 DEFINE_FAST_FILL_PALETTE_FUNCTION(16)
1172 DEFINE_FAST_FILL_PALETTE_FUNCTION(32)
1173 
1174 
1175 /*
1176  * Functions to operate with palette structures.
1177  */
1178 
1179 #define HASH_FUNC16(rgb) ((int)((((rgb) >> 8) + (rgb)) & 0xFF))
1180 #define HASH_FUNC32(rgb) ((int)((((rgb) >> 16) + ((rgb) >> 8)) & 0xFF))
1181 
1182 static void
PaletteReset(void)1183 PaletteReset(void)
1184 {
1185     paletteNumColors = 0;
1186     memset(palette.hash, 0, 256 * sizeof(COLOR_LIST *));
1187 }
1188 
1189 static int
PaletteInsert(rgb,numPixels,bpp)1190 PaletteInsert(rgb, numPixels, bpp)
1191     CARD32 rgb;
1192     int numPixels;
1193     int bpp;
1194 {
1195     COLOR_LIST *pnode;
1196     COLOR_LIST *prev_pnode = NULL;
1197     int hash_key, idx, new_idx, count;
1198 
1199     hash_key = (bpp == 16) ? HASH_FUNC16(rgb) : HASH_FUNC32(rgb);
1200 
1201     pnode = palette.hash[hash_key];
1202 
1203     while (pnode != NULL) {
1204         if (pnode->rgb == rgb) {
1205             /* Such palette entry already exists. */
1206             new_idx = idx = pnode->idx;
1207             count = palette.entry[idx].numPixels + numPixels;
1208             if (new_idx && palette.entry[new_idx-1].numPixels < count) {
1209                 do {
1210                     palette.entry[new_idx] = palette.entry[new_idx-1];
1211                     palette.entry[new_idx].listNode->idx = new_idx;
1212                     new_idx--;
1213                 }
1214                 while (new_idx && palette.entry[new_idx-1].numPixels < count);
1215                 palette.entry[new_idx].listNode = pnode;
1216                 pnode->idx = new_idx;
1217             }
1218             palette.entry[new_idx].numPixels = count;
1219             return paletteNumColors;
1220         }
1221         prev_pnode = pnode;
1222         pnode = pnode->next;
1223     }
1224 
1225     /* Check if palette is full. */
1226     if (paletteNumColors == 256 || paletteNumColors == paletteMaxColors) {
1227         paletteNumColors = 0;
1228         return 0;
1229     }
1230 
1231     /* Move palette entries with lesser pixel counts. */
1232     for ( idx = paletteNumColors;
1233           idx > 0 && palette.entry[idx-1].numPixels < numPixels;
1234           idx-- ) {
1235         palette.entry[idx] = palette.entry[idx-1];
1236         palette.entry[idx].listNode->idx = idx;
1237     }
1238 
1239     /* Add new palette entry into the freed slot. */
1240     pnode = &palette.list[paletteNumColors];
1241     if (prev_pnode != NULL) {
1242         prev_pnode->next = pnode;
1243     } else {
1244         palette.hash[hash_key] = pnode;
1245     }
1246     pnode->next = NULL;
1247     pnode->idx = idx;
1248     pnode->rgb = rgb;
1249     palette.entry[idx].listNode = pnode;
1250     palette.entry[idx].numPixels = numPixels;
1251 
1252     return (++paletteNumColors);
1253 }
1254 
1255 
1256 /*
1257  * Converting 32-bit color samples into 24-bit colors.
1258  * Should be called only when redMax, greenMax and blueMax are 255.
1259  * Color components assumed to be byte-aligned.
1260  */
1261 
Pack24(buf,fmt,count)1262 static void Pack24(buf, fmt, count)
1263     char *buf;
1264     rfbPixelFormat *fmt;
1265     int count;
1266 {
1267     CARD32 *buf32;
1268     CARD32 pix;
1269     int r_shift, g_shift, b_shift;
1270 
1271     buf32 = (CARD32 *)buf;
1272 
1273     if (!rfbServerFormat.bigEndian == !fmt->bigEndian) {
1274         r_shift = fmt->redShift;
1275         g_shift = fmt->greenShift;
1276         b_shift = fmt->blueShift;
1277     } else {
1278         r_shift = 24 - fmt->redShift;
1279         g_shift = 24 - fmt->greenShift;
1280         b_shift = 24 - fmt->blueShift;
1281     }
1282 
1283     while (count--) {
1284         pix = *buf32++;
1285         *buf++ = (char)(pix >> r_shift);
1286         *buf++ = (char)(pix >> g_shift);
1287         *buf++ = (char)(pix >> b_shift);
1288     }
1289 }
1290 
1291 
1292 /*
1293  * Converting truecolor samples into palette indices.
1294  */
1295 
1296 #define DEFINE_IDX_ENCODE_FUNCTION(bpp)                                 \
1297                                                                         \
1298 static void                                                             \
1299 EncodeIndexedRect##bpp(buf, count)                                      \
1300     CARD8 *buf;                                                         \
1301     int count;                                                          \
1302 {                                                                       \
1303     COLOR_LIST *pnode;                                                  \
1304     CARD##bpp *src;                                                     \
1305     CARD##bpp rgb;                                                      \
1306     int rep = 0;                                                        \
1307                                                                         \
1308     src = (CARD##bpp *) buf;                                            \
1309                                                                         \
1310     while (count--) {                                                   \
1311         rgb = *src++;                                                   \
1312         while (count && *src == rgb) {                                  \
1313             rep++, src++, count--;                                      \
1314         }                                                               \
1315         pnode = palette.hash[HASH_FUNC##bpp(rgb)];                      \
1316         while (pnode != NULL) {                                         \
1317             if ((CARD##bpp)pnode->rgb == rgb) {                         \
1318                 *buf++ = (CARD8)pnode->idx;                             \
1319                 while (rep) {                                           \
1320                     *buf++ = (CARD8)pnode->idx;                         \
1321                     rep--;                                              \
1322                 }                                                       \
1323                 break;                                                  \
1324             }                                                           \
1325             pnode = pnode->next;                                        \
1326         }                                                               \
1327     }                                                                   \
1328 }
1329 
1330 DEFINE_IDX_ENCODE_FUNCTION(16)
1331 DEFINE_IDX_ENCODE_FUNCTION(32)
1332 
1333 #define DEFINE_MONO_ENCODE_FUNCTION(bpp)                                \
1334                                                                         \
1335 static void                                                             \
1336 EncodeMonoRect##bpp(buf, w, h)                                          \
1337     CARD8 *buf;                                                         \
1338     int w, h;                                                           \
1339 {                                                                       \
1340     CARD##bpp *ptr;                                                     \
1341     CARD##bpp bg;                                                       \
1342     unsigned int value, mask;                                           \
1343     int aligned_width;                                                  \
1344     int x, y, bg_bits;                                                  \
1345                                                                         \
1346     ptr = (CARD##bpp *) buf;                                            \
1347     bg = (CARD##bpp) monoBackground;                                    \
1348     aligned_width = w - w % 8;                                          \
1349                                                                         \
1350     for (y = 0; y < h; y++) {                                           \
1351         for (x = 0; x < aligned_width; x += 8) {                        \
1352             for (bg_bits = 0; bg_bits < 8; bg_bits++) {                 \
1353                 if (*ptr++ != bg)                                       \
1354                     break;                                              \
1355             }                                                           \
1356             if (bg_bits == 8) {                                         \
1357                 *buf++ = 0;                                             \
1358                 continue;                                               \
1359             }                                                           \
1360             mask = 0x80 >> bg_bits;                                     \
1361             value = mask;                                               \
1362             for (bg_bits++; bg_bits < 8; bg_bits++) {                   \
1363                 mask >>= 1;                                             \
1364                 if (*ptr++ != bg) {                                     \
1365                     value |= mask;                                      \
1366                 }                                                       \
1367             }                                                           \
1368             *buf++ = (CARD8)value;                                      \
1369         }                                                               \
1370                                                                         \
1371         mask = 0x80;                                                    \
1372         value = 0;                                                      \
1373         if (x >= w)                                                     \
1374             continue;                                                   \
1375                                                                         \
1376         for (; x < w; x++) {                                            \
1377             if (*ptr++ != bg) {                                         \
1378                 value |= mask;                                          \
1379             }                                                           \
1380             mask >>= 1;                                                 \
1381         }                                                               \
1382         *buf++ = (CARD8)value;                                          \
1383     }                                                                   \
1384 }
1385 
1386 DEFINE_MONO_ENCODE_FUNCTION(8)
1387 DEFINE_MONO_ENCODE_FUNCTION(16)
1388 DEFINE_MONO_ENCODE_FUNCTION(32)
1389 
1390 /*
1391  * JPEG compression stuff.
1392  */
1393 
1394 static unsigned long jpegDstDataLen;
1395 static tjhandle j=NULL;
1396 
1397 static Bool
SendJpegRect(cl,x,y,w,h,quality)1398 SendJpegRect(cl, x, y, w, h, quality)
1399     rfbClientPtr cl;
1400     int x, y, w, h;
1401     int quality;
1402 {
1403     int dy;
1404     unsigned char *srcbuf;
1405     int ps=rfbServerFormat.bitsPerPixel/8;
1406     int subsamp=subsampLevel2tjsubsamp[subsampLevel];
1407     unsigned long size=0;
1408     int flags=0, pitch;
1409     unsigned char *tmpbuf=NULL;
1410 
1411     if (rfbServerFormat.bitsPerPixel == 8)
1412         return SendFullColorRect(cl, w, h);
1413 
1414 
1415     if(ps<2) {
1416       rfbLog("Error: JPEG requires 16-bit, 24-bit, or 32-bit pixel format.\n");
1417       return 0;
1418     }
1419     if(!j) {
1420       if((j=tjInitCompress())==NULL) {
1421         rfbLog("JPEG Error: %s\n", tjGetErrorStr());  return 0;
1422       }
1423     }
1424 
1425     if (tightAfterBufSize < TJBUFSIZE(w,h)) {
1426         if (tightAfterBuf == NULL)
1427             tightAfterBuf = (char *)xalloc(TJBUFSIZE(w,h));
1428         else
1429             tightAfterBuf = (char *)xrealloc(tightAfterBuf,
1430                                              TJBUFSIZE(w,h));
1431         if(!tightAfterBuf) {
1432             rfbLog("Memory allocation failure!\n");
1433             return 0;
1434         }
1435         tightAfterBufSize = TJBUFSIZE(w,h);
1436     }
1437 
1438     if (ps == 2) {
1439         CARD16 *srcptr, pix;
1440         unsigned char *dst;
1441         int inRed, inGreen, inBlue, i, j;
1442 
1443         if((tmpbuf=(unsigned char *)malloc(w*h*3))==NULL)
1444             rfbLog("Memory allocation failure!\n");
1445         srcptr = (CARD16 *)
1446             &rfbScreen.pfbMemory[y * rfbScreen.paddedWidthInBytes +
1447                                  x * ps];
1448         dst = tmpbuf;
1449         for(j=0; j<h; j++) {
1450             CARD16 *srcptr2=srcptr;
1451             unsigned char *dst2=dst;
1452             for(i=0; i<w; i++) {
1453                 pix = *srcptr2++;
1454                 inRed = (int)
1455                     (pix >> rfbServerFormat.redShift   & rfbServerFormat.redMax);
1456                 inGreen = (int)
1457                     (pix >> rfbServerFormat.greenShift & rfbServerFormat.greenMax);
1458                 inBlue  = (int)
1459                     (pix >> rfbServerFormat.blueShift  & rfbServerFormat.blueMax);
1460                 *dst2++ = (CARD8)((inRed   * 255 + rfbServerFormat.redMax / 2) /
1461                           rfbServerFormat.redMax);
1462                	*dst2++ = (CARD8)((inGreen * 255 + rfbServerFormat.greenMax / 2) /
1463                           rfbServerFormat.greenMax);
1464                 *dst2++ = (CARD8)((inBlue  * 255 + rfbServerFormat.blueMax / 2) /
1465                           rfbServerFormat.blueMax);
1466             }
1467             srcptr+=rfbScreen.paddedWidthInBytes/ps;
1468             dst+=w*3;
1469         }
1470         srcbuf = tmpbuf;
1471         pitch = w*3;
1472         ps = 3;
1473     } else {
1474         if(rfbServerFormat.bigEndian && ps==4) flags|=TJ_ALPHAFIRST;
1475         if(rfbServerFormat.redShift==16 && rfbServerFormat.blueShift==0)
1476             flags|=TJ_BGR;
1477         if(rfbServerFormat.bigEndian) flags^=TJ_BGR;
1478         srcbuf=(unsigned char *)&rfbScreen.pfbMemory[y *
1479             rfbScreen.paddedWidthInBytes + x * ps];
1480         pitch=rfbScreen.paddedWidthInBytes;
1481     }
1482 
1483     if(tjCompress(j, srcbuf, w, pitch, h, ps, (unsigned char *)tightAfterBuf,
1484       &size, subsamp, quality, flags)==-1) {
1485       rfbLog("JPEG Error: %s\n", tjGetErrorStr());
1486       if(tmpbuf) {free(tmpbuf);  tmpbuf=NULL;}
1487       return 0;
1488     }
1489     jpegDstDataLen=(int)size;
1490 
1491     if(tmpbuf) {free(tmpbuf);  tmpbuf=NULL;}
1492 
1493     if (ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) {
1494         if (!rfbSendUpdateBuf(cl))
1495             return FALSE;
1496     }
1497 
1498     updateBuf[ublen++] = (char)(rfbTightJpeg << 4);
1499     cl->rfbBytesSent[rfbEncodingTight]++;
1500 
1501     return SendCompressedData(cl, tightAfterBuf, jpegDstDataLen);
1502 }
1503