/[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 1371 - (hide annotations)
Sat Jan 6 22:21:20 2007 UTC (17 years, 5 months ago) by jsorg71
File MIME type: text/plain
File size: 15179 byte(s)
remove old unused code and update email address

1 astrand 963 /* -*- c-basic-offset: 8 -*-
2 matty 3 rdesktop: A Remote Desktop Protocol client.
3     Bitmap decompression routines
4 jsorg71 1365 Copyright (C) Matthew Chapman 1999-2007
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 jsorg71 1371 /* three seperate function for speed when decompressing the bitmaps
22     when modifing one function make the change in the others
23     jay.sorg@gmail.com */
24 jsorg71 649
25     /* indent is confused by this file */
26     /* *INDENT-OFF* */
27    
28 matty 10 #include "rdesktop.h"
29 matty 3
30 matty 7 #define CVAL(p) (*(p++))
31 stargo 693 #ifdef NEED_ALIGN
32     #ifdef L_ENDIAN
33     #define CVAL2(p, v) { v = (*(p++)); v |= (*(p++)) << 8; }
34     #else
35     #define CVAL2(p, v) { v = (*(p++)) << 8; v |= (*(p++)); }
36     #endif /* L_ENDIAN */
37     #else
38 stargo 695 #define CVAL2(p, v) { v = (*((uint16*)p)); p += 2; }
39 stargo 693 #endif /* NEED_ALIGN */
40 matty 3
41 jsorg71 649 #define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
42    
43     #define REPEAT(statement) \
44     { \
45     while((count & ~0x7) && ((x+8) < width)) \
46     UNROLL8( statement; count--; x++; ); \
47     \
48     while((count > 0) && (x < width)) \
49     { \
50     statement; \
51     count--; \
52     x++; \
53     } \
54     }
55    
56     #define MASK_UPDATE() \
57     { \
58     mixmask <<= 1; \
59     if (mixmask == 0) \
60     { \
61     mask = fom_mask ? fom_mask : CVAL(input); \
62     mixmask = 1; \
63     } \
64     }
65    
66     /* 1 byte bitmap decompress */
67     static BOOL
68     bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size)
69     {
70     uint8 *end = input + size;
71     uint8 *prevline = NULL, *line = NULL;
72     int opcode, count, offset, isfillormix, x = width;
73     int lastopcode = -1, insertmix = False, bicolour = False;
74     uint8 code;
75     uint8 colour1 = 0, colour2 = 0;
76     uint8 mixmask, mask = 0;
77     uint8 mix = 0xff;
78     int fom_mask = 0;
79    
80     while (input < end)
81     {
82     fom_mask = 0;
83     code = CVAL(input);
84     opcode = code >> 4;
85     /* Handle different opcode forms */
86     switch (opcode)
87     {
88     case 0xc:
89     case 0xd:
90     case 0xe:
91     opcode -= 6;
92     count = code & 0xf;
93     offset = 16;
94     break;
95     case 0xf:
96     opcode = code & 0xf;
97     if (opcode < 9)
98     {
99     count = CVAL(input);
100     count |= CVAL(input) << 8;
101     }
102     else
103     {
104     count = (opcode < 0xb) ? 8 : 1;
105     }
106     offset = 0;
107     break;
108     default:
109     opcode >>= 1;
110     count = code & 0x1f;
111     offset = 32;
112     break;
113     }
114     /* Handle strange cases for counts */
115     if (offset != 0)
116     {
117     isfillormix = ((opcode == 2) || (opcode == 7));
118     if (count == 0)
119     {
120     if (isfillormix)
121     count = CVAL(input) + 1;
122     else
123     count = CVAL(input) + offset;
124     }
125     else if (isfillormix)
126     {
127     count <<= 3;
128     }
129     }
130     /* Read preliminary data */
131     switch (opcode)
132     {
133     case 0: /* Fill */
134     if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
135     insertmix = True;
136     break;
137     case 8: /* Bicolour */
138     colour1 = CVAL(input);
139     case 3: /* Colour */
140     colour2 = CVAL(input);
141     break;
142     case 6: /* SetMix/Mix */
143     case 7: /* SetMix/FillOrMix */
144     mix = CVAL(input);
145     opcode -= 5;
146     break;
147     case 9: /* FillOrMix_1 */
148     mask = 0x03;
149     opcode = 0x02;
150     fom_mask = 3;
151     break;
152     case 0x0a: /* FillOrMix_2 */
153     mask = 0x05;
154     opcode = 0x02;
155     fom_mask = 5;
156     break;
157     }
158     lastopcode = opcode;
159     mixmask = 0;
160     /* Output body */
161     while (count > 0)
162     {
163     if (x >= width)
164     {
165     if (height <= 0)
166     return False;
167     x = 0;
168     height--;
169     prevline = line;
170     line = output + height * width;
171     }
172     switch (opcode)
173     {
174     case 0: /* Fill */
175     if (insertmix)
176     {
177     if (prevline == NULL)
178     line[x] = mix;
179     else
180     line[x] = prevline[x] ^ mix;
181     insertmix = False;
182     count--;
183     x++;
184     }
185     if (prevline == NULL)
186     {
187     REPEAT(line[x] = 0)
188     }
189     else
190     {
191     REPEAT(line[x] = prevline[x])
192     }
193     break;
194     case 1: /* Mix */
195     if (prevline == NULL)
196     {
197     REPEAT(line[x] = mix)
198     }
199     else
200     {
201     REPEAT(line[x] = prevline[x] ^ mix)
202     }
203     break;
204     case 2: /* Fill or Mix */
205     if (prevline == NULL)
206     {
207     REPEAT
208     (
209     MASK_UPDATE();
210     if (mask & mixmask)
211     line[x] = mix;
212     else
213     line[x] = 0;
214     )
215     }
216     else
217     {
218     REPEAT
219     (
220     MASK_UPDATE();
221     if (mask & mixmask)
222     line[x] = prevline[x] ^ mix;
223     else
224     line[x] = prevline[x];
225     )
226     }
227     break;
228     case 3: /* Colour */
229     REPEAT(line[x] = colour2)
230     break;
231     case 4: /* Copy */
232     REPEAT(line[x] = CVAL(input))
233     break;
234     case 8: /* Bicolour */
235     REPEAT
236     (
237     if (bicolour)
238     {
239     line[x] = colour2;
240     bicolour = False;
241     }
242     else
243     {
244     line[x] = colour1;
245     bicolour = True; count++;
246     }
247     )
248     break;
249     case 0xd: /* White */
250     REPEAT(line[x] = 0xff)
251     break;
252     case 0xe: /* Black */
253     REPEAT(line[x] = 0)
254     break;
255     default:
256     unimpl("bitmap opcode 0x%x\n", opcode);
257     return False;
258     }
259     }
260     }
261     return True;
262     }
263    
264     /* 2 byte bitmap decompress */
265     static BOOL
266     bitmap_decompress2(uint8 * output, int width, int height, uint8 * input, int size)
267     {
268     uint8 *end = input + size;
269     uint16 *prevline = NULL, *line = NULL;
270     int opcode, count, offset, isfillormix, x = width;
271     int lastopcode = -1, insertmix = False, bicolour = False;
272     uint8 code;
273     uint16 colour1 = 0, colour2 = 0;
274     uint8 mixmask, mask = 0;
275     uint16 mix = 0xffff;
276     int fom_mask = 0;
277    
278     while (input < end)
279     {
280     fom_mask = 0;
281     code = CVAL(input);
282     opcode = code >> 4;
283     /* Handle different opcode forms */
284     switch (opcode)
285     {
286     case 0xc:
287     case 0xd:
288     case 0xe:
289     opcode -= 6;
290     count = code & 0xf;
291     offset = 16;
292     break;
293     case 0xf:
294     opcode = code & 0xf;
295     if (opcode < 9)
296     {
297     count = CVAL(input);
298     count |= CVAL(input) << 8;
299     }
300     else
301     {
302     count = (opcode < 0xb) ? 8 : 1;
303     }
304     offset = 0;
305     break;
306     default:
307     opcode >>= 1;
308     count = code & 0x1f;
309     offset = 32;
310     break;
311     }
312     /* Handle strange cases for counts */
313     if (offset != 0)
314     {
315     isfillormix = ((opcode == 2) || (opcode == 7));
316     if (count == 0)
317     {
318     if (isfillormix)
319     count = CVAL(input) + 1;
320     else
321     count = CVAL(input) + offset;
322     }
323     else if (isfillormix)
324     {
325     count <<= 3;
326     }
327     }
328     /* Read preliminary data */
329     switch (opcode)
330     {
331     case 0: /* Fill */
332     if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
333     insertmix = True;
334     break;
335     case 8: /* Bicolour */
336 stargo 693 CVAL2(input, colour1);
337 jsorg71 649 case 3: /* Colour */
338 stargo 693 CVAL2(input, colour2);
339 jsorg71 649 break;
340     case 6: /* SetMix/Mix */
341     case 7: /* SetMix/FillOrMix */
342 stargo 693 CVAL2(input, mix);
343 jsorg71 649 opcode -= 5;
344     break;
345     case 9: /* FillOrMix_1 */
346     mask = 0x03;
347     opcode = 0x02;
348     fom_mask = 3;
349     break;
350     case 0x0a: /* FillOrMix_2 */
351     mask = 0x05;
352     opcode = 0x02;
353     fom_mask = 5;
354     break;
355     }
356     lastopcode = opcode;
357     mixmask = 0;
358     /* Output body */
359     while (count > 0)
360     {
361     if (x >= width)
362     {
363     if (height <= 0)
364     return False;
365     x = 0;
366     height--;
367     prevline = line;
368     line = ((uint16 *) output) + height * width;
369     }
370     switch (opcode)
371     {
372     case 0: /* Fill */
373     if (insertmix)
374     {
375     if (prevline == NULL)
376     line[x] = mix;
377     else
378     line[x] = prevline[x] ^ mix;
379     insertmix = False;
380     count--;
381     x++;
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     case 1: /* Mix */
393     if (prevline == NULL)
394     {
395     REPEAT(line[x] = mix)
396     }
397     else
398     {
399     REPEAT(line[x] = prevline[x] ^ mix)
400     }
401     break;
402     case 2: /* Fill or Mix */
403     if (prevline == NULL)
404     {
405     REPEAT
406     (
407     MASK_UPDATE();
408     if (mask & mixmask)
409     line[x] = mix;
410     else
411     line[x] = 0;
412     )
413     }
414     else
415     {
416     REPEAT
417     (
418     MASK_UPDATE();
419     if (mask & mixmask)
420     line[x] = prevline[x] ^ mix;
421     else
422     line[x] = prevline[x];
423     )
424     }
425     break;
426     case 3: /* Colour */
427     REPEAT(line[x] = colour2)
428     break;
429     case 4: /* Copy */
430 stargo 693 REPEAT(CVAL2(input, line[x]))
431 jsorg71 649 break;
432     case 8: /* Bicolour */
433     REPEAT
434     (
435     if (bicolour)
436     {
437     line[x] = colour2;
438     bicolour = False;
439     }
440     else
441     {
442     line[x] = colour1;
443     bicolour = True;
444     count++;
445     }
446     )
447     break;
448     case 0xd: /* White */
449     REPEAT(line[x] = 0xffff)
450     break;
451     case 0xe: /* Black */
452     REPEAT(line[x] = 0)
453     break;
454     default:
455     unimpl("bitmap opcode 0x%x\n", opcode);
456     return False;
457     }
458     }
459     }
460     return True;
461     }
462    
463     /* 3 byte bitmap decompress */
464     static BOOL
465     bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int size)
466     {
467     uint8 *end = input + size;
468     uint8 *prevline = NULL, *line = NULL;
469     int opcode, count, offset, isfillormix, x = width;
470     int lastopcode = -1, insertmix = False, bicolour = False;
471     uint8 code;
472     uint8 colour1[3] = {0, 0, 0}, colour2[3] = {0, 0, 0};
473     uint8 mixmask, mask = 0;
474     uint8 mix[3] = {0xff, 0xff, 0xff};
475     int fom_mask = 0;
476    
477     while (input < end)
478     {
479     fom_mask = 0;
480     code = CVAL(input);
481     opcode = code >> 4;
482     /* Handle different opcode forms */
483     switch (opcode)
484     {
485     case 0xc:
486     case 0xd:
487     case 0xe:
488     opcode -= 6;
489     count = code & 0xf;
490     offset = 16;
491     break;
492     case 0xf:
493     opcode = code & 0xf;
494     if (opcode < 9)
495     {
496     count = CVAL(input);
497     count |= CVAL(input) << 8;
498     }
499     else
500     {
501     count = (opcode <
502     0xb) ? 8 : 1;
503     }
504     offset = 0;
505     break;
506     default:
507     opcode >>= 1;
508     count = code & 0x1f;
509     offset = 32;
510     break;
511     }
512     /* Handle strange cases for counts */
513     if (offset != 0)
514     {
515     isfillormix = ((opcode == 2) || (opcode == 7));
516     if (count == 0)
517     {
518     if (isfillormix)
519     count = CVAL(input) + 1;
520     else
521     count = CVAL(input) + offset;
522     }
523     else if (isfillormix)
524     {
525     count <<= 3;
526     }
527     }
528     /* Read preliminary data */
529     switch (opcode)
530     {
531     case 0: /* Fill */
532     if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
533     insertmix = True;
534     break;
535     case 8: /* Bicolour */
536     colour1[0] = CVAL(input);
537     colour1[1] = CVAL(input);
538     colour1[2] = CVAL(input);
539     case 3: /* Colour */
540     colour2[0] = CVAL(input);
541     colour2[1] = CVAL(input);
542     colour2[2] = CVAL(input);
543     break;
544     case 6: /* SetMix/Mix */
545     case 7: /* SetMix/FillOrMix */
546     mix[0] = CVAL(input);
547     mix[1] = CVAL(input);
548     mix[2] = CVAL(input);
549     opcode -= 5;
550     break;
551     case 9: /* FillOrMix_1 */
552     mask = 0x03;
553     opcode = 0x02;
554     fom_mask = 3;
555     break;
556     case 0x0a: /* FillOrMix_2 */
557     mask = 0x05;
558     opcode = 0x02;
559     fom_mask = 5;
560     break;
561     }
562     lastopcode = opcode;
563     mixmask = 0;
564     /* Output body */
565     while (count > 0)
566     {
567     if (x >= width)
568     {
569     if (height <= 0)
570     return False;
571     x = 0;
572     height--;
573     prevline = line;
574     line = output + height * (width * 3);
575     }
576     switch (opcode)
577     {
578     case 0: /* Fill */
579     if (insertmix)
580     {
581     if (prevline == NULL)
582     {
583     line[x * 3] = mix[0];
584     line[x * 3 + 1] = mix[1];
585     line[x * 3 + 2] = mix[2];
586     }
587     else
588     {
589     line[x * 3] =
590     prevline[x * 3] ^ mix[0];
591     line[x * 3 + 1] =
592     prevline[x * 3 + 1] ^ mix[1];
593     line[x * 3 + 2] =
594     prevline[x * 3 + 2] ^ mix[2];
595     }
596     insertmix = False;
597     count--;
598     x++;
599     }
600     if (prevline == NULL)
601     {
602     REPEAT
603     (
604     line[x * 3] = 0;
605     line[x * 3 + 1] = 0;
606     line[x * 3 + 2] = 0;
607     )
608     }
609     else
610     {
611     REPEAT
612     (
613     line[x * 3] = prevline[x * 3];
614     line[x * 3 + 1] = prevline[x * 3 + 1];
615     line[x * 3 + 2] = prevline[x * 3 + 2];
616     )
617     }
618     break;
619     case 1: /* Mix */
620     if (prevline == NULL)
621     {
622     REPEAT
623     (
624     line[x * 3] = mix[0];
625     line[x * 3 + 1] = mix[1];
626     line[x * 3 + 2] = mix[2];
627     )
628     }
629     else
630     {
631     REPEAT
632     (
633     line[x * 3] =
634     prevline[x * 3] ^ mix[0];
635     line[x * 3 + 1] =
636     prevline[x * 3 + 1] ^ mix[1];
637     line[x * 3 + 2] =
638     prevline[x * 3 + 2] ^ mix[2];
639     )
640     }
641     break;
642     case 2: /* Fill or Mix */
643     if (prevline == NULL)
644     {
645     REPEAT
646     (
647     MASK_UPDATE();
648     if (mask & mixmask)
649     {
650     line[x * 3] = mix[0];
651     line[x * 3 + 1] = mix[1];
652     line[x * 3 + 2] = mix[2];
653     }
654     else
655     {
656     line[x * 3] = 0;
657     line[x * 3 + 1] = 0;
658     line[x * 3 + 2] = 0;
659     }
660     )
661     }
662     else
663     {
664     REPEAT
665     (
666     MASK_UPDATE();
667     if (mask & mixmask)
668     {
669     line[x * 3] =
670     prevline[x * 3] ^ mix [0];
671     line[x * 3 + 1] =
672     prevline[x * 3 + 1] ^ mix [1];
673     line[x * 3 + 2] =
674     prevline[x * 3 + 2] ^ mix [2];
675     }
676     else
677     {
678     line[x * 3] =
679     prevline[x * 3];
680     line[x * 3 + 1] =
681     prevline[x * 3 + 1];
682     line[x * 3 + 2] =
683     prevline[x * 3 + 2];
684     }
685     )
686     }
687     break;
688     case 3: /* Colour */
689     REPEAT
690     (
691     line[x * 3] = colour2 [0];
692     line[x * 3 + 1] = colour2 [1];
693     line[x * 3 + 2] = colour2 [2];
694     )
695     break;
696     case 4: /* Copy */
697     REPEAT
698     (
699     line[x * 3] = CVAL(input);
700     line[x * 3 + 1] = CVAL(input);
701     line[x * 3 + 2] = CVAL(input);
702     )
703     break;
704     case 8: /* Bicolour */
705     REPEAT
706     (
707     if (bicolour)
708     {
709     line[x * 3] = colour2[0];
710     line[x * 3 + 1] = colour2[1];
711     line[x * 3 + 2] = colour2[2];
712     bicolour = False;
713     }
714     else
715     {
716     line[x * 3] = colour1[0];
717     line[x * 3 + 1] = colour1[1];
718     line[x * 3 + 2] = colour1[2];
719     bicolour = True;
720     count++;
721     }
722     )
723     break;
724     case 0xd: /* White */
725     REPEAT
726     (
727     line[x * 3] = 0xff;
728     line[x * 3 + 1] = 0xff;
729     line[x * 3 + 2] = 0xff;
730     )
731     break;
732     case 0xe: /* Black */
733     REPEAT
734     (
735     line[x * 3] = 0;
736     line[x * 3 + 1] = 0;
737     line[x * 3 + 2] = 0;
738     )
739     break;
740     default:
741     unimpl("bitmap opcode 0x%x\n", opcode);
742     return False;
743     }
744     }
745     }
746     return True;
747     }
748    
749     /* main decompress function */
750     BOOL
751     bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp)
752     {
753     BOOL rv = False;
754 jsorg71 1371
755 jsorg71 649 switch (Bpp)
756     {
757     case 1:
758     rv = bitmap_decompress1(output, width, height, input, size);
759     break;
760     case 2:
761     rv = bitmap_decompress2(output, width, height, input, size);
762     break;
763     case 3:
764     rv = bitmap_decompress3(output, width, height, input, size);
765     break;
766     }
767     return rv;
768     }
769    
770     /* *INDENT-ON* */

  ViewVC Help
Powered by ViewVC 1.1.26