/[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 309 - (show annotations)
Tue Feb 4 05:32:13 2003 UTC (21 years, 4 months ago) by jsorg71
File MIME type: text/plain
File size: 8929 byte(s)
16bit

1 /*
2 rdesktop: A Remote Desktop Protocol client.
3 Bitmap decompression routines
4 Copyright (C) Matthew Chapman 1999-2002
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 CVAL16(p) (*(((uint16*)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_decompress8(unsigned char *output, int width, int height, unsigned char *input, int size)
48 {
49 unsigned char *end = input + size;
50 unsigned char *prevline = NULL, *line = NULL;
51 int opcode, count, offset, isfillormix, x = width;
52 int lastopcode = -1, insertmix = False, bicolour = False;
53 uint8 code, colour1 = 0, colour2 = 0;
54 uint8 mixmask, mask = 0, mix = 0xff;
55 int fom_mask = 0;
56
57 while (input < end)
58 {
59 fom_mask = 0;
60 code = CVAL(input);
61 opcode = code >> 4;
62
63 /* Handle different opcode forms */
64 switch (opcode)
65 {
66 case 0xc:
67 case 0xd:
68 case 0xe:
69 opcode -= 6;
70 count = code & 0xf;
71 offset = 16;
72 break;
73
74 case 0xf:
75 opcode = code & 0xf;
76 if (opcode < 9)
77 {
78 count = CVAL(input);
79 count |= CVAL(input) << 8;
80 }
81 else
82 {
83 count = (opcode < 0xb) ? 8 : 1;
84 }
85 offset = 0;
86 break;
87
88 default:
89 opcode >>= 1;
90 count = code & 0x1f;
91 offset = 32;
92 break;
93 }
94
95 /* Handle strange cases for counts */
96 if (offset != 0)
97 {
98 isfillormix = ((opcode == 2) || (opcode == 7));
99
100 if (count == 0)
101 {
102 if (isfillormix)
103 count = CVAL(input) + 1;
104 else
105 count = CVAL(input) + offset;
106 }
107 else if (isfillormix)
108 {
109 count <<= 3;
110 }
111 }
112
113 /* Read preliminary data */
114 switch (opcode)
115 {
116 case 0: /* Fill */
117 if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
118 insertmix = True;
119 break;
120 case 8: /* Bicolour */
121 colour1 = CVAL(input);
122 case 3: /* Colour */
123 colour2 = CVAL(input);
124 break;
125 case 6: /* SetMix/Mix */
126 case 7: /* SetMix/FillOrMix */
127 mix = CVAL(input);
128 opcode -= 5;
129 break;
130 case 9: /* FillOrMix_1 */
131 mask = 0x03;
132 opcode = 0x02;
133 fom_mask = 3;
134 break;
135 case 0x0a: /* FillOrMix_2 */
136 mask = 0x05;
137 opcode = 0x02;
138 fom_mask = 5;
139 break;
140
141 }
142
143 lastopcode = opcode;
144 mixmask = 0;
145
146 /* Output body */
147 while (count > 0)
148 {
149 if (x >= width)
150 {
151 if (height <= 0)
152 return False;
153
154 x = 0;
155 height--;
156
157 prevline = line;
158 line = output + height * width;
159 }
160
161 switch (opcode)
162 {
163 case 0: /* Fill */
164 if (insertmix)
165 {
166 if (prevline == NULL)
167 line[x] = mix;
168 else
169 line[x] = prevline[x] ^ mix;
170
171 insertmix = False;
172 count--;
173 x++;
174 }
175
176 if (prevline == NULL)
177 {
178 REPEAT(line[x] = 0);
179 }
180 else
181 {
182 REPEAT(line[x] = prevline[x]);
183 }
184 break;
185
186 case 1: /* Mix */
187 if (prevline == NULL)
188 {
189 REPEAT(line[x] = mix);
190 }
191 else
192 {
193 REPEAT(line[x] = 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) line[x] = mix;
202 else
203 line[x] = 0;);
204 }
205 else
206 {
207 REPEAT(MASK_UPDATE();
208 if (mask & mixmask)
209 line[x] = prevline[x] ^ mix;
210 else
211 line[x] = prevline[x];);
212 }
213 break;
214
215 case 3: /* Colour */
216 REPEAT(line[x] = colour2);
217 break;
218
219 case 4: /* Copy */
220 REPEAT(line[x] = CVAL(input));
221 break;
222
223 case 8: /* Bicolour */
224 REPEAT(if (bicolour)
225 {
226 line[x] = colour2; bicolour = False;}
227 else
228 {
229 line[x] = colour1; bicolour = True; count++;}
230 );
231 break;
232
233 case 0xd: /* White */
234 REPEAT(line[x] = 0xff);
235 break;
236
237 case 0xe: /* Black */
238 REPEAT(line[x] = 0x00);
239 break;
240
241 default:
242 unimpl("bitmap opcode 0x%x\n", opcode);
243 return False;
244 }
245 }
246 }
247
248 return True;
249 }
250
251 BOOL
252 bitmap_decompress16(unsigned char *output, int width, int height, unsigned char *input, int size)
253 {
254 unsigned char *end = input + size;
255 uint16 *prevline = NULL, *line = NULL;
256 int opcode, count, offset, isfillormix, x = width;
257 int lastopcode = -1, insertmix = False, bicolour = False;
258 uint8 code;
259 uint16 colour1 = 0, colour2 = 0;
260 uint8 mixmask, mask = 0;
261 uint16 mix = 0xffff;
262 int fom_mask = 0;
263
264 while (input < end)
265 {
266 fom_mask = 0;
267 code = CVAL(input);
268 opcode = code >> 4;
269
270 /* Handle different opcode forms */
271 switch (opcode)
272 {
273 case 0xc:
274 case 0xd:
275 case 0xe:
276 opcode -= 6;
277 count = code & 0xf;
278 offset = 16;
279 break;
280
281 case 0xf:
282 opcode = code & 0xf;
283 if (opcode < 9)
284 {
285 count = CVAL(input);
286 count |= CVAL(input) << 8;
287 }
288 else
289 {
290 count = (opcode < 0xd) ? 8 : 1; // was 0xb in 8 bit
291 }
292 offset = 0;
293 break;
294
295 default:
296 opcode >>= 1;
297 count = code & 0x1f;
298 offset = 32;
299 break;
300 }
301
302 /* Handle strange cases for counts */
303 if (offset != 0)
304 {
305 isfillormix = ((opcode == 2) || (opcode == 7));
306
307 if (count == 0)
308 {
309 if (isfillormix)
310 count = CVAL(input) + 1;
311 else
312 count = CVAL(input) + offset;
313 }
314 else if (isfillormix)
315 {
316 count <<= 3;
317 }
318 }
319
320 /* Read preliminary data */
321 switch (opcode)
322 {
323 case 0: /* Fill */
324 if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
325 insertmix = True;
326 break;
327 case 8: /* Bicolour */
328 colour1 = CVAL16(input);
329 case 3: /* Colour */
330 colour2 = CVAL16(input);
331 break;
332 case 6: /* SetMix/Mix */
333 case 7: /* SetMix/FillOrMix */
334 mix = CVAL16(input);
335 opcode -= 5;
336 break;
337 case 9: /* FillOrMix_1 */
338 mask = 0x03;
339 opcode = 0x02;
340 fom_mask = 3;
341 break;
342 case 0x0a: /* FillOrMix_2 */
343 mask = 0x05;
344 opcode = 0x02;
345 fom_mask = 5;
346 break;
347
348 }
349
350 lastopcode = opcode;
351 mixmask = 0;
352
353 /* Output body */
354 while (count > 0)
355 {
356 if (x >= width)
357 {
358 if (height <= 0)
359 return False;
360
361 x = 0;
362 height--;
363
364 prevline = line;
365 line = (uint16*)output + height * width;
366 }
367
368 switch (opcode)
369 {
370 case 0: /* Fill */
371 if (insertmix)
372 {
373 if (prevline == NULL)
374 line[x] = mix;
375 else
376 line[x] = prevline[x] ^ mix;
377
378 insertmix = False;
379 count--;
380 x++;
381 }
382
383 if (prevline == NULL)
384 {
385 REPEAT(line[x] = 0);
386 }
387 else
388 {
389 REPEAT(line[x] = prevline[x]);
390 }
391 break;
392
393 case 1: /* Mix */
394 if (prevline == NULL)
395 {
396 REPEAT(line[x] = mix);
397 }
398 else
399 {
400 REPEAT(line[x] = prevline[x] ^ mix);
401 }
402 break;
403
404 case 2: /* Fill or Mix */
405 if (prevline == NULL)
406 {
407 REPEAT(MASK_UPDATE();
408 if (mask & mixmask) line[x] = mix;
409 else
410 line[x] = 0;);
411 }
412 else
413 {
414 REPEAT(MASK_UPDATE();
415 if (mask & mixmask)
416 line[x] = prevline[x] ^ mix;
417 else
418 line[x] = prevline[x];);
419 }
420 break;
421
422 case 3: /* Colour */
423 REPEAT(line[x] = colour2);
424 break;
425
426 case 4: /* Copy */
427 REPEAT(line[x] = CVAL16(input));
428 break;
429
430 case 8: /* Bicolour */
431 REPEAT(if (bicolour)
432 {
433 line[x] = colour2; bicolour = False;}
434 else
435 {
436 line[x] = colour1; bicolour = True; count++;}
437 );
438 break;
439
440 case 0xd: /* White */
441 REPEAT(line[x] = 0xffff);
442 break;
443
444 case 0xe: /* Black */
445 REPEAT(line[x] = 0x00);
446 break;
447
448 default:
449 unimpl("bitmap opcode 0x%x\n", opcode);
450 return False;
451 }
452 }
453 }
454
455 return True;
456 }
457
458 BOOL
459 bitmap_decompress(unsigned char *output, int width, int height, unsigned char *input, int size, int bpp)
460 {
461 if (bpp == 8)
462 return bitmap_decompress8(output, width, height, input, size);
463 else if (bpp == 16)
464 return bitmap_decompress16(output, width, height, input, size);
465 else
466 return False;
467 }

  ViewVC Help
Powered by ViewVC 1.1.26