/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 309 - (hide 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 matty 3 /*
2     rdesktop: A Remote Desktop Protocol client.
3     Bitmap decompression routines
4 matthewc 207 Copyright (C) Matthew Chapman 1999-2002
5 jsorg71 309
6 matty 3 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 jsorg71 309
11 matty 3 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 jsorg71 309
16 matty 3 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 matty 10 #include "rdesktop.h"
22 matty 3
23 matty 7 #define CVAL(p) (*(p++))
24 jsorg71 309 #define CVAL16(p) (*(((uint16*)p)++))
25 matty 3
26 matty 28 #define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
27 matty 3
28 matty 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 matty 25 BOOL
47 jsorg71 309 bitmap_decompress8(unsigned char *output, int width, int height, unsigned char *input, int size)
48 matty 3 {
49     unsigned char *end = input + size;
50 matty 10 unsigned char *prevline = NULL, *line = NULL;
51 matty 7 int opcode, count, offset, isfillormix, x = width;
52 matty 19 int lastopcode = -1, insertmix = False, bicolour = False;
53 matty 10 uint8 code, colour1 = 0, colour2 = 0;
54     uint8 mixmask, mask = 0, mix = 0xff;
55 matty 28 int fom_mask = 0;
56 matty 3
57     while (input < end)
58     {
59 matty 28 fom_mask = 0;
60 matty 7 code = CVAL(input);
61     opcode = code >> 4;
62    
63     /* Handle different opcode forms */
64     switch (opcode)
65 matty 3 {
66 matty 7 case 0xc:
67     case 0xd:
68     case 0xe:
69     opcode -= 6;
70     count = code & 0xf;
71     offset = 16;
72     break;
73 matty 3
74 matty 7 case 0xf:
75     opcode = code & 0xf;
76 matty 28 if (opcode < 9)
77 matty 36 {
78     count = CVAL(input);
79     count |= CVAL(input) << 8;
80     }
81 matty 28 else
82 matty 36 {
83 matty 28 count = (opcode < 0xb) ? 8 : 1;
84 matty 36 }
85 matty 7 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 matty 3 {
102 matty 7 if (isfillormix)
103     count = CVAL(input) + 1;
104     else
105     count = CVAL(input) + offset;
106 matty 3 }
107 matty 7 else if (isfillormix)
108     {
109     count <<= 3;
110     }
111     }
112 matty 3
113 matty 7 /* Read preliminary data */
114     switch (opcode)
115     {
116 matty 24 case 0: /* Fill */
117 astrand 82 if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
118 matty 9 insertmix = True;
119 matty 3 break;
120 matty 24 case 8: /* Bicolour */
121 matty 9 colour1 = CVAL(input);
122 matty 24 case 3: /* Colour */
123 matty 9 colour2 = CVAL(input);
124     break;
125 matty 24 case 6: /* SetMix/Mix */
126     case 7: /* SetMix/FillOrMix */
127 matty 7 mix = CVAL(input);
128     opcode -= 5;
129 matty 3 break;
130 matty 28 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 matty 7 }
142 matty 28
143 matty 9 lastopcode = opcode;
144 matty 28 mixmask = 0;
145 matty 3
146 matty 7 /* Output body */
147     while (count > 0)
148     {
149     if (x >= width)
150     {
151     if (height <= 0)
152 matty 9 return False;
153 matty 7
154     x = 0;
155     height--;
156    
157     prevline = line;
158     line = output + height * width;
159     }
160    
161     switch (opcode)
162     {
163 matty 24 case 0: /* Fill */
164 matty 9 if (insertmix)
165     {
166     if (prevline == NULL)
167     line[x] = mix;
168     else
169 astrand 82 line[x] = prevline[x] ^ mix;
170 matty 9
171     insertmix = False;
172     count--;
173     x++;
174     }
175    
176 matty 7 if (prevline == NULL)
177 matty 24 {
178     REPEAT(line[x] = 0);
179     }
180 matty 7 else
181 matty 24 {
182     REPEAT(line[x] = prevline[x]);
183     }
184 matty 3 break;
185 matty 7
186 matty 24 case 1: /* Mix */
187 matty 7 if (prevline == NULL)
188 matty 24 {
189     REPEAT(line[x] = mix);
190     }
191 matty 7 else
192 matty 24 {
193 astrand 82 REPEAT(line[x] = prevline[x] ^ mix);
194 matty 24 }
195 matty 3 break;
196 matty 7
197 matty 24 case 2: /* Fill or Mix */
198 matty 7 if (prevline == NULL)
199 matty 24 {
200     REPEAT(MASK_UPDATE();
201 astrand 82 if (mask & mixmask) line[x] = mix;
202 matty 24 else
203     line[x] = 0;);
204     }
205 matty 7 else
206 matty 24 {
207     REPEAT(MASK_UPDATE();
208     if (mask & mixmask)
209 astrand 82 line[x] = prevline[x] ^ mix;
210 matty 24 else
211 astrand 82 line[x] = prevline[x];);
212 matty 24 }
213 matty 7 break;
214 matty 3
215 matty 24 case 3: /* Colour */
216     REPEAT(line[x] = colour2);
217 matty 7 break;
218 matty 3
219 matty 24 case 4: /* Copy */
220     REPEAT(line[x] = CVAL(input));
221 matty 7 break;
222 matty 3
223 matty 24 case 8: /* Bicolour */
224     REPEAT(if (bicolour)
225     {
226 astrand 82 line[x] = colour2; bicolour = False;}
227 matty 24 else
228     {
229 astrand 82 line[x] = colour1; bicolour = True; count++;}
230 matty 24 );
231 matty 7 break;
232 matty 3
233 matty 28 case 0xd: /* White */
234 matty 24 REPEAT(line[x] = 0xff);
235 matty 7 break;
236 matty 3
237 matty 28 case 0xe: /* Black */
238 matty 24 REPEAT(line[x] = 0x00);
239 matty 7 break;
240 matty 3
241 matty 7 default:
242 astrand 82 unimpl("bitmap opcode 0x%x\n", opcode);
243 matty 7 return False;
244     }
245     }
246 matty 3 }
247    
248 matty 7 return True;
249 matty 3 }
250 jsorg71 309
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