~ubuntu-branches/ubuntu/dapper/vino/dapper

« back to all changes in this revision

Viewing changes to server/libvncserver/zrleencodetemplate.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2004-10-12 19:36:40 UTC
  • Revision ID: james.westby@ubuntu.com-20041012193640-ybetkwuqt7e04dke
Tags: upstream-2.8.1
ImportĀ upstreamĀ versionĀ 2.8.1

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