2
* Copyright (C) 2005 Johannes E. Schindelin. All Rights Reserved.
4
* This is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This software is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this software; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20
#ifdef LIBVNCSERVER_HAVE_LIBZ
23
* zrle.c - handle zrle encoding.
25
* This file shouldn't be compiled directly. It is included multiple times by
26
* rfbproto.c, each time with a different definition of the macro BPP. For
27
* each value of BPP, this file defines a function which handles an zrle
28
* encoded rectangle with BPP bits per pixel.
35
#if !defined(UNCOMP) || UNCOMP==0
36
#define HandleZRLE CONCAT2E(HandleZRLE,REALBPP)
37
#define HandleZRLETile CONCAT2E(HandleZRLETile,REALBPP)
39
#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Down)
40
#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Down)
42
#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Up)
43
#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Up)
45
#define CARDBPP CONCAT3E(uint,BPP,_t)
46
#define CARDREALBPP CONCAT3E(uint,REALBPP,_t)
48
#define ENDIAN_LITTLE 0
51
#define ZYWRLE_ENDIAN ENDIAN_LITTLE
53
#if ZYWRLE_ENDIAN == ENDIAN_LITTLE
55
#elif ZYWRLE_ENDIAN == ENDIAN_BIG
60
#define __RFB_CONCAT3E(a,b,c) CONCAT3E(a,b,c)
61
#define __RFB_CONCAT2E(a,b) CONCAT2E(a,b)
65
#define CPIXEL REALBPP
67
#define CPIXEL CONCAT2E(REALBPP,Down)
69
#define CPIXEL CONCAT2E(REALBPP,Up)
72
#define PIXEL_T __RFB_CONCAT3E(uint,BPP,_t)
74
#define ZYWRLE_DECODE 1
75
#include "../libvncserver/zywrletemplate.c"
79
static int HandleZRLETile(rfbClient* client,
80
uint8_t* buffer,size_t buffer_length,
81
int x,int y,int w,int h);
84
HandleZRLE (rfbClient* client, int rx, int ry, int rw, int rh)
90
int min_buffer_size = rw * rh * (REALBPP / 8) * 2;
92
/* First make sure we have a large enough raw buffer to hold the
93
* decompressed data. In practice, with a fixed REALBPP, fixed frame
94
* buffer size and the first update containing the entire frame
95
* buffer, this buffer allocation should only happen once, on the
98
if ( client->raw_buffer_size < min_buffer_size) {
100
if ( client->raw_buffer != NULL ) {
102
free( client->raw_buffer );
106
client->raw_buffer_size = min_buffer_size;
107
client->raw_buffer = (char*) malloc( client->raw_buffer_size );
111
if (!ReadFromRFBServer(client, (char *)&header, sz_rfbZRLEHeader))
114
remaining = rfbClientSwap32IfLE(header.length);
116
/* Need to initialize the decompressor state. */
117
client->decompStream.next_in = ( Bytef * )client->buffer;
118
client->decompStream.avail_in = 0;
119
client->decompStream.next_out = ( Bytef * )client->raw_buffer;
120
client->decompStream.avail_out = client->raw_buffer_size;
121
client->decompStream.data_type = Z_BINARY;
123
/* Initialize the decompression stream structures on the first invocation. */
124
if ( client->decompStreamInited == FALSE ) {
126
inflateResult = inflateInit( &client->decompStream );
128
if ( inflateResult != Z_OK ) {
130
"inflateInit returned error: %d, msg: %s\n",
132
client->decompStream.msg);
136
client->decompStreamInited = TRUE;
140
inflateResult = Z_OK;
142
/* Process buffer full of data until no more to process, or
143
* some type of inflater error, or Z_STREAM_END.
145
while (( remaining > 0 ) &&
146
( inflateResult == Z_OK )) {
148
if ( remaining > RFB_BUFFER_SIZE ) {
149
toRead = RFB_BUFFER_SIZE;
155
/* Fill the buffer, obtaining data from the server. */
156
if (!ReadFromRFBServer(client, client->buffer,toRead))
159
client->decompStream.next_in = ( Bytef * )client->buffer;
160
client->decompStream.avail_in = toRead;
162
/* Need to uncompress buffer full. */
163
inflateResult = inflate( &client->decompStream, Z_SYNC_FLUSH );
165
/* We never supply a dictionary for compression. */
166
if ( inflateResult == Z_NEED_DICT ) {
167
rfbClientLog("zlib inflate needs a dictionary!\n");
170
if ( inflateResult < 0 ) {
172
"zlib inflate returned error: %d, msg: %s\n",
174
client->decompStream.msg);
178
/* Result buffer allocated to be at least large enough. We should
179
* never run out of space!
181
if (( client->decompStream.avail_in > 0 ) &&
182
( client->decompStream.avail_out <= 0 )) {
183
rfbClientLog("zlib inflate ran out of space!\n");
189
} /* while ( remaining > 0 ) */
191
if ( inflateResult == Z_OK ) {
192
void* buf=client->raw_buffer;
195
remaining = client->raw_buffer_size-client->decompStream.avail_out;
197
for(j=0; j<rh; j+=rfbZRLETileHeight)
198
for(i=0; i<rw; i+=rfbZRLETileWidth) {
199
int subWidth=(i+rfbZRLETileWidth>rw)?rw-i:rfbZRLETileWidth;
200
int subHeight=(j+rfbZRLETileHeight>rh)?rh-j:rfbZRLETileHeight;
201
int result=HandleZRLETile(client,buf,remaining,rx+i,ry+j,subWidth,subHeight);
204
rfbClientLog("ZRLE decoding failed (%d)\n",result);
216
"zlib inflate returned error: %d, msg: %s\n",
218
client->decompStream.msg);
226
#if REALBPP!=BPP && defined(UNCOMP) && UNCOMP!=0
228
#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)>>UNCOMP)
230
#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)<<(-(UNCOMP)))
233
#define UncompressCPixel(pointer) (*(CARDBPP*)pointer)
236
static int HandleZRLETile(rfbClient* client,
237
uint8_t* buffer,size_t buffer_length,
238
int x,int y,int w,int h) {
239
uint8_t* buffer_copy = buffer;
240
uint8_t* buffer_end = buffer+buffer_length;
243
uint8_t zywrle_level = (client->appData.qualityLevel & 0x80) ?
244
0 : (3 - client->appData.qualityLevel / 3);
253
if( type == 0 ) /* raw */
255
if( zywrle_level > 0 ){
256
CARDBPP* pFrame = (CARDBPP*)client->frameBuffer + y*client->width+x;
258
client->appData.qualityLevel |= 0x80;
259
ret = HandleZRLETile(client, buffer, buffer_end-buffer, x, y, w, h);
260
client->appData.qualityLevel &= 0x7F;
264
ZYWRLE_SYNTHESIZE( pFrame, pFrame, w, h, client->width, zywrle_level, (int*)client->zlib_buffer );
272
if(1+w*h*REALBPP/8>buffer_length) {
273
rfbClientLog("expected %d bytes, got only %d (%dx%d)\n",1+w*h*REALBPP/8,buffer_length,w,h);
277
for(j=y*client->width; j<(y+h)*client->width; j+=client->width)
278
for(i=x; i<x+w; i++,buffer+=REALBPP/8)
279
((CARDBPP*)client->frameBuffer)[j+i] = UncompressCPixel(buffer);
281
CopyRectangle(client, buffer, x, y, w, h);
282
buffer+=w*h*REALBPP/8;
285
else if( type == 1 ) /* solid */
287
CARDBPP color = UncompressCPixel(buffer);
289
if(1+REALBPP/8>buffer_length)
292
FillRectangle(client, x, y, w, h, color);
297
else if( (type >= 2)&&(type <= 127) ) /* packed Palette */
301
bpp=(type>4?(type>16?8:4):(type>2?2:1)),
305
if(1+type*REALBPP/8+((w+divider-1)/divider)*h>buffer_length)
309
for(i=0; i<type; i++,buffer+=REALBPP/8)
310
palette[i] = UncompressCPixel(buffer);
312
/* read palettized pixels */
313
for(j=y*client->width; j<(y+h)*client->width; j+=client->width) {
314
for(i=x,shift=8-bpp; i<x+w; i++) {
315
((CARDBPP*)client->frameBuffer)[j+i] = palette[((*buffer)>>shift)&mask];
327
/* case 17 ... 127: not used, but valid */
328
else if( type == 128 ) /* plain RLE */
334
if(buffer+REALBPP/8+1>buffer_end)
336
color = UncompressCPixel(buffer);
338
/* read run length */
340
while(*buffer==0xff) {
341
if(buffer+1>=buffer_end)
348
while(j<h && length>0) {
349
((CARDBPP*)client->frameBuffer)[(y+j)*client->width+x+i] = color;
358
rfbClientLog("Warning: possible ZRLE corruption\n");
362
else if( type == 129 ) /* unused */
366
else if( (type >= 130)&&(type <= 255) ) /* palette RLE */
368
CARDBPP palette[128];
371
if(2+(type-128)*REALBPP/8>buffer_length)
375
for(i=0; i<type-128; i++,buffer+=REALBPP/8)
376
palette[i] = UncompressCPixel(buffer);
377
/* read palettized pixels */
382
if(buffer>=buffer_end)
384
color = palette[(*buffer)&0x7f];
387
if(buffer+1>=buffer_end)
390
/* read run length */
391
while(*buffer==0xff) {
392
if(buffer+1>=buffer_end)
400
while(j<h && length>0) {
401
((CARDBPP*)client->frameBuffer)[(y+j)*client->width+x+i] = color;
410
rfbClientLog("Warning: possible ZRLE corruption\n");
415
return buffer-buffer_copy;
421
#undef HandleZRLETile
422
#undef UncompressCPixel