2
* Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
3
* Copyright (C) 2003 Sun Microsystems, Inc.
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.
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.
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,
22
* Before including this file, you must define a number of CPP macros.
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.
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.
34
#include "zrleoutstream.h"
35
#include "zrlepalettehelper.h"
38
/* __RFB_CONCAT2 concatenates its two arguments. __RFB_CONCAT2E does the same
39
but also expands its arguments if they are macros */
41
#ifndef __RFB_CONCAT2E
42
#define __RFB_CONCAT2(a,b) a##b
43
#define __RFB_CONCAT2E(a,b) __RFB_CONCAT2(a,b)
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)
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)
63
static const int bitsPerPackedPixel[] = {
64
0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
67
static zrlePaletteHelper paletteHelper;
69
#endif /* ZRLE_ONCE */
71
void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os);
73
void ZRLE_ENCODE (int x, int y, int w, int h,
74
zrleOutStream* os, void* buf
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;
86
GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf);
88
ZRLE_ENCODE_TILE((PIXEL_T*)buf, tw, th, os);
91
zrleOutStreamFlush(os);
95
void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os)
97
/* First find the palette and the number of runs */
99
zrlePaletteHelper *ph;
102
int singlePixels = 0;
112
PIXEL_T* end = ptr + h * w;
113
*end = ~*(end-1); /* one past the end is different so the while loop ends */
116
zrlePaletteHelperInit(ph);
123
while (*++ptr == pix) ;
126
zrlePaletteHelperInsert(ph, pix);
129
/* Solid tile is a special case */
132
zrleOutStreamWriteU8(os, 1);
133
zrleOutStreamWRITE_PIXEL(os, ph->palette[0]);
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... */
145
estimatedBytes = w * h * (BPPOUT/8); /* start assuming raw */
147
plainRleBytes = ((BPPOUT/8)+1) * (runs + singlePixels);
149
if (plainRleBytes < estimatedBytes) {
151
estimatedBytes = plainRleBytes;
154
if (ph->size < 128) {
155
int paletteRleBytes = (BPPOUT/8) * ph->size + 2 * runs + singlePixels;
157
if (paletteRleBytes < estimatedBytes) {
160
estimatedBytes = paletteRleBytes;
164
int packedBytes = ((BPPOUT/8) * ph->size +
165
w * h * bitsPerPackedPixel[ph->size-1] / 8);
167
if (packedBytes < estimatedBytes) {
170
estimatedBytes = packedBytes;
175
if (!usePalette) ph->size = 0;
177
zrleOutStreamWriteU8(os, (useRle ? 128 : 0) | ph->size);
179
for (i = 0; i < ph->size; i++) {
180
zrleOutStreamWRITE_PIXEL(os, ph->palette[i]);
186
PIXEL_T* end = ptr + w * h;
193
while (*ptr == pix && ptr < end)
195
len = ptr - runStart;
196
if (len <= 2 && usePalette) {
197
int index = zrlePaletteHelperLookup(ph, pix);
199
zrleOutStreamWriteU8(os, index);
200
zrleOutStreamWriteU8(os, index);
204
int index = zrlePaletteHelperLookup(ph, pix);
205
zrleOutStreamWriteU8(os, index | 128);
207
zrleOutStreamWRITE_PIXEL(os, pix);
211
zrleOutStreamWriteU8(os, 255);
214
zrleOutStreamWriteU8(os, len);
227
assert (ph->size < 17);
229
bppp = bitsPerPackedPixel[ph->size-1];
231
for (i = 0; i < h; i++) {
235
PIXEL_T* eol = ptr + w;
238
PIXEL_T pix = *ptr++;
239
zrle_U8 index = zrlePaletteHelperLookup(ph, pix);
240
byte = (byte << bppp) | index;
243
zrleOutStreamWriteU8(os, byte);
249
zrleOutStreamWriteU8(os, byte);
258
for (ptr = data; ptr < data+w*h; ptr++) {
259
zrleOutStreamWRITE_PIXEL(os, *ptr);
262
zrleOutStreamWriteBytes(os, (zrle_U8 *)data, w*h*(BPP/8));
269
#undef zrleOutStreamWRITE_PIXEL
271
#undef ZRLE_ENCODE_TILE