1
/* -*- c-basic-offset: 8 -*-
2
rdesktop: A Remote Desktop Protocol client.
3
Bitmap decompression routines
4
Copyright (C) Matthew Chapman 1999-2002
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
#define CVAL(p) (*(p++))
26
cvalx(unsigned char **input, int Bpp)
29
memcpy(&rv, *input, Bpp);
35
setli(unsigned char *input, int offset, uint32 value, int Bpp)
37
input += offset * Bpp;
38
memcpy(input, &value, Bpp);
42
getli(unsigned char *input, int offset, int Bpp)
45
input += offset * Bpp;
46
memcpy(&rv, input, Bpp);
50
#define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
52
#define REPEAT(statement) \
54
while((count & ~0x7) && ((x+8) < width)) \
55
UNROLL8( statement; count--; x++; ); \
57
while((count > 0) && (x < width)) { statement; count--; x++; } \
60
#define MASK_UPDATE() \
65
mask = fom_mask ? fom_mask : CVAL(input); \
71
bitmap_decompress(unsigned char *output, int width, int height, unsigned char *input, int size,
74
unsigned char *end = input + size;
75
unsigned char *prevline = NULL, *line = NULL;
76
int opcode, count, offset, isfillormix, x = width;
77
int lastopcode = -1, insertmix = False, bicolour = False;
79
uint32 colour1 = 0, colour2 = 0;
80
uint8 mixmask, mask = 0;
81
uint32 mix = 0xffffffff;
90
/* Handle different opcode forms */
106
count |= CVAL(input) << 8;
110
count = (opcode < 0xb) ? 8 : 1;
122
/* Handle strange cases for counts */
125
isfillormix = ((opcode == 2) || (opcode == 7));
130
count = CVAL(input) + 1;
132
count = CVAL(input) + offset;
134
else if (isfillormix)
140
/* Read preliminary data */
144
if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
147
case 8: /* Bicolour */
148
colour1 = cvalx(&input, Bpp);
150
colour2 = cvalx(&input, Bpp);
152
case 6: /* SetMix/Mix */
153
case 7: /* SetMix/FillOrMix */
154
mix = cvalx(&input, Bpp);
157
case 9: /* FillOrMix_1 */
162
case 0x0a: /* FillOrMix_2 */
185
line = output + height * width * Bpp;
193
if (prevline == NULL)
194
setli(line, x, mix, Bpp);
197
getli(prevline, x, Bpp) ^ mix, Bpp);
204
if (prevline == NULL)
206
REPEAT(setli(line, x, 0, Bpp))}
210
(line, x, getli(prevline, x, Bpp), Bpp));
215
if (prevline == NULL)
217
REPEAT(setli(line, x, mix, Bpp));
222
(line, x, getli(prevline, x, Bpp) ^ mix,
227
case 2: /* Fill or Mix */
228
if (prevline == NULL)
230
REPEAT(MASK_UPDATE();
231
if (mask & mixmask) setli(line, x, mix, Bpp);
233
setli(line, x, 0, Bpp););
237
REPEAT(MASK_UPDATE();
239
setli(line, x, getli(prevline, x, Bpp) ^ mix,
242
setli(line, x, getli(prevline, x, Bpp),
248
REPEAT(setli(line, x, colour2, Bpp));
252
REPEAT(setli(line, x, cvalx(&input, Bpp), Bpp));
255
case 8: /* Bicolour */
258
setli(line, x, colour2, Bpp); bicolour = False;}
261
setli(line, x, colour1, Bpp); bicolour = True;
266
case 0xd: /* White */
267
REPEAT(setli(line, x, 0xffffffff, Bpp));
270
case 0xe: /* Black */
271
REPEAT(setli(line, x, 0, Bpp));
275
unimpl("bitmap opcode 0x%x\n", opcode);