20#include <winpr/assert.h>
21#include <winpr/cast.h>
23#include <freerdp/config.h>
25#include <freerdp/codec/bitmap.h>
26#include <freerdp/codec/planar.h>
30 ALIGN64 UINT16 bicolor_count;
31 ALIGN64 UINT16 fill_count;
32 ALIGN64 UINT16 color_count;
33 ALIGN64 UINT16 mix_count;
34 ALIGN64 UINT16 fom_count;
35 ALIGN64
size_t fom_mask_len;
36 ALIGN64 BOOL bicolor_spin;
39static inline void reset_counts(
struct count* counts)
41 const struct count empty = WINPR_C_ARRAY_INIT;
46static inline UINT16 GETPIXEL16(
const void* WINPR_RESTRICT d, UINT32 x, UINT32 y, UINT32 w)
48 const BYTE* WINPR_RESTRICT src = (
const BYTE*)d + ((y * w + x) *
sizeof(UINT16));
49 return WINPR_ASSERTING_INT_CAST(UINT16, ((UINT16)src[1] << 8) | (UINT16)src[0]);
52static inline UINT32 GETPIXEL32(
const void* WINPR_RESTRICT d, UINT32 x, UINT32 y, UINT32 w)
54 const BYTE* WINPR_RESTRICT src = (
const BYTE*)d + ((y * w + x) *
sizeof(UINT32));
55 return (((UINT32)src[3]) << 24) | (((UINT32)src[2]) << 16) | (((UINT32)src[1]) << 8) |
60static inline UINT16 IN_PIXEL16(
const void* WINPR_RESTRICT in_ptr, UINT32 in_x, UINT32 in_y,
61 UINT32 in_w, UINT16 in_last_pixel)
63 if (in_ptr ==
nullptr)
66 return GETPIXEL16(in_ptr, in_x, in_y, in_w);
72static inline UINT32 IN_PIXEL32(
const void* WINPR_RESTRICT in_ptr, UINT32 in_x, UINT32 in_y,
73 UINT32 in_w, UINT32 in_last_pixel)
75 if (in_ptr ==
nullptr)
78 return GETPIXEL32(in_ptr, in_x, in_y, in_w);
85static inline UINT16 out_color_count_2(UINT16 in_count,
wStream* WINPR_RESTRICT in_s,
92 const BYTE temp = ((0x3u << 5) | in_count) & 0xFF;
93 Stream_Write_UINT8(in_s, temp);
95 else if (in_count < 256 + 32)
97 const BYTE temp = (in_count - 32) & 0xFF;
98 Stream_Write_UINT8(in_s, 0x60);
99 Stream_Write_UINT8(in_s, temp);
103 Stream_Write_UINT8(in_s, 0xf3);
104 Stream_Write_UINT16(in_s, in_count);
107 Stream_Write_UINT16(in_s, in_data);
115static inline UINT16 out_color_count_3(UINT16 in_count,
wStream* WINPR_RESTRICT in_s,
122 const BYTE temp = ((0x3u << 5) | in_count) & 0xFF;
123 Stream_Write_UINT8(in_s, temp);
125 else if (in_count < 256 + 32)
127 const BYTE temp = (in_count - 32) & 0xFF;
128 Stream_Write_UINT8(in_s, 0x60);
129 Stream_Write_UINT8(in_s, temp);
133 Stream_Write_UINT8(in_s, 0xf3);
134 Stream_Write_UINT16(in_s, in_count);
137 Stream_Write_UINT8(in_s, in_data & 0xFF);
139 Stream_Write_UINT8(in_s, (in_data >> 8) & 0xFF);
140 Stream_Write_UINT8(in_s, (in_data >> 16) & 0xFF);
148static inline UINT16 out_copy_count_2(UINT16 in_count,
wStream* WINPR_RESTRICT in_s,
149 wStream* WINPR_RESTRICT in_data)
156 const BYTE temp = ((0x4u << 5) | in_count) & 0xFF;
157 Stream_Write_UINT8(in_s, temp);
159 else if (in_count < 256 + 32)
161 const BYTE temp = (in_count - 32) & 0xFF;
162 Stream_Write_UINT8(in_s, 0x80);
163 Stream_Write_UINT8(in_s, temp);
167 Stream_Write_UINT8(in_s, 0xf4);
168 Stream_Write_UINT16(in_s, in_count);
171 Stream_Write(in_s, Stream_Buffer(in_data), 2ULL * in_count);
174 Stream_ResetPosition(in_data);
180static inline UINT16 out_copy_count_3(UINT16 in_count,
wStream* WINPR_RESTRICT in_s,
181 wStream* WINPR_RESTRICT in_data)
187 const BYTE temp = ((0x4u << 5) | in_count) & 0xFF;
188 Stream_Write_UINT8(in_s, temp);
190 else if (in_count < 256 + 32)
192 const BYTE temp = (in_count - 32) & 0xFF;
193 Stream_Write_UINT8(in_s, 0x80);
194 Stream_Write_UINT8(in_s, temp);
198 Stream_Write_UINT8(in_s, 0xf4);
199 Stream_Write_UINT16(in_s, in_count);
202 Stream_Write(in_s, Stream_Pointer(in_data), 3ULL * in_count);
205 Stream_ResetPosition(in_data);
211static inline UINT16 out_bicolor_count_2(UINT16 in_count,
wStream* WINPR_RESTRICT in_s,
212 UINT16 in_color1, UINT16 in_color2)
216 if (in_count / 2 < 16)
218 const BYTE temp = ((0xe << 4) | (in_count / 2)) & 0xFF;
219 Stream_Write_UINT8(in_s, temp);
221 else if (in_count / 2 < 256 + 16)
223 const BYTE temp = (in_count / 2 - 16) & 0xFF;
224 Stream_Write_UINT8(in_s, 0xe0);
225 Stream_Write_UINT8(in_s, temp);
229 Stream_Write_UINT8(in_s, 0xf8);
230 Stream_Write_UINT16(in_s, in_count / 2);
233 Stream_Write_UINT16(in_s, in_color1);
234 Stream_Write_UINT16(in_s, in_color2);
242static inline UINT16 out_bicolor_count_3(UINT16 in_count,
wStream* WINPR_RESTRICT in_s,
243 UINT32 in_color1, UINT32 in_color2)
247 if (in_count / 2 < 16)
249 const BYTE temp = ((0xe << 4) | (in_count / 2)) & 0xFF;
250 Stream_Write_UINT8(in_s, temp);
252 else if (in_count / 2 < 256 + 16)
254 const BYTE temp = (in_count / 2 - 16) & 0xFF;
255 Stream_Write_UINT8(in_s, 0xe0);
256 Stream_Write_UINT8(in_s, temp);
260 Stream_Write_UINT8(in_s, 0xf8);
261 Stream_Write_UINT16(in_s, in_count / 2);
264 Stream_Write_UINT8(in_s, in_color1 & 0xFF);
265 Stream_Write_UINT8(in_s, (in_color1 >> 8) & 0xFF);
266 Stream_Write_UINT8(in_s, (in_color1 >> 16) & 0xFF);
267 Stream_Write_UINT8(in_s, in_color2 & 0xFF);
268 Stream_Write_UINT8(in_s, (in_color2 >> 8) & 0xFF);
269 Stream_Write_UINT8(in_s, (in_color2 >> 16) & 0xFF);
277static inline UINT16 out_fill_count_2(UINT16 in_count,
wStream* WINPR_RESTRICT in_s)
283 Stream_Write_UINT8(in_s, in_count & 0xFF);
285 else if (in_count < 256 + 32)
287 const BYTE temp = (in_count - 32) & 0xFF;
288 Stream_Write_UINT8(in_s, 0x0);
289 Stream_Write_UINT8(in_s, temp);
293 Stream_Write_UINT8(in_s, 0xf0);
294 Stream_Write_UINT16(in_s, in_count);
303static inline UINT16 out_fill_count_3(UINT16 in_count,
wStream* WINPR_RESTRICT in_s)
309 Stream_Write_UINT8(in_s, in_count & 0xFF);
311 else if (in_count < 256 + 32)
313 const BYTE temp = (in_count - 32) & 0xFF;
314 Stream_Write_UINT8(in_s, 0x0);
315 Stream_Write_UINT8(in_s, temp);
319 Stream_Write_UINT8(in_s, 0xf0);
320 Stream_Write_UINT16(in_s, in_count);
329static inline UINT16 out_counts_mix_count_2(UINT16 in_count,
wStream* WINPR_RESTRICT in_s)
335 const BYTE temp = ((0x1u << 5) | in_count) & 0xFF;
336 Stream_Write_UINT8(in_s, temp);
338 else if (in_count < 256 + 32)
340 const BYTE temp = (in_count - 32) & 0xFF;
341 Stream_Write_UINT8(in_s, 0x20);
342 Stream_Write_UINT8(in_s, temp);
346 Stream_Write_UINT8(in_s, 0xf1);
347 Stream_Write_UINT16(in_s, in_count);
356static inline UINT16 out_counts_mix_count_3(UINT16 in_count,
wStream* WINPR_RESTRICT in_s)
362 const BYTE temp = ((0x1u << 5) | in_count) & 0xFF;
363 Stream_Write_UINT8(in_s, temp);
365 else if (in_count < 256 + 32)
367 const BYTE temp = (in_count - 32) & 0xFF;
368 Stream_Write_UINT8(in_s, 0x20);
369 Stream_Write_UINT8(in_s, temp);
373 Stream_Write_UINT8(in_s, 0xf1);
374 Stream_Write_UINT16(in_s, in_count);
383static inline UINT16 out_from_count_2(UINT16 in_count,
wStream* WINPR_RESTRICT in_s,
384 const uint8_t* WINPR_RESTRICT in_mask,
size_t in_mask_len)
388 if ((in_count % 8) == 0 && in_count < 249)
390 const BYTE temp = ((0x2u << 5) | (in_count / 8)) & 0xFF;
391 Stream_Write_UINT8(in_s, temp);
393 else if (in_count < 256)
395 const BYTE temp = (in_count - 1) & 0xFF;
396 Stream_Write_UINT8(in_s, 0x40);
397 Stream_Write_UINT8(in_s, temp);
401 Stream_Write_UINT8(in_s, 0xf2);
402 Stream_Write_UINT16(in_s, in_count);
405 Stream_Write(in_s, in_mask, in_mask_len);
413static inline UINT16 out_from_count_3(UINT16 in_count,
wStream* WINPR_RESTRICT in_s,
414 const uint8_t* WINPR_RESTRICT in_mask,
size_t in_mask_len)
418 if ((in_count % 8) == 0 && in_count < 249)
420 const BYTE temp = ((0x2u << 5) | (in_count / 8)) & 0xFF;
421 Stream_Write_UINT8(in_s, temp);
423 else if (in_count < 256)
425 const BYTE temp = (in_count - 1) & 0xFF;
426 Stream_Write_UINT8(in_s, 0x40);
427 Stream_Write_UINT8(in_s, temp);
431 Stream_Write_UINT8(in_s, 0xf2);
432 Stream_Write_UINT16(in_s, in_count);
435 Stream_Write(in_s, in_mask, in_mask_len);
441#define TEST_FILL ((last_line == 0 && pixel == 0) || (last_line != 0 && pixel == ypixel))
442#define TEST_MIX ((last_line == 0 && pixel == mix) || (last_line != 0 && pixel == (ypixel ^ mix)))
443#define TEST_FOM TEST_FILL || TEST_MIX
444#define TEST_COLOR pixel == last_pixel
446#define test_bicolor(counts) \
447 ((pixel != last_pixel) && \
448 ((!(counts)->bicolor_spin && (pixel == bicolor1) && (last_pixel == bicolor2)) || \
449 ((counts)->bicolor_spin && (pixel == bicolor2) && (last_pixel == bicolor1))))
451static inline SSIZE_T freerdp_bitmap_compress_24(
const void* WINPR_RESTRICT srcData, UINT32 width,
452 WINPR_ATTR_UNUSED UINT32 height,
453 wStream* WINPR_RESTRICT s, UINT32 byte_limit,
454 UINT32 sline,
wStream* WINPR_RESTRICT temp_s,
457 uint8_t fom_mask[8192] = WINPR_C_ARRAY_INIT;
458 SSIZE_T lines_sent = 0;
460 UINT32 last_pixel = 0;
461 UINT32 last_ypixel = 0;
462 struct count counts = WINPR_C_ARRAY_INIT;
465 UINT32 end = width + e;
466 UINT32 out_count = end * 3;
467 const UINT32 mix = 0xFFFFFF;
468 const char* start = (
const char*)srcData;
471 const char* last_line =
nullptr;
473 INT64 start_line = sline;
474 while ((start_line >= 0) && (out_count < 32768))
476 const char* line = &start[4ULL * width * WINPR_ASSERTING_INT_CAST(
size_t, start_line)];
477 size_t i = Stream_GetPosition(s) + 3ULL * count;
479 if ((i - (3ULL * counts.color_count) >= byte_limit) &&
480 (i - (3ULL * counts.bicolor_count) >= byte_limit) &&
481 (i - (3ULL * counts.fill_count) >= byte_limit) &&
482 (i - (3ULL * counts.mix_count) >= byte_limit) &&
483 (i - (3ULL * counts.fom_count) >= byte_limit))
488 out_count += end * 3;
490 for (UINT32 j = 0; j < end; j++)
493 const UINT32 pixel = IN_PIXEL32(line, j, 0, width, last_pixel);
494 const UINT32 ypixel = IN_PIXEL32(last_line, j, 0, width, last_ypixel);
498 if (counts.fill_count > 3 && counts.fill_count >= counts.color_count &&
499 counts.fill_count >= counts.bicolor_count &&
500 counts.fill_count >= counts.mix_count && counts.fill_count >= counts.fom_count)
502 if (counts.fill_count > count)
505 count -= counts.fill_count;
506 count = out_copy_count_3(count, s, temp_s);
507 counts.fill_count = out_fill_count_3(counts.fill_count, s);
508 reset_counts(&counts);
511 counts.fill_count = 0;
516 if (counts.mix_count > 3 && counts.mix_count >= counts.fill_count &&
517 counts.mix_count >= counts.bicolor_count &&
518 counts.mix_count >= counts.color_count && counts.mix_count >= counts.fom_count)
520 if (counts.mix_count > count)
523 count -= counts.mix_count;
524 count = out_copy_count_3(count, s, temp_s);
525 counts.mix_count = out_counts_mix_count_3(counts.mix_count, s);
526 reset_counts(&counts);
529 counts.mix_count = 0;
534 if (counts.color_count > 3 && counts.color_count >= counts.fill_count &&
535 counts.color_count >= counts.bicolor_count &&
536 counts.color_count >= counts.mix_count &&
537 counts.color_count >= counts.fom_count)
539 if (counts.color_count > count)
542 count -= counts.color_count;
543 count = out_copy_count_3(count, s, temp_s);
544 counts.color_count = out_color_count_3(counts.color_count, s, last_pixel);
545 reset_counts(&counts);
548 counts.color_count = 0;
551 if (!test_bicolor(&counts))
553 if (counts.bicolor_count > 3 && counts.bicolor_count >= counts.fill_count &&
554 counts.bicolor_count >= counts.color_count &&
555 counts.bicolor_count >= counts.mix_count &&
556 counts.bicolor_count >= counts.fom_count)
558 if ((counts.bicolor_count % 2) != 0)
559 counts.bicolor_count--;
561 if (counts.bicolor_count > count)
564 count -= counts.bicolor_count;
565 count = out_copy_count_3(count, s, temp_s);
566 counts.bicolor_count =
567 out_bicolor_count_3(counts.bicolor_count, s, bicolor2, bicolor1);
568 reset_counts(&counts);
571 counts.bicolor_count = 0;
572 bicolor1 = last_pixel;
574 counts.bicolor_spin = FALSE;
579 if (counts.fom_count > 3 && counts.fom_count >= counts.fill_count &&
580 counts.fom_count >= counts.color_count &&
581 counts.fom_count >= counts.mix_count &&
582 counts.fom_count >= counts.bicolor_count)
584 if (counts.fom_count > count)
587 count -= counts.fom_count;
588 count = out_copy_count_3(count, s, temp_s);
590 out_from_count_3(counts.fom_count, s, fom_mask, counts.fom_mask_len);
591 reset_counts(&counts);
594 counts.fom_count = 0;
595 counts.fom_mask_len = 0;
610 counts.color_count++;
613 if (test_bicolor(&counts))
615 counts.bicolor_spin = !counts.bicolor_spin;
616 counts.bicolor_count++;
621 if ((counts.fom_count % 8) == 0)
623 fom_mask[counts.fom_mask_len] = 0;
624 counts.fom_mask_len++;
627 if (pixel == (ypixel ^ mix))
629 const uint8_t tmp = (1u << (counts.fom_count % 8)) & 0xFF;
630 const uint8_t val = fom_mask[counts.fom_mask_len - 1] | tmp;
631 fom_mask[counts.fom_mask_len - 1] = val;
637 Stream_Write_UINT8(temp_s, pixel & 0xff);
638 Stream_Write_UINT8(temp_s, (pixel >> 8) & 0xff);
639 Stream_Write_UINT8(temp_s, (pixel >> 16) & 0xff);
642 last_ypixel = ypixel;
646 if (last_line ==
nullptr)
648 if (counts.fill_count > 3 && counts.fill_count >= counts.color_count &&
649 counts.fill_count >= counts.bicolor_count &&
650 counts.fill_count >= counts.mix_count && counts.fill_count >= counts.fom_count)
652 if (counts.fill_count > count)
655 count -= counts.fill_count;
656 count = out_copy_count_3(count, s, temp_s);
657 counts.fill_count = out_fill_count_3(counts.fill_count, s);
658 reset_counts(&counts);
661 counts.fill_count = 0;
663 if (counts.mix_count > 3 && counts.mix_count >= counts.fill_count &&
664 counts.mix_count >= counts.bicolor_count &&
665 counts.mix_count >= counts.color_count && counts.mix_count >= counts.fom_count)
667 if (counts.mix_count > count)
670 count -= counts.mix_count;
671 count = out_copy_count_3(count, s, temp_s);
672 counts.mix_count = out_counts_mix_count_3(counts.mix_count, s);
673 reset_counts(&counts);
676 counts.mix_count = 0;
678 if (counts.fom_count > 3 && counts.fom_count >= counts.fill_count &&
679 counts.fom_count >= counts.color_count && counts.fom_count >= counts.mix_count &&
680 counts.fom_count >= counts.bicolor_count)
682 if (counts.fom_count > count)
685 count -= counts.fom_count;
686 count = out_copy_count_3(count, s, temp_s);
688 out_from_count_3(counts.fom_count, s, fom_mask, counts.fom_mask_len);
689 reset_counts(&counts);
692 counts.fom_count = 0;
693 counts.fom_mask_len = 0;
702 Stream_ResetPosition(temp_s);
704 if (counts.fill_count > 3 && counts.fill_count >= counts.color_count &&
705 counts.fill_count >= counts.bicolor_count && counts.fill_count >= counts.mix_count &&
706 counts.fill_count >= counts.fom_count)
708 if (counts.fill_count > count)
711 count -= counts.fill_count;
712 (void)out_copy_count_3(count, s, temp_s);
713 counts.fill_count = out_fill_count_3(counts.fill_count, s);
715 else if (counts.mix_count > 3 && counts.mix_count >= counts.color_count &&
716 counts.mix_count >= counts.bicolor_count && counts.mix_count >= counts.fill_count &&
717 counts.mix_count >= counts.fom_count)
719 if (counts.mix_count > count)
722 count -= counts.mix_count;
723 (void)out_copy_count_3(count, s, temp_s);
724 counts.mix_count = out_counts_mix_count_3(counts.mix_count, s);
726 else if (counts.color_count > 3 && counts.color_count >= counts.mix_count &&
727 counts.color_count >= counts.bicolor_count &&
728 counts.color_count >= counts.fill_count && counts.color_count >= counts.fom_count)
730 if (counts.color_count > count)
733 count -= counts.color_count;
734 (void)out_copy_count_3(count, s, temp_s);
735 counts.color_count = out_color_count_3(counts.color_count, s, last_pixel);
737 else if (counts.bicolor_count > 3 && counts.bicolor_count >= counts.mix_count &&
738 counts.bicolor_count >= counts.color_count &&
739 counts.bicolor_count >= counts.fill_count && counts.bicolor_count >= counts.fom_count)
741 if ((counts.bicolor_count % 2) != 0)
742 counts.bicolor_count--;
744 if (counts.bicolor_count > count)
747 count -= counts.bicolor_count;
748 count = out_copy_count_3(count, s, temp_s);
749 counts.bicolor_count = out_bicolor_count_3(counts.bicolor_count, s, bicolor2, bicolor1);
751 if (counts.bicolor_count > count)
754 count -= counts.bicolor_count;
755 (void)out_copy_count_3(count, s, temp_s);
756 counts.bicolor_count = out_bicolor_count_3(counts.bicolor_count, s, bicolor1, bicolor2);
758 else if (counts.fom_count > 3 && counts.fom_count >= counts.mix_count &&
759 counts.fom_count >= counts.color_count && counts.fom_count >= counts.fill_count &&
760 counts.fom_count >= counts.bicolor_count)
762 if (counts.fom_count > count)
765 count -= counts.fom_count;
766 (void)out_copy_count_3(count, s, temp_s);
767 counts.fom_count = out_from_count_3(counts.fom_count, s, fom_mask, counts.fom_mask_len);
771 (void)out_copy_count_3(count, s, temp_s);
777static inline SSIZE_T freerdp_bitmap_compress_16(
const void* WINPR_RESTRICT srcData, UINT32 width,
778 WINPR_ATTR_UNUSED UINT32 height,
779 wStream* WINPR_RESTRICT s, UINT32 bpp,
780 UINT32 byte_limit, UINT32 sline,
781 wStream* WINPR_RESTRICT temp_s, UINT32 e)
783 uint8_t fom_mask[8192] = WINPR_C_ARRAY_INIT;
784 SSIZE_T lines_sent = 0;
786 UINT16 last_pixel = 0;
787 UINT16 last_ypixel = 0;
788 struct count counts = WINPR_C_ARRAY_INIT;
791 UINT32 end = width + e;
792 UINT32 out_count = end * 2;
793 const UINT32 mix = (bpp == 15) ? 0xBA1F : 0xFFFF;
794 const char* start = (
const char*)srcData;
798 const char* last_line =
nullptr;
800 INT64 start_line = sline;
801 while ((start_line >= 0) && (out_count < 32768))
803 const char* line = &start[2ULL * width * WINPR_ASSERTING_INT_CAST(
size_t, start_line)];
804 size_t i = Stream_GetPosition(s) + 2ULL * count;
806 if ((i - (2ULL * counts.color_count) >= byte_limit) &&
807 (i - (2ULL * counts.bicolor_count) >= byte_limit) &&
808 (i - (2ULL * counts.fill_count) >= byte_limit) &&
809 (i - (2ULL * counts.mix_count) >= byte_limit) &&
810 (i - (2ULL * counts.fom_count) >= byte_limit))
815 out_count += end * 2;
817 for (UINT32 j = 0; j < end; j++)
820 const UINT16 pixel = IN_PIXEL16(line, j, 0, width, last_pixel);
821 const UINT16 ypixel = IN_PIXEL16(last_line, j, 0, width, last_ypixel);
825 if (counts.fill_count > 3 && counts.fill_count >= counts.color_count &&
826 counts.fill_count >= counts.bicolor_count &&
827 counts.fill_count >= counts.mix_count && counts.fill_count >= counts.fom_count)
829 if (counts.fill_count > count)
832 count -= counts.fill_count;
833 count = out_copy_count_2(count, s, temp_s);
834 counts.fill_count = out_fill_count_2(counts.fill_count, s);
835 reset_counts(&counts);
838 counts.fill_count = 0;
843 if (counts.mix_count > 3 && counts.mix_count >= counts.fill_count &&
844 counts.mix_count >= counts.bicolor_count &&
845 counts.mix_count >= counts.color_count && counts.mix_count >= counts.fom_count)
847 if (counts.mix_count > count)
850 count -= counts.mix_count;
851 count = out_copy_count_2(count, s, temp_s);
852 counts.mix_count = out_counts_mix_count_2(counts.mix_count, s);
853 reset_counts(&counts);
856 counts.mix_count = 0;
861 if (counts.color_count > 3 && counts.color_count >= counts.fill_count &&
862 counts.color_count >= counts.bicolor_count &&
863 counts.color_count >= counts.mix_count &&
864 counts.color_count >= counts.fom_count)
866 if (counts.color_count > count)
869 count -= counts.color_count;
870 count = out_copy_count_2(count, s, temp_s);
871 counts.color_count = out_color_count_2(counts.color_count, s, last_pixel);
872 reset_counts(&counts);
875 counts.color_count = 0;
878 if (!test_bicolor(&counts))
880 if ((counts.bicolor_count > 3) && (counts.bicolor_count >= counts.fill_count) &&
881 (counts.bicolor_count >= counts.color_count) &&
882 (counts.bicolor_count >= counts.mix_count) &&
883 (counts.bicolor_count >= counts.fom_count))
885 if ((counts.bicolor_count % 2) != 0)
886 counts.bicolor_count--;
888 if (counts.bicolor_count > count)
891 count -= counts.bicolor_count;
892 count = out_copy_count_2(count, s, temp_s);
893 counts.bicolor_count =
894 out_bicolor_count_2(counts.bicolor_count, s, bicolor2, bicolor1);
895 reset_counts(&counts);
898 counts.bicolor_count = 0;
899 bicolor1 = last_pixel;
901 counts.bicolor_spin = FALSE;
906 if (counts.fom_count > 3 && counts.fom_count >= counts.fill_count &&
907 counts.fom_count >= counts.color_count &&
908 counts.fom_count >= counts.mix_count &&
909 counts.fom_count >= counts.bicolor_count)
911 if (counts.fom_count > count)
914 count -= counts.fom_count;
915 count = out_copy_count_2(count, s, temp_s);
917 out_from_count_2(counts.fom_count, s, fom_mask, counts.fom_mask_len);
918 reset_counts(&counts);
921 counts.fom_count = 0;
922 counts.fom_mask_len = 0;
937 counts.color_count++;
940 if (test_bicolor(&counts))
942 counts.bicolor_spin = !counts.bicolor_spin;
943 counts.bicolor_count++;
948 if ((counts.fom_count % 8) == 0)
950 fom_mask[counts.fom_mask_len] = 0;
951 counts.fom_mask_len++;
954 if (pixel == (ypixel ^ mix))
956 const uint8_t tmp = (1u << (counts.fom_count % 8)) & 0xFF;
957 const uint8_t val = fom_mask[counts.fom_mask_len - 1] | tmp;
958 fom_mask[counts.fom_mask_len - 1] = val;
964 Stream_Write_UINT16(temp_s, pixel);
967 last_ypixel = ypixel;
971 if (last_line ==
nullptr)
973 if (counts.fill_count > 3 && counts.fill_count >= counts.color_count &&
974 counts.fill_count >= counts.bicolor_count &&
975 counts.fill_count >= counts.mix_count && counts.fill_count >= counts.fom_count)
977 if (counts.fill_count > count)
980 count -= counts.fill_count;
981 count = out_copy_count_2(count, s, temp_s);
982 counts.fill_count = out_fill_count_2(counts.fill_count, s);
983 reset_counts(&counts);
986 counts.fill_count = 0;
988 if (counts.mix_count > 3 && counts.mix_count >= counts.fill_count &&
989 counts.mix_count >= counts.bicolor_count &&
990 counts.mix_count >= counts.color_count && counts.mix_count >= counts.fom_count)
992 if (counts.mix_count > count)
995 count -= counts.mix_count;
996 count = out_copy_count_2(count, s, temp_s);
997 counts.mix_count = out_counts_mix_count_2(counts.mix_count, s);
998 reset_counts(&counts);
1001 counts.mix_count = 0;
1003 if (counts.fom_count > 3 && counts.fom_count >= counts.fill_count &&
1004 counts.fom_count >= counts.color_count && counts.fom_count >= counts.mix_count &&
1005 counts.fom_count >= counts.bicolor_count)
1007 if (counts.fom_count > count)
1010 count -= counts.fom_count;
1011 count = out_copy_count_2(count, s, temp_s);
1013 out_from_count_2(counts.fom_count, s, fom_mask, counts.fom_mask_len);
1014 reset_counts(&counts);
1017 counts.fom_count = 0;
1018 counts.fom_mask_len = 0;
1027 Stream_ResetPosition(temp_s);
1029 if (counts.fill_count > 3 && counts.fill_count >= counts.color_count &&
1030 counts.fill_count >= counts.bicolor_count && counts.fill_count >= counts.mix_count &&
1031 counts.fill_count >= counts.fom_count)
1033 if (counts.fill_count > count)
1036 count -= counts.fill_count;
1037 (void)out_copy_count_2(count, s, temp_s);
1038 counts.fill_count = out_fill_count_2(counts.fill_count, s);
1040 else if (counts.mix_count > 3 && counts.mix_count >= counts.color_count &&
1041 counts.mix_count >= counts.bicolor_count && counts.mix_count >= counts.fill_count &&
1042 counts.mix_count >= counts.fom_count)
1044 if (counts.mix_count > count)
1047 count -= counts.mix_count;
1048 (void)out_copy_count_2(count, s, temp_s);
1049 counts.mix_count = out_counts_mix_count_2(counts.mix_count, s);
1051 else if (counts.color_count > 3 && counts.color_count >= counts.mix_count &&
1052 counts.color_count >= counts.bicolor_count &&
1053 counts.color_count >= counts.fill_count && counts.color_count >= counts.fom_count)
1055 if (counts.color_count > count)
1058 count -= counts.color_count;
1059 (void)out_copy_count_2(count, s, temp_s);
1060 counts.color_count = out_color_count_2(counts.color_count, s, last_pixel);
1062 else if (counts.bicolor_count > 3 && counts.bicolor_count >= counts.mix_count &&
1063 counts.bicolor_count >= counts.color_count &&
1064 counts.bicolor_count >= counts.fill_count && counts.bicolor_count >= counts.fom_count)
1066 if ((counts.bicolor_count % 2) != 0)
1067 counts.bicolor_count--;
1069 if (counts.bicolor_count > count)
1072 count -= counts.bicolor_count;
1073 count = out_copy_count_2(count, s, temp_s);
1074 counts.bicolor_count = out_bicolor_count_2(counts.bicolor_count, s, bicolor2, bicolor1);
1076 if (counts.bicolor_count > count)
1079 count -= counts.bicolor_count;
1080 (void)out_copy_count_2(count, s, temp_s);
1081 counts.bicolor_count = out_bicolor_count_2(counts.bicolor_count, s, bicolor1, bicolor2);
1083 else if (counts.fom_count > 3 && counts.fom_count >= counts.mix_count &&
1084 counts.fom_count >= counts.color_count && counts.fom_count >= counts.fill_count &&
1085 counts.fom_count >= counts.bicolor_count)
1087 if (counts.fom_count > count)
1090 count -= counts.fom_count;
1091 (void)out_copy_count_2(count, s, temp_s);
1092 counts.fom_count = out_from_count_2(counts.fom_count, s, fom_mask, counts.fom_mask_len);
1096 (void)out_copy_count_2(count, s, temp_s);
1102SSIZE_T freerdp_bitmap_compress(
const void* WINPR_RESTRICT srcData, UINT32 width, UINT32 height,
1103 wStream* WINPR_RESTRICT s, UINT32 bpp, UINT32 byte_limit,
1104 UINT32 start_line,
wStream* WINPR_RESTRICT temp_s, UINT32 e)
1106 Stream_ResetPosition(temp_s);
1112 return freerdp_bitmap_compress_16(srcData, width, height, s, bpp, byte_limit,
1113 start_line, temp_s, e);
1116 return freerdp_bitmap_compress_24(srcData, width, height, s, byte_limit, start_line,