~ubuntu-branches/debian/lenny/italc/lenny

« back to all changes in this revision

Viewing changes to ica/x11/libvncserver/zrleencodetemplate.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2008-06-17 13:46:54 UTC
  • mto: This revision was merged to the branch mainline in revision 5.
  • Revision ID: james.westby@ubuntu.com-20080617134654-2y5m7ki93r5c1ysf
Tags: upstream-1.0.9~rc3
ImportĀ upstreamĀ versionĀ 1.0.9~rc3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2002 RealVNC Ltd.  All Rights Reserved.
 
3
 * Copyright (C) 2003 Sun Microsystems, Inc.
 
4
 *
 
5
 * This is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This software is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this software; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
 
18
 * USA.
 
19
 */
 
20
 
 
21
/*
 
22
 * Before including this file, you must define a number of CPP macros.
 
23
 *
 
24
 * BPP should be 8, 16 or 32 depending on the bits per pixel.
 
25
 * GET_IMAGE_INTO_BUF should be some code which gets a rectangle of pixel data
 
26
 * into the given buffer.  EXTRA_ARGS can be defined to pass any other
 
27
 * arguments needed by GET_IMAGE_INTO_BUF.
 
28
 *
 
29
 * Note that the buf argument to ZRLE_ENCODE needs to be at least one pixel
 
30
 * bigger than the largest tile of pixel data, since the ZRLE encoding
 
31
 * algorithm writes to the position one past the end of the pixel data.
 
32
 */
 
33
 
 
34
#include "zrleoutstream.h"
 
35
#include "zrlepalettehelper.h"
 
36
#include <assert.h>
 
37
 
 
38
/* __RFB_CONCAT2 concatenates its two arguments.  __RFB_CONCAT2E does the same
 
39
   but also expands its arguments if they are macros */
 
40
 
 
41
#ifndef __RFB_CONCAT2E
 
42
#define __RFB_CONCAT2(a,b) a##b
 
43
#define __RFB_CONCAT2E(a,b) __RFB_CONCAT2(a,b)
 
44
#endif
 
45
 
 
46
#ifndef __RFB_CONCAT3E
 
47
#define __RFB_CONCAT3(a,b,c) a##b##c
 
48
#define __RFB_CONCAT3E(a,b,c) __RFB_CONCAT3(a,b,c)
 
49
#endif
 
50
 
 
51
#undef END_FIX
 
52
#if ZYWRLE_ENDIAN == ENDIAN_LITTLE
 
53
#  define END_FIX LE
 
54
#elif ZYWRLE_ENDIAN == ENDIAN_BIG
 
55
#  define END_FIX BE
 
56
#else
 
57
#  define END_FIX NE
 
58
#endif
 
59
 
 
60
#ifdef CPIXEL
 
61
#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP)
 
62
#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,CPIXEL)
 
63
#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,CPIXEL,END_FIX)
 
64
#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,CPIXEL,END_FIX)
 
65
#define BPPOUT 24
 
66
#elif BPP==15
 
67
#define PIXEL_T __RFB_CONCAT2E(zrle_U,16)
 
68
#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,16)
 
69
#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX)
 
70
#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX)
 
71
#define BPPOUT 16
 
72
#else
 
73
#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP)
 
74
#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,BPP)
 
75
#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX)
 
76
#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX)
 
77
#define BPPOUT BPP
 
78
#endif
 
79
 
 
80
#ifndef ZRLE_ONCE
 
81
#define ZRLE_ONCE
 
82
 
 
83
static const int bitsPerPackedPixel[] = {
 
84
  0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
 
85
};
 
86
 
 
87
static zrlePaletteHelper paletteHelper;
 
88
 
 
89
#endif /* ZRLE_ONCE */
 
90
 
 
91
void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os,
 
92
                int zywrle_level, int *zywrleBuf);
 
93
 
 
94
#if BPP!=8
 
95
#define ZYWRLE_ENCODE
 
96
#include "zywrletemplate.c"
 
97
#endif
 
98
 
 
99
static void ZRLE_ENCODE (int x, int y, int w, int h,
 
100
                  zrleOutStream* os, void* buf
 
101
                  EXTRA_ARGS
 
102
                  )
 
103
{
 
104
  int ty;
 
105
  for (ty = y; ty < y+h; ty += rfbZRLETileHeight) {
 
106
    int tx, th = rfbZRLETileHeight;
 
107
    if (th > y+h-ty) th = y+h-ty;
 
108
    for (tx = x; tx < x+w; tx += rfbZRLETileWidth) {
 
109
      int tw = rfbZRLETileWidth;
 
110
      if (tw > x+w-tx) tw = x+w-tx;
 
111
 
 
112
      GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf);
 
113
 
 
114
      ZRLE_ENCODE_TILE((PIXEL_T*)buf, tw, th, os,
 
115
                      cl->zywrleLevel, cl->zywrleBuf);
 
116
    }
 
117
  }
 
118
  zrleOutStreamFlush(os);
 
119
}
 
120
 
 
121
 
 
122
void ZRLE_ENCODE_TILE(PIXEL_T* data, int w, int h, zrleOutStream* os,
 
123
        int zywrle_level, int *zywrleBuf)
 
124
{
 
125
  /* First find the palette and the number of runs */
 
126
 
 
127
  zrlePaletteHelper *ph;
 
128
 
 
129
  int runs = 0;
 
130
  int singlePixels = 0;
 
131
 
 
132
  rfbBool useRle;
 
133
  rfbBool usePalette;
 
134
 
 
135
  int estimatedBytes;
 
136
  int plainRleBytes;
 
137
  int i;
 
138
 
 
139
  PIXEL_T* ptr = data;
 
140
  PIXEL_T* end = ptr + h * w;
 
141
  *end = ~*(end-1); /* one past the end is different so the while loop ends */
 
142
 
 
143
  ph = &paletteHelper;
 
144
  zrlePaletteHelperInit(ph);
 
145
 
 
146
  while (ptr < end) {
 
147
    PIXEL_T pix = *ptr;
 
148
    if (*++ptr != pix) {
 
149
      singlePixels++;
 
150
    } else {
 
151
      while (*++ptr == pix) ;
 
152
      runs++;
 
153
    }
 
154
    zrlePaletteHelperInsert(ph, pix);
 
155
  }
 
156
 
 
157
  /* Solid tile is a special case */
 
158
 
 
159
  if (ph->size == 1) {
 
160
    zrleOutStreamWriteU8(os, 1);
 
161
    zrleOutStreamWRITE_PIXEL(os, ph->palette[0]);
 
162
    return;
 
163
  }
 
164
 
 
165
  /* Try to work out whether to use RLE and/or a palette.  We do this by
 
166
     estimating the number of bytes which will be generated and picking the
 
167
     method which results in the fewest bytes.  Of course this may not result
 
168
     in the fewest bytes after compression... */
 
169
 
 
170
  useRle = FALSE;
 
171
  usePalette = FALSE;
 
172
 
 
173
  estimatedBytes = w * h * (BPPOUT/8); /* start assuming raw */
 
174
 
 
175
#if BPP!=8
 
176
  if (zywrle_level > 0 && !(zywrle_level & 0x80))
 
177
          estimatedBytes >>= zywrle_level;
 
178
#endif
 
179
 
 
180
  plainRleBytes = ((BPPOUT/8)+1) * (runs + singlePixels);
 
181
 
 
182
  if (plainRleBytes < estimatedBytes) {
 
183
    useRle = TRUE;
 
184
    estimatedBytes = plainRleBytes;
 
185
  }
 
186
 
 
187
  if (ph->size < 128) {
 
188
    int paletteRleBytes = (BPPOUT/8) * ph->size + 2 * runs + singlePixels;
 
189
 
 
190
    if (paletteRleBytes < estimatedBytes) {
 
191
      useRle = TRUE;
 
192
      usePalette = TRUE;
 
193
      estimatedBytes = paletteRleBytes;
 
194
    }
 
195
 
 
196
    if (ph->size < 17) {
 
197
      int packedBytes = ((BPPOUT/8) * ph->size +
 
198
                         w * h * bitsPerPackedPixel[ph->size-1] / 8);
 
199
 
 
200
      if (packedBytes < estimatedBytes) {
 
201
        useRle = FALSE;
 
202
        usePalette = TRUE;
 
203
        estimatedBytes = packedBytes;
 
204
      }
 
205
    }
 
206
  }
 
207
 
 
208
  if (!usePalette) ph->size = 0;
 
209
 
 
210
  zrleOutStreamWriteU8(os, (useRle ? 128 : 0) | ph->size);
 
211
 
 
212
  for (i = 0; i < ph->size; i++) {
 
213
    zrleOutStreamWRITE_PIXEL(os, ph->palette[i]);
 
214
  }
 
215
 
 
216
  if (useRle) {
 
217
 
 
218
    PIXEL_T* ptr = data;
 
219
    PIXEL_T* end = ptr + w * h;
 
220
    PIXEL_T* runStart;
 
221
    PIXEL_T pix;
 
222
    while (ptr < end) {
 
223
      int len;
 
224
      runStart = ptr;
 
225
      pix = *ptr++;
 
226
      while (*ptr == pix && ptr < end)
 
227
        ptr++;
 
228
      len = ptr - runStart;
 
229
      if (len <= 2 && usePalette) {
 
230
        int index = zrlePaletteHelperLookup(ph, pix);
 
231
        if (len == 2)
 
232
          zrleOutStreamWriteU8(os, index);
 
233
        zrleOutStreamWriteU8(os, index);
 
234
        continue;
 
235
      }
 
236
      if (usePalette) {
 
237
        int index = zrlePaletteHelperLookup(ph, pix);
 
238
        zrleOutStreamWriteU8(os, index | 128);
 
239
      } else {
 
240
        zrleOutStreamWRITE_PIXEL(os, pix);
 
241
      }
 
242
      len -= 1;
 
243
      while (len >= 255) {
 
244
        zrleOutStreamWriteU8(os, 255);
 
245
        len -= 255;
 
246
      }
 
247
      zrleOutStreamWriteU8(os, len);
 
248
    }
 
249
 
 
250
  } else {
 
251
 
 
252
    /* no RLE */
 
253
 
 
254
    if (usePalette) {
 
255
      int bppp;
 
256
      PIXEL_T* ptr = data;
 
257
 
 
258
      /* packed pixels */
 
259
 
 
260
      assert (ph->size < 17);
 
261
 
 
262
      bppp = bitsPerPackedPixel[ph->size-1];
 
263
 
 
264
      for (i = 0; i < h; i++) {
 
265
        zrle_U8 nbits = 0;
 
266
        zrle_U8 byte = 0;
 
267
 
 
268
        PIXEL_T* eol = ptr + w;
 
269
 
 
270
        while (ptr < eol) {
 
271
          PIXEL_T pix = *ptr++;
 
272
          zrle_U8 index = zrlePaletteHelperLookup(ph, pix);
 
273
          byte = (byte << bppp) | index;
 
274
          nbits += bppp;
 
275
          if (nbits >= 8) {
 
276
            zrleOutStreamWriteU8(os, byte);
 
277
            nbits = 0;
 
278
          }
 
279
        }
 
280
        if (nbits > 0) {
 
281
          byte <<= 8 - nbits;
 
282
          zrleOutStreamWriteU8(os, byte);
 
283
        }
 
284
      }
 
285
    } else {
 
286
 
 
287
      /* raw */
 
288
 
 
289
#if BPP!=8
 
290
      if (zywrle_level > 0 && !(zywrle_level & 0x80)) {
 
291
        ZYWRLE_ANALYZE(data, data, w, h, w, zywrle_level, zywrleBuf);
 
292
        ZRLE_ENCODE_TILE(data, w, h, os, zywrle_level | 0x80, zywrleBuf);
 
293
      }
 
294
      else
 
295
#endif
 
296
      {
 
297
#ifdef CPIXEL
 
298
        PIXEL_T *ptr;
 
299
        for (ptr = data; ptr < data+w*h; ptr++)
 
300
          zrleOutStreamWRITE_PIXEL(os, *ptr);
 
301
#else
 
302
        zrleOutStreamWriteBytes(os, (zrle_U8 *)data, w*h*(BPP/8));
 
303
#endif
 
304
      }
 
305
    }
 
306
  }
 
307
}
 
308
 
 
309
#undef PIXEL_T
 
310
#undef zrleOutStreamWRITE_PIXEL
 
311
#undef ZRLE_ENCODE
 
312
#undef ZRLE_ENCODE_TILE
 
313
#undef ZYWRLE_ENCODE_TILE
 
314
#undef BPPOUT