/[rdesktop]/sourceforge.net/trunk/rdesktop/bitmap.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/trunk/rdesktop/bitmap.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (show annotations)
Fri Sep 14 13:51:38 2001 UTC (22 years, 9 months ago) by matty
File MIME type: text/plain
File size: 5018 byte(s)
Portability fixes, including elimination of variable argument macros.
Rudimentary configure script.
Miscellaneous cleanups.

1 /*
2 rdesktop: A Remote Desktop Protocol client.
3 Bitmap decompression routines
4 Copyright (C) Matthew Chapman 1999-2001
5
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.
10
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.
15
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.
19 */
20
21 #include "rdesktop.h"
22
23 #define CVAL(p) (*(p++))
24 #define SVAL(p) ((*((p++) + 1) << 8) | CVAL(p))
25
26 #define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
27
28 #define REPEAT(statement) \
29 { \
30 while((count & ~0x7) && ((x+8) < width)) \
31 UNROLL8( statement; count--; x++; ); \
32 \
33 while((count > 0) && (x < width)) { statement; count--; x++; } \
34 }
35
36 #define MASK_UPDATE() \
37 { \
38 mixmask <<= 1; \
39 if (mixmask == 0) \
40 { \
41 mask = fom_mask ? fom_mask : CVAL(input); \
42 mixmask = 1; \
43 } \
44 }
45
46 BOOL
47 bitmap_decompress(unsigned char *output, int width, int height,
48 unsigned char *input, int size)
49 {
50 unsigned char *end = input + size;
51 unsigned char *prevline = NULL, *line = NULL;
52 int opcode, count, offset, isfillormix, x = width;
53 int lastopcode = -1, insertmix = False, bicolour = False;
54 uint8 code, colour1 = 0, colour2 = 0;
55 uint8 mixmask, mask = 0, mix = 0xff;
56 int fom_mask = 0;
57
58 while (input < end)
59 {
60 fom_mask = 0;
61 code = CVAL(input);
62 opcode = code >> 4;
63
64 /* Handle different opcode forms */
65 switch (opcode)
66 {
67 case 0xc:
68 case 0xd:
69 case 0xe:
70 opcode -= 6;
71 count = code & 0xf;
72 offset = 16;
73 break;
74
75 case 0xf:
76 opcode = code & 0xf;
77 if (opcode < 9)
78 count = SVAL(input);
79 else
80 count = (opcode < 0xb) ? 8 : 1;
81 offset = 0;
82 break;
83
84 default:
85 opcode >>= 1;
86 count = code & 0x1f;
87 offset = 32;
88 break;
89 }
90
91 /* Handle strange cases for counts */
92 if (offset != 0)
93 {
94 isfillormix = ((opcode == 2) || (opcode == 7));
95
96 if (count == 0)
97 {
98 if (isfillormix)
99 count = CVAL(input) + 1;
100 else
101 count = CVAL(input) + offset;
102 }
103 else if (isfillormix)
104 {
105 count <<= 3;
106 }
107 }
108
109 /* Read preliminary data */
110 switch (opcode)
111 {
112 case 0: /* Fill */
113 if ((lastopcode == opcode)
114 && !((x == width) && (prevline == NULL)))
115 insertmix = True;
116 break;
117 case 8: /* Bicolour */
118 colour1 = CVAL(input);
119 case 3: /* Colour */
120 colour2 = CVAL(input);
121 break;
122 case 6: /* SetMix/Mix */
123 case 7: /* SetMix/FillOrMix */
124 mix = CVAL(input);
125 opcode -= 5;
126 break;
127 case 9: /* FillOrMix_1 */
128 mask = 0x03;
129 opcode = 0x02;
130 fom_mask = 3;
131 break;
132 case 0x0a: /* FillOrMix_2 */
133 mask = 0x05;
134 opcode = 0x02;
135 fom_mask = 5;
136 break;
137
138 }
139
140 lastopcode = opcode;
141 mixmask = 0;
142
143 /* Output body */
144 while (count > 0)
145 {
146 if (x >= width)
147 {
148 if (height <= 0)
149 return False;
150
151 x = 0;
152 height--;
153
154 prevline = line;
155 line = output + height * width;
156 }
157
158 switch (opcode)
159 {
160 case 0: /* Fill */
161 if (insertmix)
162 {
163 if (prevline == NULL)
164 line[x] = mix;
165 else
166 line[x] =
167 prevline[x] ^
168 mix;
169
170 insertmix = False;
171 count--;
172 x++;
173 }
174
175 if (prevline == NULL)
176 {
177 REPEAT(line[x] = 0);
178 }
179 else
180 {
181 REPEAT(line[x] = prevline[x]);
182 }
183 break;
184
185 case 1: /* Mix */
186 if (prevline == NULL)
187 {
188 REPEAT(line[x] = mix);
189 }
190 else
191 {
192 REPEAT(line[x] =
193 prevline[x] ^ mix);
194 }
195 break;
196
197 case 2: /* Fill or Mix */
198 if (prevline == NULL)
199 {
200 REPEAT(MASK_UPDATE();
201 if (mask & mixmask)
202 line[x] = mix;
203 else
204 line[x] = 0;);
205 }
206 else
207 {
208 REPEAT(MASK_UPDATE();
209 if (mask & mixmask)
210 line[x] =
211 prevline[x] ^ mix;
212 else
213 line[x] =
214 prevline[x];);
215 }
216 break;
217
218 case 3: /* Colour */
219 REPEAT(line[x] = colour2);
220 break;
221
222 case 4: /* Copy */
223 REPEAT(line[x] = CVAL(input));
224 break;
225
226 case 8: /* Bicolour */
227 REPEAT(if (bicolour)
228 {
229 line[x] = colour2;
230 bicolour = False;}
231 else
232 {
233 line[x] = colour1;
234 bicolour = True; count++;}
235 );
236 break;
237
238 case 0xd: /* White */
239 REPEAT(line[x] = 0xff);
240 break;
241
242 case 0xe: /* Black */
243 REPEAT(line[x] = 0x00);
244 break;
245
246 default:
247 unimpl("bitmap opcode 0x%x\n",
248 opcode);
249 return False;
250 }
251 }
252 }
253
254 return True;
255 }

  ViewVC Help
Powered by ViewVC 1.1.26