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

« back to all changes in this revision

Viewing changes to common/ivs/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
 
#ifdef CPIXEL
47
 
#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP)
48
 
#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,CPIXEL)
49
 
#define ZRLE_ENCODE __RFB_CONCAT2E(zrleEncode,CPIXEL)
50
 
#define ZRLE_ENCODE_TILE __RFB_CONCAT2E(zrleEncodeTile,CPIXEL)
51
 
#define BPPOUT 24
52
 
#else
53
 
#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP)
54
 
#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,BPP)
55
 
#define ZRLE_ENCODE __RFB_CONCAT2E(zrleEncode,BPP)
56
 
#define ZRLE_ENCODE_TILE __RFB_CONCAT2E(zrleEncodeTile,BPP)
57
 
#define BPPOUT BPP
58
 
#endif
59
 
 
60
 
#ifndef ZRLE_ONCE
61
 
#define ZRLE_ONCE
62
 
 
63
 
static const int bitsPerPackedPixel[] = {
64
 
  0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
65
 
};
66
 
 
67
 
static zrlePaletteHelper paletteHelper;
68
 
 
69
 
#endif /* ZRLE_ONCE */
70
 
 
71
 
void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os);
72
 
 
73
 
void ZRLE_ENCODE (int x, int y, int w, int h,
74
 
                  zrleOutStream* os, void* buf
75
 
                  EXTRA_ARGS
76
 
                  )
77
 
{
78
 
  int ty;
79
 
  for (ty = y; ty < y+h; ty += rfbZRLETileHeight) {
80
 
    int tx, th = rfbZRLETileHeight;
81
 
    if (th > y+h-ty) th = y+h-ty;
82
 
    for (tx = x; tx < x+w; tx += rfbZRLETileWidth) {
83
 
      int tw = rfbZRLETileWidth;
84
 
      if (tw > x+w-tx) tw = x+w-tx;
85
 
 
86
 
      GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf);
87
 
 
88
 
      ZRLE_ENCODE_TILE((PIXEL_T*)buf, tw, th, os);
89
 
    }
90
 
  }
91
 
  zrleOutStreamFlush(os);
92
 
}
93
 
 
94
 
 
95
 
void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os)
96
 
{
97
 
  /* First find the palette and the number of runs */
98
 
 
99
 
  zrlePaletteHelper *ph;
100
 
 
101
 
  int runs = 0;
102
 
  int singlePixels = 0;
103
 
 
104
 
  rfbBool useRle;
105
 
  rfbBool usePalette;
106
 
 
107
 
  int estimatedBytes;
108
 
  int plainRleBytes;
109
 
  int i;
110
 
 
111
 
  PIXEL_T* ptr = data;
112
 
  PIXEL_T* end = ptr + h * w;
113
 
  *end = ~*(end-1); /* one past the end is different so the while loop ends */
114
 
 
115
 
  ph = &paletteHelper;
116
 
  zrlePaletteHelperInit(ph);
117
 
 
118
 
  while (ptr < end) {
119
 
    PIXEL_T pix = *ptr;
120
 
    if (*++ptr != pix) {
121
 
      singlePixels++;
122
 
    } else {
123
 
      while (*++ptr == pix) ;
124
 
      runs++;
125
 
    }
126
 
    zrlePaletteHelperInsert(ph, pix);
127
 
  }
128
 
 
129
 
  /* Solid tile is a special case */
130
 
 
131
 
  if (ph->size == 1) {
132
 
    zrleOutStreamWriteU8(os, 1);
133
 
    zrleOutStreamWRITE_PIXEL(os, ph->palette[0]);
134
 
    return;
135
 
  }
136
 
 
137
 
  /* Try to work out whether to use RLE and/or a palette.  We do this by
138
 
     estimating the number of bytes which will be generated and picking the
139
 
     method which results in the fewest bytes.  Of course this may not result
140
 
     in the fewest bytes after compression... */
141
 
 
142
 
  useRle = FALSE;
143
 
  usePalette = FALSE;
144
 
 
145
 
  estimatedBytes = w * h * (BPPOUT/8); /* start assuming raw */
146
 
 
147
 
  plainRleBytes = ((BPPOUT/8)+1) * (runs + singlePixels);
148
 
 
149
 
  if (plainRleBytes < estimatedBytes) {
150
 
    useRle = TRUE;
151
 
    estimatedBytes = plainRleBytes;
152
 
  }
153
 
 
154
 
  if (ph->size < 128) {
155
 
    int paletteRleBytes = (BPPOUT/8) * ph->size + 2 * runs + singlePixels;
156
 
 
157
 
    if (paletteRleBytes < estimatedBytes) {
158
 
      useRle = TRUE;
159
 
      usePalette = TRUE;
160
 
      estimatedBytes = paletteRleBytes;
161
 
    }
162
 
 
163
 
    if (ph->size < 17) {
164
 
      int packedBytes = ((BPPOUT/8) * ph->size +
165
 
                         w * h * bitsPerPackedPixel[ph->size-1] / 8);
166
 
 
167
 
      if (packedBytes < estimatedBytes) {
168
 
        useRle = FALSE;
169
 
        usePalette = TRUE;
170
 
        estimatedBytes = packedBytes;
171
 
      }
172
 
    }
173
 
  }
174
 
 
175
 
  if (!usePalette) ph->size = 0;
176
 
 
177
 
  zrleOutStreamWriteU8(os, (useRle ? 128 : 0) | ph->size);
178
 
 
179
 
  for (i = 0; i < ph->size; i++) {
180
 
    zrleOutStreamWRITE_PIXEL(os, ph->palette[i]);
181
 
  }
182
 
 
183
 
  if (useRle) {
184
 
 
185
 
    PIXEL_T* ptr = data;
186
 
    PIXEL_T* end = ptr + w * h;
187
 
    PIXEL_T* runStart;
188
 
    PIXEL_T pix;
189
 
    while (ptr < end) {
190
 
      int len;
191
 
      runStart = ptr;
192
 
      pix = *ptr++;
193
 
      while (*ptr == pix && ptr < end)
194
 
        ptr++;
195
 
      len = ptr - runStart;
196
 
      if (len <= 2 && usePalette) {
197
 
        int index = zrlePaletteHelperLookup(ph, pix);
198
 
        if (len == 2)
199
 
          zrleOutStreamWriteU8(os, index);
200
 
        zrleOutStreamWriteU8(os, index);
201
 
        continue;
202
 
      }
203
 
      if (usePalette) {
204
 
        int index = zrlePaletteHelperLookup(ph, pix);
205
 
        zrleOutStreamWriteU8(os, index | 128);
206
 
      } else {
207
 
        zrleOutStreamWRITE_PIXEL(os, pix);
208
 
      }
209
 
      len -= 1;
210
 
      while (len >= 255) {
211
 
        zrleOutStreamWriteU8(os, 255);
212
 
        len -= 255;
213
 
      }
214
 
      zrleOutStreamWriteU8(os, len);
215
 
    }
216
 
 
217
 
  } else {
218
 
 
219
 
    /* no RLE */
220
 
 
221
 
    if (usePalette) {
222
 
      int bppp;
223
 
      PIXEL_T* ptr = data;
224
 
 
225
 
      /* packed pixels */
226
 
 
227
 
      assert (ph->size < 17);
228
 
 
229
 
      bppp = bitsPerPackedPixel[ph->size-1];
230
 
 
231
 
      for (i = 0; i < h; i++) {
232
 
        zrle_U8 nbits = 0;
233
 
        zrle_U8 byte = 0;
234
 
 
235
 
        PIXEL_T* eol = ptr + w;
236
 
 
237
 
        while (ptr < eol) {
238
 
          PIXEL_T pix = *ptr++;
239
 
          zrle_U8 index = zrlePaletteHelperLookup(ph, pix);
240
 
          byte = (byte << bppp) | index;
241
 
          nbits += bppp;
242
 
          if (nbits >= 8) {
243
 
            zrleOutStreamWriteU8(os, byte);
244
 
            nbits = 0;
245
 
          }
246
 
        }
247
 
        if (nbits > 0) {
248
 
          byte <<= 8 - nbits;
249
 
          zrleOutStreamWriteU8(os, byte);
250
 
        }
251
 
      }
252
 
    } else {
253
 
 
254
 
      /* raw */
255
 
 
256
 
#ifdef CPIXEL
257
 
      PIXEL_T *ptr;
258
 
      for (ptr = data; ptr < data+w*h; ptr++) {
259
 
        zrleOutStreamWRITE_PIXEL(os, *ptr);
260
 
      }
261
 
#else
262
 
      zrleOutStreamWriteBytes(os, (zrle_U8 *)data, w*h*(BPP/8));
263
 
#endif
264
 
    }
265
 
  }
266
 
}
267
 
 
268
 
#undef PIXEL_T
269
 
#undef zrleOutStreamWRITE_PIXEL
270
 
#undef ZRLE_ENCODE
271
 
#undef ZRLE_ENCODE_TILE
272
 
#undef BPPOUT