VirtualBox

source: vbox/trunk/src/VBox/RDP/client-1.8.4/bitmap.c@ 83298

Last change on this file since 83298 was 76779, checked in by vboxsync, 6 years ago

RDP: add client-1.8.4.
bugref:9356: Update rdesktop-vrdp to 1.8.4
client-1.8.4 is a Subversion copy of 1.8.3 with the upstream 1.8.3 to 1.8.4
patch applied and a couple of fixes and changes after review, namely:

  • Stopped disabling the new pointer data format for our build, as this is no

longer needed.

  • Adjusted some snprintf buffers to make GCC happy.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.9 KB
Line 
1/* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Bitmap decompression routines
4 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
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 3 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, see <http://www.gnu.org/licenses/>.
18*/
19
20/*
21 * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
22 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
23 * the General Public License version 2 (GPLv2) at this time for any software where
24 * a choice of GPL license versions is made available with the language indicating
25 * that GPLv2 or any later version may be used, or where a choice of which version
26 * of the GPL is applied is otherwise unspecified.
27 */
28
29/* three seperate function for speed when decompressing the bitmaps
30 when modifing one function make the change in the others
31 jay.sorg@gmail.com */
32
33/* indent is confused by this file */
34/* *INDENT-OFF* */
35
36#include "rdesktop.h"
37
38#define CVAL(p) (*(p++))
39#ifdef NEED_ALIGN
40#ifdef L_ENDIAN
41#define CVAL2(p, v) { v = (*(p++)); v |= (*(p++)) << 8; }
42#else
43#define CVAL2(p, v) { v = (*(p++)) << 8; v |= (*(p++)); }
44#endif /* L_ENDIAN */
45#else
46#define CVAL2(p, v) { v = (*((uint16*)p)); p += 2; }
47#endif /* NEED_ALIGN */
48
49#define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
50
51#define REPEAT(statement) \
52{ \
53 while((count & ~0x7) && ((x+8) < width)) \
54 UNROLL8( statement; count--; x++; ); \
55 \
56 while((count > 0) && (x < width)) \
57 { \
58 statement; \
59 count--; \
60 x++; \
61 } \
62}
63
64#define MASK_UPDATE() \
65{ \
66 mixmask <<= 1; \
67 if (mixmask == 0) \
68 { \
69 mask = fom_mask ? fom_mask : CVAL(input); \
70 mixmask = 1; \
71 } \
72}
73
74/* 1 byte bitmap decompress */
75static RD_BOOL
76bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size)
77{
78 uint8 *end = input + size;
79 uint8 *prevline = NULL, *line = NULL;
80 int opcode, count, offset, isfillormix, x = width;
81 int lastopcode = -1, insertmix = False, bicolour = False;
82 uint8 code;
83 uint8 colour1 = 0, colour2 = 0;
84 uint8 mixmask, mask = 0;
85 uint8 mix = 0xff;
86 int fom_mask = 0;
87
88 while (input < end)
89 {
90 fom_mask = 0;
91 code = CVAL(input);
92 opcode = code >> 4;
93 /* Handle different opcode forms */
94 switch (opcode)
95 {
96 case 0xc:
97 case 0xd:
98 case 0xe:
99 opcode -= 6;
100 count = code & 0xf;
101 offset = 16;
102 break;
103 case 0xf:
104 opcode = code & 0xf;
105 if (opcode < 9)
106 {
107 count = CVAL(input);
108 count |= CVAL(input) << 8;
109 }
110 else
111 {
112 count = (opcode < 0xb) ? 8 : 1;
113 }
114 offset = 0;
115 break;
116 default:
117 opcode >>= 1;
118 count = code & 0x1f;
119 offset = 32;
120 break;
121 }
122 /* Handle strange cases for counts */
123 if (offset != 0)
124 {
125 isfillormix = ((opcode == 2) || (opcode == 7));
126 if (count == 0)
127 {
128 if (isfillormix)
129 count = CVAL(input) + 1;
130 else
131 count = CVAL(input) + offset;
132 }
133 else if (isfillormix)
134 {
135 count <<= 3;
136 }
137 }
138 /* Read preliminary data */
139 switch (opcode)
140 {
141 case 0: /* Fill */
142 if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
143 insertmix = True;
144 break;
145 case 8: /* Bicolour */
146 colour1 = CVAL(input);
147 case 3: /* Colour */
148 colour2 = CVAL(input);
149 break;
150 case 6: /* SetMix/Mix */
151 case 7: /* SetMix/FillOrMix */
152 mix = CVAL(input);
153 opcode -= 5;
154 break;
155 case 9: /* FillOrMix_1 */
156 mask = 0x03;
157 opcode = 0x02;
158 fom_mask = 3;
159 break;
160 case 0x0a: /* FillOrMix_2 */
161 mask = 0x05;
162 opcode = 0x02;
163 fom_mask = 5;
164 break;
165 }
166 lastopcode = opcode;
167 mixmask = 0;
168 /* Output body */
169 while (count > 0)
170 {
171 if (x >= width)
172 {
173 if (height <= 0)
174 return False;
175 x = 0;
176 height--;
177 prevline = line;
178 line = output + height * width;
179 }
180 switch (opcode)
181 {
182 case 0: /* Fill */
183 if (insertmix)
184 {
185 if (prevline == NULL)
186 line[x] = mix;
187 else
188 line[x] = prevline[x] ^ mix;
189 insertmix = False;
190 count--;
191 x++;
192 }
193 if (prevline == NULL)
194 {
195 REPEAT(line[x] = 0)
196 }
197 else
198 {
199 REPEAT(line[x] = prevline[x])
200 }
201 break;
202 case 1: /* Mix */
203 if (prevline == NULL)
204 {
205 REPEAT(line[x] = mix)
206 }
207 else
208 {
209 REPEAT(line[x] = prevline[x] ^ mix)
210 }
211 break;
212 case 2: /* Fill or Mix */
213 if (prevline == NULL)
214 {
215 REPEAT
216 (
217 MASK_UPDATE();
218 if (mask & mixmask)
219 line[x] = mix;
220 else
221 line[x] = 0;
222 )
223 }
224 else
225 {
226 REPEAT
227 (
228 MASK_UPDATE();
229 if (mask & mixmask)
230 line[x] = prevline[x] ^ mix;
231 else
232 line[x] = prevline[x];
233 )
234 }
235 break;
236 case 3: /* Colour */
237 REPEAT(line[x] = colour2)
238 break;
239 case 4: /* Copy */
240 REPEAT(line[x] = CVAL(input))
241 break;
242 case 8: /* Bicolour */
243 REPEAT
244 (
245 if (bicolour)
246 {
247 line[x] = colour2;
248 bicolour = False;
249 }
250 else
251 {
252 line[x] = colour1;
253 bicolour = True; count++;
254 }
255 )
256 break;
257 case 0xd: /* White */
258 REPEAT(line[x] = 0xff)
259 break;
260 case 0xe: /* Black */
261 REPEAT(line[x] = 0)
262 break;
263 default:
264 unimpl("bitmap opcode 0x%x\n", opcode);
265 return False;
266 }
267 }
268 }
269 return True;
270}
271
272/* 2 byte bitmap decompress */
273static RD_BOOL
274bitmap_decompress2(uint8 * output, int width, int height, uint8 * input, int size)
275{
276 uint8 *end = input + size;
277 uint16 *prevline = NULL, *line = NULL;
278 int opcode, count, offset, isfillormix, x = width;
279 int lastopcode = -1, insertmix = False, bicolour = False;
280 uint8 code;
281 uint16 colour1 = 0, colour2 = 0;
282 uint8 mixmask, mask = 0;
283 uint16 mix = 0xffff;
284 int fom_mask = 0;
285
286 while (input < end)
287 {
288 fom_mask = 0;
289 code = CVAL(input);
290 opcode = code >> 4;
291 /* Handle different opcode forms */
292 switch (opcode)
293 {
294 case 0xc:
295 case 0xd:
296 case 0xe:
297 opcode -= 6;
298 count = code & 0xf;
299 offset = 16;
300 break;
301 case 0xf:
302 opcode = code & 0xf;
303 if (opcode < 9)
304 {
305 count = CVAL(input);
306 count |= CVAL(input) << 8;
307 }
308 else
309 {
310 count = (opcode < 0xb) ? 8 : 1;
311 }
312 offset = 0;
313 break;
314 default:
315 opcode >>= 1;
316 count = code & 0x1f;
317 offset = 32;
318 break;
319 }
320 /* Handle strange cases for counts */
321 if (offset != 0)
322 {
323 isfillormix = ((opcode == 2) || (opcode == 7));
324 if (count == 0)
325 {
326 if (isfillormix)
327 count = CVAL(input) + 1;
328 else
329 count = CVAL(input) + offset;
330 }
331 else if (isfillormix)
332 {
333 count <<= 3;
334 }
335 }
336 /* Read preliminary data */
337 switch (opcode)
338 {
339 case 0: /* Fill */
340 if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
341 insertmix = True;
342 break;
343 case 8: /* Bicolour */
344 CVAL2(input, colour1);
345 case 3: /* Colour */
346 CVAL2(input, colour2);
347 break;
348 case 6: /* SetMix/Mix */
349 case 7: /* SetMix/FillOrMix */
350 CVAL2(input, mix);
351 opcode -= 5;
352 break;
353 case 9: /* FillOrMix_1 */
354 mask = 0x03;
355 opcode = 0x02;
356 fom_mask = 3;
357 break;
358 case 0x0a: /* FillOrMix_2 */
359 mask = 0x05;
360 opcode = 0x02;
361 fom_mask = 5;
362 break;
363 }
364 lastopcode = opcode;
365 mixmask = 0;
366 /* Output body */
367 while (count > 0)
368 {
369 if (x >= width)
370 {
371 if (height <= 0)
372 return False;
373 x = 0;
374 height--;
375 prevline = line;
376 line = ((uint16 *) output) + height * width;
377 }
378 switch (opcode)
379 {
380 case 0: /* Fill */
381 if (insertmix)
382 {
383 if (prevline == NULL)
384 line[x] = mix;
385 else
386 line[x] = prevline[x] ^ mix;
387 insertmix = False;
388 count--;
389 x++;
390 }
391 if (prevline == NULL)
392 {
393 REPEAT(line[x] = 0)
394 }
395 else
396 {
397 REPEAT(line[x] = prevline[x])
398 }
399 break;
400 case 1: /* Mix */
401 if (prevline == NULL)
402 {
403 REPEAT(line[x] = mix)
404 }
405 else
406 {
407 REPEAT(line[x] = prevline[x] ^ mix)
408 }
409 break;
410 case 2: /* Fill or Mix */
411 if (prevline == NULL)
412 {
413 REPEAT
414 (
415 MASK_UPDATE();
416 if (mask & mixmask)
417 line[x] = mix;
418 else
419 line[x] = 0;
420 )
421 }
422 else
423 {
424 REPEAT
425 (
426 MASK_UPDATE();
427 if (mask & mixmask)
428 line[x] = prevline[x] ^ mix;
429 else
430 line[x] = prevline[x];
431 )
432 }
433 break;
434 case 3: /* Colour */
435 REPEAT(line[x] = colour2)
436 break;
437 case 4: /* Copy */
438 REPEAT(CVAL2(input, line[x]))
439 break;
440 case 8: /* Bicolour */
441 REPEAT
442 (
443 if (bicolour)
444 {
445 line[x] = colour2;
446 bicolour = False;
447 }
448 else
449 {
450 line[x] = colour1;
451 bicolour = True;
452 count++;
453 }
454 )
455 break;
456 case 0xd: /* White */
457 REPEAT(line[x] = 0xffff)
458 break;
459 case 0xe: /* Black */
460 REPEAT(line[x] = 0)
461 break;
462 default:
463 unimpl("bitmap opcode 0x%x\n", opcode);
464 return False;
465 }
466 }
467 }
468 return True;
469}
470
471/* 3 byte bitmap decompress */
472static RD_BOOL
473bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int size)
474{
475 uint8 *end = input + size;
476 uint8 *prevline = NULL, *line = NULL;
477 int opcode, count, offset, isfillormix, x = width;
478 int lastopcode = -1, insertmix = False, bicolour = False;
479 uint8 code;
480 uint8 colour1[3] = {0, 0, 0}, colour2[3] = {0, 0, 0};
481 uint8 mixmask, mask = 0;
482 uint8 mix[3] = {0xff, 0xff, 0xff};
483 int fom_mask = 0;
484
485 while (input < end)
486 {
487 fom_mask = 0;
488 code = CVAL(input);
489 opcode = code >> 4;
490 /* Handle different opcode forms */
491 switch (opcode)
492 {
493 case 0xc:
494 case 0xd:
495 case 0xe:
496 opcode -= 6;
497 count = code & 0xf;
498 offset = 16;
499 break;
500 case 0xf:
501 opcode = code & 0xf;
502 if (opcode < 9)
503 {
504 count = CVAL(input);
505 count |= CVAL(input) << 8;
506 }
507 else
508 {
509 count = (opcode <
510 0xb) ? 8 : 1;
511 }
512 offset = 0;
513 break;
514 default:
515 opcode >>= 1;
516 count = code & 0x1f;
517 offset = 32;
518 break;
519 }
520 /* Handle strange cases for counts */
521 if (offset != 0)
522 {
523 isfillormix = ((opcode == 2) || (opcode == 7));
524 if (count == 0)
525 {
526 if (isfillormix)
527 count = CVAL(input) + 1;
528 else
529 count = CVAL(input) + offset;
530 }
531 else if (isfillormix)
532 {
533 count <<= 3;
534 }
535 }
536 /* Read preliminary data */
537 switch (opcode)
538 {
539 case 0: /* Fill */
540 if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
541 insertmix = True;
542 break;
543 case 8: /* Bicolour */
544 colour1[0] = CVAL(input);
545 colour1[1] = CVAL(input);
546 colour1[2] = CVAL(input);
547 case 3: /* Colour */
548 colour2[0] = CVAL(input);
549 colour2[1] = CVAL(input);
550 colour2[2] = CVAL(input);
551 break;
552 case 6: /* SetMix/Mix */
553 case 7: /* SetMix/FillOrMix */
554 mix[0] = CVAL(input);
555 mix[1] = CVAL(input);
556 mix[2] = CVAL(input);
557 opcode -= 5;
558 break;
559 case 9: /* FillOrMix_1 */
560 mask = 0x03;
561 opcode = 0x02;
562 fom_mask = 3;
563 break;
564 case 0x0a: /* FillOrMix_2 */
565 mask = 0x05;
566 opcode = 0x02;
567 fom_mask = 5;
568 break;
569 }
570 lastopcode = opcode;
571 mixmask = 0;
572 /* Output body */
573 while (count > 0)
574 {
575 if (x >= width)
576 {
577 if (height <= 0)
578 return False;
579 x = 0;
580 height--;
581 prevline = line;
582 line = output + height * (width * 3);
583 }
584 switch (opcode)
585 {
586 case 0: /* Fill */
587 if (insertmix)
588 {
589 if (prevline == NULL)
590 {
591 line[x * 3] = mix[0];
592 line[x * 3 + 1] = mix[1];
593 line[x * 3 + 2] = mix[2];
594 }
595 else
596 {
597 line[x * 3] =
598 prevline[x * 3] ^ mix[0];
599 line[x * 3 + 1] =
600 prevline[x * 3 + 1] ^ mix[1];
601 line[x * 3 + 2] =
602 prevline[x * 3 + 2] ^ mix[2];
603 }
604 insertmix = False;
605 count--;
606 x++;
607 }
608 if (prevline == NULL)
609 {
610 REPEAT
611 (
612 line[x * 3] = 0;
613 line[x * 3 + 1] = 0;
614 line[x * 3 + 2] = 0;
615 )
616 }
617 else
618 {
619 REPEAT
620 (
621 line[x * 3] = prevline[x * 3];
622 line[x * 3 + 1] = prevline[x * 3 + 1];
623 line[x * 3 + 2] = prevline[x * 3 + 2];
624 )
625 }
626 break;
627 case 1: /* Mix */
628 if (prevline == NULL)
629 {
630 REPEAT
631 (
632 line[x * 3] = mix[0];
633 line[x * 3 + 1] = mix[1];
634 line[x * 3 + 2] = mix[2];
635 )
636 }
637 else
638 {
639 REPEAT
640 (
641 line[x * 3] =
642 prevline[x * 3] ^ mix[0];
643 line[x * 3 + 1] =
644 prevline[x * 3 + 1] ^ mix[1];
645 line[x * 3 + 2] =
646 prevline[x * 3 + 2] ^ mix[2];
647 )
648 }
649 break;
650 case 2: /* Fill or Mix */
651 if (prevline == NULL)
652 {
653 REPEAT
654 (
655 MASK_UPDATE();
656 if (mask & mixmask)
657 {
658 line[x * 3] = mix[0];
659 line[x * 3 + 1] = mix[1];
660 line[x * 3 + 2] = mix[2];
661 }
662 else
663 {
664 line[x * 3] = 0;
665 line[x * 3 + 1] = 0;
666 line[x * 3 + 2] = 0;
667 }
668 )
669 }
670 else
671 {
672 REPEAT
673 (
674 MASK_UPDATE();
675 if (mask & mixmask)
676 {
677 line[x * 3] =
678 prevline[x * 3] ^ mix [0];
679 line[x * 3 + 1] =
680 prevline[x * 3 + 1] ^ mix [1];
681 line[x * 3 + 2] =
682 prevline[x * 3 + 2] ^ mix [2];
683 }
684 else
685 {
686 line[x * 3] =
687 prevline[x * 3];
688 line[x * 3 + 1] =
689 prevline[x * 3 + 1];
690 line[x * 3 + 2] =
691 prevline[x * 3 + 2];
692 }
693 )
694 }
695 break;
696 case 3: /* Colour */
697 REPEAT
698 (
699 line[x * 3] = colour2 [0];
700 line[x * 3 + 1] = colour2 [1];
701 line[x * 3 + 2] = colour2 [2];
702 )
703 break;
704 case 4: /* Copy */
705 REPEAT
706 (
707 line[x * 3] = CVAL(input);
708 line[x * 3 + 1] = CVAL(input);
709 line[x * 3 + 2] = CVAL(input);
710 )
711 break;
712 case 8: /* Bicolour */
713 REPEAT
714 (
715 if (bicolour)
716 {
717 line[x * 3] = colour2[0];
718 line[x * 3 + 1] = colour2[1];
719 line[x * 3 + 2] = colour2[2];
720 bicolour = False;
721 }
722 else
723 {
724 line[x * 3] = colour1[0];
725 line[x * 3 + 1] = colour1[1];
726 line[x * 3 + 2] = colour1[2];
727 bicolour = True;
728 count++;
729 }
730 )
731 break;
732 case 0xd: /* White */
733 REPEAT
734 (
735 line[x * 3] = 0xff;
736 line[x * 3 + 1] = 0xff;
737 line[x * 3 + 2] = 0xff;
738 )
739 break;
740 case 0xe: /* Black */
741 REPEAT
742 (
743 line[x * 3] = 0;
744 line[x * 3 + 1] = 0;
745 line[x * 3 + 2] = 0;
746 )
747 break;
748 default:
749 unimpl("bitmap opcode 0x%x\n", opcode);
750 return False;
751 }
752 }
753 }
754 return True;
755}
756
757/* decompress a colour plane */
758static int
759process_plane(uint8 * in, int width, int height, uint8 * out, int size)
760{
761 int indexw;
762 int indexh;
763 int code;
764 int collen;
765 int replen;
766 int color;
767 int x;
768 int revcode;
769 uint8 * last_line;
770 uint8 * this_line;
771 uint8 * org_in;
772 uint8 * org_out;
773
774 org_in = in;
775 org_out = out;
776 last_line = 0;
777 indexh = 0;
778 while (indexh < height)
779 {
780 out = (org_out + width * height * 4) - ((indexh + 1) * width * 4);
781 color = 0;
782 this_line = out;
783 indexw = 0;
784 if (last_line == 0)
785 {
786 while (indexw < width)
787 {
788 code = CVAL(in);
789 replen = code & 0xf;
790 collen = (code >> 4) & 0xf;
791 revcode = (replen << 4) | collen;
792 if ((revcode <= 47) && (revcode >= 16))
793 {
794 replen = revcode;
795 collen = 0;
796 }
797 while (indexw < width && collen > 0)
798 {
799 color = CVAL(in);
800 *out = color;
801 out += 4;
802 indexw++;
803 collen--;
804 }
805 while (indexw < width && replen > 0)
806 {
807 *out = color;
808 out += 4;
809 indexw++;
810 replen--;
811 }
812 }
813 }
814 else
815 {
816 while (indexw < width)
817 {
818 code = CVAL(in);
819 replen = code & 0xf;
820 collen = (code >> 4) & 0xf;
821 revcode = (replen << 4) | collen;
822 if ((revcode <= 47) && (revcode >= 16))
823 {
824 replen = revcode;
825 collen = 0;
826 }
827 while (indexw < width && collen > 0)
828 {
829 x = CVAL(in);
830 if (x & 1)
831 {
832 x = x >> 1;
833 x = x + 1;
834 color = -x;
835 }
836 else
837 {
838 x = x >> 1;
839 color = x;
840 }
841 x = last_line[indexw * 4] + color;
842 *out = x;
843 out += 4;
844 indexw++;
845 collen--;
846 }
847 while (indexw < width && replen > 0)
848 {
849 x = last_line[indexw * 4] + color;
850 *out = x;
851 out += 4;
852 indexw++;
853 replen--;
854 }
855 }
856 }
857 indexh++;
858 last_line = this_line;
859 }
860 return (int) (in - org_in);
861}
862
863/* 4 byte bitmap decompress */
864static RD_BOOL
865bitmap_decompress4(uint8 * output, int width, int height, uint8 * input, int size)
866{
867 int code;
868 int bytes_pro;
869 int total_pro;
870
871 code = CVAL(input);
872 if (code != 0x10)
873 {
874 return False;
875 }
876 total_pro = 1;
877 bytes_pro = process_plane(input, width, height, output + 3, size - total_pro);
878 total_pro += bytes_pro;
879 input += bytes_pro;
880 bytes_pro = process_plane(input, width, height, output + 2, size - total_pro);
881 total_pro += bytes_pro;
882 input += bytes_pro;
883 bytes_pro = process_plane(input, width, height, output + 1, size - total_pro);
884 total_pro += bytes_pro;
885 input += bytes_pro;
886 bytes_pro = process_plane(input, width, height, output + 0, size - total_pro);
887 total_pro += bytes_pro;
888 return size == total_pro;
889}
890
891/* main decompress function */
892RD_BOOL
893bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp)
894{
895 RD_BOOL rv = False;
896
897 switch (Bpp)
898 {
899 case 1:
900 rv = bitmap_decompress1(output, width, height, input, size);
901 break;
902 case 2:
903 rv = bitmap_decompress2(output, width, height, input, size);
904 break;
905 case 3:
906 rv = bitmap_decompress3(output, width, height, input, size);
907 break;
908 case 4:
909 rv = bitmap_decompress4(output, width, height, input, size);
910 break;
911 default:
912 unimpl("Bpp %d\n", Bpp);
913 break;
914 }
915 return rv;
916}
917
918/* *INDENT-ON* */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette