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>
28static INLINE UINT16 GETPIXEL16(
const void* WINPR_RESTRICT d, UINT32 x, UINT32 y, UINT32 w)
30 const BYTE* WINPR_RESTRICT src = (
const BYTE*)d + ((y * w + x) *
sizeof(UINT16));
31 return WINPR_ASSERTING_INT_CAST(UINT16, ((UINT16)src[1] << 8) | (UINT16)src[0]);
34static INLINE UINT32 GETPIXEL32(
const void* WINPR_RESTRICT d, UINT32 x, UINT32 y, UINT32 w)
36 const BYTE* WINPR_RESTRICT src = (
const BYTE*)d + ((y * w + x) *
sizeof(UINT32));
37 return (((UINT32)src[3]) << 24) | (((UINT32)src[2]) << 16) | (((UINT32)src[1]) << 8) |
42static INLINE UINT16 IN_PIXEL16(
const void* WINPR_RESTRICT in_ptr, UINT32 in_x, UINT32 in_y,
43 UINT32 in_w, UINT16 in_last_pixel)
48 return GETPIXEL16(in_ptr, in_x, in_y, in_w);
54static INLINE UINT32 IN_PIXEL32(
const void* WINPR_RESTRICT in_ptr, UINT32 in_x, UINT32 in_y,
55 UINT32 in_w, UINT32 in_last_pixel)
60 return GETPIXEL32(in_ptr, in_x, in_y, in_w);
67static INLINE UINT16 out_color_count_2(UINT16 in_count,
wStream* WINPR_RESTRICT in_s,
74 const BYTE temp = ((0x3 << 5) | in_count) & 0xFF;
75 Stream_Write_UINT8(in_s, temp);
77 else if (in_count < 256 + 32)
79 const BYTE temp = (in_count - 32) & 0xFF;
80 Stream_Write_UINT8(in_s, 0x60);
81 Stream_Write_UINT8(in_s, temp);
85 Stream_Write_UINT8(in_s, 0xf3);
86 Stream_Write_UINT16(in_s, in_count);
89 Stream_Write_UINT16(in_s, in_data);
94#define OUT_COLOR_COUNT2(in_count, in_s, in_data) \
95 in_count = out_color_count_2(in_count, in_s, in_data)
99static INLINE UINT16 out_color_count_3(UINT16 in_count,
wStream* WINPR_RESTRICT in_s,
106 const BYTE temp = ((0x3 << 5) | in_count) & 0xFF;
107 Stream_Write_UINT8(in_s, temp);
109 else if (in_count < 256 + 32)
111 const BYTE temp = (in_count - 32) & 0xFF;
112 Stream_Write_UINT8(in_s, 0x60);
113 Stream_Write_UINT8(in_s, temp);
117 Stream_Write_UINT8(in_s, 0xf3);
118 Stream_Write_UINT16(in_s, in_count);
121 Stream_Write_UINT8(in_s, in_data & 0xFF);
123 Stream_Write_UINT8(in_s, (in_data >> 8) & 0xFF);
124 Stream_Write_UINT8(in_s, (in_data >> 16) & 0xFF);
130#define OUT_COLOR_COUNT3(in_count, in_s, in_data) \
131 in_count = out_color_count_3(in_count, in_s, in_data)
135static INLINE UINT16 out_copy_count_2(UINT16 in_count,
wStream* WINPR_RESTRICT in_s,
136 wStream* WINPR_RESTRICT in_data)
143 const BYTE temp = ((0x4 << 5) | in_count) & 0xFF;
144 Stream_Write_UINT8(in_s, temp);
146 else if (in_count < 256 + 32)
148 const BYTE temp = (in_count - 32) & 0xFF;
149 Stream_Write_UINT8(in_s, 0x80);
150 Stream_Write_UINT8(in_s, temp);
154 Stream_Write_UINT8(in_s, 0xf4);
155 Stream_Write_UINT16(in_s, in_count);
158 Stream_Write(in_s, Stream_Buffer(in_data), 2ULL * in_count);
161 Stream_SetPosition(in_data, 0);
164#define OUT_COPY_COUNT2(in_count, in_s, in_data) \
165 in_count = out_copy_count_2(in_count, in_s, in_data)
168static INLINE UINT16 out_copy_count_3(UINT16 in_count,
wStream* WINPR_RESTRICT in_s,
169 wStream* WINPR_RESTRICT in_data)
175 const BYTE temp = ((0x4 << 5) | in_count) & 0xFF;
176 Stream_Write_UINT8(in_s, temp);
178 else if (in_count < 256 + 32)
180 const BYTE temp = (in_count - 32) & 0xFF;
181 Stream_Write_UINT8(in_s, 0x80);
182 Stream_Write_UINT8(in_s, temp);
186 Stream_Write_UINT8(in_s, 0xf4);
187 Stream_Write_UINT16(in_s, in_count);
190 Stream_Write(in_s, Stream_Pointer(in_data), 3ULL * in_count);
193 Stream_SetPosition(in_data, 0);
196#define OUT_COPY_COUNT3(in_count, in_s, in_data) \
197 in_count = out_copy_count_3(in_count, in_s, in_data)
201static INLINE UINT16 out_bicolor_count_2(UINT16 in_count,
wStream* WINPR_RESTRICT in_s,
202 UINT16 in_color1, UINT16 in_color2)
206 if (in_count / 2 < 16)
208 const BYTE temp = ((0xe << 4) | (in_count / 2)) & 0xFF;
209 Stream_Write_UINT8(in_s, temp);
211 else if (in_count / 2 < 256 + 16)
213 const BYTE temp = (in_count / 2 - 16) & 0xFF;
214 Stream_Write_UINT8(in_s, 0xe0);
215 Stream_Write_UINT8(in_s, temp);
219 Stream_Write_UINT8(in_s, 0xf8);
220 Stream_Write_UINT16(in_s, in_count / 2);
223 Stream_Write_UINT16(in_s, in_color1);
224 Stream_Write_UINT16(in_s, in_color2);
230#define OUT_BICOLOR_COUNT2(in_count, in_s, in_color1, in_color2) \
231 in_count = out_bicolor_count_2(in_count, in_s, in_color1, in_color2)
235static INLINE UINT16 out_bicolor_count_3(UINT16 in_count,
wStream* WINPR_RESTRICT in_s,
236 UINT32 in_color1, UINT32 in_color2)
240 if (in_count / 2 < 16)
242 const BYTE temp = ((0xe << 4) | (in_count / 2)) & 0xFF;
243 Stream_Write_UINT8(in_s, temp);
245 else if (in_count / 2 < 256 + 16)
247 const BYTE temp = (in_count / 2 - 16) & 0xFF;
248 Stream_Write_UINT8(in_s, 0xe0);
249 Stream_Write_UINT8(in_s, temp);
253 Stream_Write_UINT8(in_s, 0xf8);
254 Stream_Write_UINT16(in_s, in_count / 2);
257 Stream_Write_UINT8(in_s, in_color1 & 0xFF);
258 Stream_Write_UINT8(in_s, (in_color1 >> 8) & 0xFF);
259 Stream_Write_UINT8(in_s, (in_color1 >> 16) & 0xFF);
260 Stream_Write_UINT8(in_s, in_color2 & 0xFF);
261 Stream_Write_UINT8(in_s, (in_color2 >> 8) & 0xFF);
262 Stream_Write_UINT8(in_s, (in_color2 >> 16) & 0xFF);
268#define OUT_BICOLOR_COUNT3(in_count, in_s, in_color1, in_color2) \
269 in_count = out_bicolor_count_3(in_count, in_s, in_color1, in_color2)
273static INLINE UINT16 out_fill_count_2(UINT16 in_count,
wStream* WINPR_RESTRICT in_s)
279 Stream_Write_UINT8(in_s, in_count & 0xFF);
281 else if (in_count < 256 + 32)
283 const BYTE temp = (in_count - 32) & 0xFF;
284 Stream_Write_UINT8(in_s, 0x0);
285 Stream_Write_UINT8(in_s, temp);
289 Stream_Write_UINT8(in_s, 0xf0);
290 Stream_Write_UINT16(in_s, in_count);
297#define OUT_FILL_COUNT2(in_count, in_s) in_count = out_fill_count_2(in_count, in_s)
301static INLINE UINT16 out_fill_count_3(UINT16 in_count,
wStream* WINPR_RESTRICT in_s)
307 Stream_Write_UINT8(in_s, in_count & 0xFF);
309 else if (in_count < 256 + 32)
311 const BYTE temp = (in_count - 32) & 0xFF;
312 Stream_Write_UINT8(in_s, 0x0);
313 Stream_Write_UINT8(in_s, temp);
317 Stream_Write_UINT8(in_s, 0xf0);
318 Stream_Write_UINT16(in_s, in_count);
324#define OUT_FILL_COUNT3(in_count, in_s) in_count = out_fill_count_3(in_count, in_s)
328static INLINE UINT16 out_mix_count_2(UINT16 in_count,
wStream* WINPR_RESTRICT in_s)
334 const BYTE temp = ((0x1 << 5) | in_count) & 0xFF;
335 Stream_Write_UINT8(in_s, temp);
337 else if (in_count < 256 + 32)
339 const BYTE temp = (in_count - 32) & 0xFF;
340 Stream_Write_UINT8(in_s, 0x20);
341 Stream_Write_UINT8(in_s, temp);
345 Stream_Write_UINT8(in_s, 0xf1);
346 Stream_Write_UINT16(in_s, in_count);
352#define OUT_MIX_COUNT2(in_count, in_s) in_count = out_mix_count_2(in_count, in_s)
356static INLINE UINT16 out_mix_count_3(UINT16 in_count,
wStream* WINPR_RESTRICT in_s)
362 const BYTE temp = ((0x1 << 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);
381#define OUT_MIX_COUNT3(in_count, in_s) in_count = out_mix_count_3(in_count, in_s)
385static INLINE UINT16 out_from_count_2(UINT16 in_count,
wStream* WINPR_RESTRICT in_s,
386 const int8_t* WINPR_RESTRICT in_mask,
size_t in_mask_len)
390 if ((in_count % 8) == 0 && in_count < 249)
392 const BYTE temp = ((0x2 << 5) | (in_count / 8)) & 0xFF;
393 Stream_Write_UINT8(in_s, temp);
395 else if (in_count < 256)
397 const BYTE temp = (in_count - 1) & 0xFF;
398 Stream_Write_UINT8(in_s, 0x40);
399 Stream_Write_UINT8(in_s, temp);
403 Stream_Write_UINT8(in_s, 0xf2);
404 Stream_Write_UINT16(in_s, in_count);
407 Stream_Write(in_s, in_mask, in_mask_len);
412#define OUT_FOM_COUNT2(in_count, in_s, in_mask, in_mask_len) \
413 in_count = out_from_count_2(in_count, in_s, in_mask, in_mask_len)
417static INLINE UINT16 out_from_count_3(UINT16 in_count,
wStream* WINPR_RESTRICT in_s,
418 const int8_t* WINPR_RESTRICT in_mask,
size_t in_mask_len)
422 if ((in_count % 8) == 0 && in_count < 249)
424 const BYTE temp = ((0x2 << 5) | (in_count / 8)) & 0xFF;
425 Stream_Write_UINT8(in_s, temp);
427 else if (in_count < 256)
429 const BYTE temp = (in_count - 1) & 0xFF;
430 Stream_Write_UINT8(in_s, 0x40);
431 Stream_Write_UINT8(in_s, temp);
435 Stream_Write_UINT8(in_s, 0xf2);
436 Stream_Write_UINT16(in_s, in_count);
439 Stream_Write(in_s, in_mask, in_mask_len);
444#define OUT_FOM_COUNT3(in_count, in_s, in_mask, in_mask_len) \
445 in_count = out_from_count_3(in_count, in_s, in_mask, in_mask_len)
447#define TEST_FILL ((last_line == 0 && pixel == 0) || (last_line != 0 && pixel == ypixel))
448#define TEST_MIX ((last_line == 0 && pixel == mix) || (last_line != 0 && pixel == (ypixel ^ mix)))
449#define TEST_FOM TEST_FILL || TEST_MIX
450#define TEST_COLOR pixel == last_pixel
451#define TEST_BICOLOR \
452 ((pixel != last_pixel) && \
453 ((!bicolor_spin && (pixel == bicolor1) && (last_pixel == bicolor2)) || \
454 (bicolor_spin && (pixel == bicolor2) && (last_pixel == bicolor1))))
455#define RESET_COUNTS \
464 bicolor_spin = FALSE; \
467static INLINE SSIZE_T freerdp_bitmap_compress_24(
const void* WINPR_RESTRICT srcData, UINT32 width,
468 WINPR_ATTR_UNUSED UINT32 height,
469 wStream* WINPR_RESTRICT s, UINT32 byte_limit,
470 UINT32 start_line,
wStream* WINPR_RESTRICT temp_s,
473 int8_t fom_mask[8192] = { 0 };
474 SSIZE_T lines_sent = 0;
476 UINT16 color_count = 0;
477 UINT32 last_pixel = 0;
478 UINT32 last_ypixel = 0;
479 UINT16 bicolor_count = 0;
482 BOOL bicolor_spin = FALSE;
483 UINT32 end = width + e;
484 UINT32 out_count = end * 3;
485 UINT16 fill_count = 0;
486 UINT16 mix_count = 0;
487 const UINT32 mix = 0xFFFFFF;
488 UINT16 fom_count = 0;
489 size_t fom_mask_len = 0;
490 const char* start = (
const char*)srcData;
491 const char* line = start + 4ULL * width * start_line;
492 const char* last_line = NULL;
494 while ((line >= start) && (out_count < 32768))
496 size_t i = Stream_GetPosition(s) + 3ULL * count;
498 if ((i - (3ULL * color_count) >= byte_limit) &&
499 (i - (3ULL * bicolor_count) >= byte_limit) && (i - (3ULL * fill_count) >= byte_limit) &&
500 (i - (3ULL * mix_count) >= byte_limit) && (i - (3ULL * fom_count) >= byte_limit))
505 out_count += end * 3;
507 for (UINT32 j = 0; j < end; j++)
510 const UINT32 pixel = IN_PIXEL32(line, j, 0, width, last_pixel);
511 const UINT32 ypixel = IN_PIXEL32(last_line, j, 0, width, last_ypixel);
515 if (fill_count > 3 && fill_count >= color_count && fill_count >= bicolor_count &&
516 fill_count >= mix_count && fill_count >= fom_count)
518 if (fill_count > count)
522 OUT_COPY_COUNT3(count, s, temp_s);
523 OUT_FILL_COUNT3(fill_count, s);
532 if (mix_count > 3 && mix_count >= fill_count && mix_count >= bicolor_count &&
533 mix_count >= color_count && mix_count >= fom_count)
535 if (mix_count > count)
539 OUT_COPY_COUNT3(count, s, temp_s);
540 OUT_MIX_COUNT3(mix_count, s);
549 if (color_count > 3 && color_count >= fill_count && color_count >= bicolor_count &&
550 color_count >= mix_count && color_count >= fom_count)
552 if (color_count > count)
555 count -= color_count;
556 OUT_COPY_COUNT3(count, s, temp_s);
557 OUT_COLOR_COUNT3(color_count, s, last_pixel);
566 if (bicolor_count > 3 && bicolor_count >= fill_count &&
567 bicolor_count >= color_count && bicolor_count >= mix_count &&
568 bicolor_count >= fom_count)
570 if ((bicolor_count % 2) != 0)
573 if (bicolor_count > count)
576 count -= bicolor_count;
577 OUT_COPY_COUNT3(count, s, temp_s);
578 OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor2, bicolor1);
583 bicolor1 = last_pixel;
585 bicolor_spin = FALSE;
590 if (fom_count > 3 && fom_count >= fill_count && fom_count >= color_count &&
591 fom_count >= mix_count && fom_count >= bicolor_count)
593 if (fom_count > count)
597 OUT_COPY_COUNT3(count, s, temp_s);
598 OUT_FOM_COUNT3(fom_count, s, fom_mask, fom_mask_len);
623 bicolor_spin = !bicolor_spin;
629 if ((fom_count % 8) == 0)
631 fom_mask[fom_mask_len] = 0;
635 if (pixel == (ypixel ^ mix))
637 const int tmp = (1 << (fom_count % 8));
638 const int val = fom_mask[fom_mask_len - 1] | tmp;
639 const int8_t ival = WINPR_ASSERTING_INT_CAST(int8_t, val);
640 fom_mask[fom_mask_len - 1] = ival;
646 Stream_Write_UINT8(temp_s, pixel & 0xff);
647 Stream_Write_UINT8(temp_s, (pixel >> 8) & 0xff);
648 Stream_Write_UINT8(temp_s, (pixel >> 16) & 0xff);
651 last_ypixel = ypixel;
657 if (fill_count > 3 && fill_count >= color_count && fill_count >= bicolor_count &&
658 fill_count >= mix_count && fill_count >= fom_count)
660 if (fill_count > count)
664 OUT_COPY_COUNT3(count, s, temp_s);
665 OUT_FILL_COUNT3(fill_count, s);
671 if (mix_count > 3 && mix_count >= fill_count && mix_count >= bicolor_count &&
672 mix_count >= color_count && mix_count >= fom_count)
674 if (mix_count > count)
678 OUT_COPY_COUNT3(count, s, temp_s);
679 OUT_MIX_COUNT3(mix_count, s);
685 if (fom_count > 3 && fom_count >= fill_count && fom_count >= color_count &&
686 fom_count >= mix_count && fom_count >= bicolor_count)
688 if (fom_count > count)
692 OUT_COPY_COUNT3(count, s, temp_s);
693 OUT_FOM_COUNT3(fom_count, s, fom_mask, fom_mask_len);
702 line = line - 4ULL * width;
707 Stream_SetPosition(temp_s, 0);
709 if (fill_count > 3 && fill_count >= color_count && fill_count >= bicolor_count &&
710 fill_count >= mix_count && fill_count >= fom_count)
712 if (fill_count > count)
716 OUT_COPY_COUNT3(count, s, temp_s);
717 OUT_FILL_COUNT3(fill_count, s);
719 else if (mix_count > 3 && mix_count >= color_count && mix_count >= bicolor_count &&
720 mix_count >= fill_count && mix_count >= fom_count)
722 if (mix_count > count)
726 OUT_COPY_COUNT3(count, s, temp_s);
727 OUT_MIX_COUNT3(mix_count, s);
729 else if (color_count > 3 && color_count >= mix_count && color_count >= bicolor_count &&
730 color_count >= fill_count && color_count >= fom_count)
732 if (color_count > count)
735 count -= color_count;
736 OUT_COPY_COUNT3(count, s, temp_s);
737 OUT_COLOR_COUNT3(color_count, s, last_pixel);
739 else if (bicolor_count > 3 && bicolor_count >= mix_count && bicolor_count >= color_count &&
740 bicolor_count >= fill_count && bicolor_count >= fom_count)
742 if ((bicolor_count % 2) != 0)
745 if (bicolor_count > count)
748 count -= bicolor_count;
749 OUT_COPY_COUNT3(count, s, temp_s);
750 OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor2, bicolor1);
752 if (bicolor_count > count)
755 count -= bicolor_count;
756 OUT_COPY_COUNT3(count, s, temp_s);
757 OUT_BICOLOR_COUNT3(bicolor_count, s, bicolor1, bicolor2);
759 else if (fom_count > 3 && fom_count >= mix_count && fom_count >= color_count &&
760 fom_count >= fill_count && fom_count >= bicolor_count)
762 if (fom_count > count)
766 OUT_COPY_COUNT3(count, s, temp_s);
767 OUT_FOM_COUNT3(fom_count, s, fom_mask, fom_mask_len);
771 OUT_COPY_COUNT3(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 start_line,
781 wStream* WINPR_RESTRICT temp_s, UINT32 e)
783 int8_t fom_mask[8192] = { 0 };
784 SSIZE_T lines_sent = 0;
786 UINT16 color_count = 0;
787 UINT16 last_pixel = 0;
788 UINT16 last_ypixel = 0;
789 UINT16 bicolor_count = 0;
792 BOOL bicolor_spin = FALSE;
793 UINT32 end = width + e;
794 UINT32 out_count = end * 2;
795 UINT16 fill_count = 0;
796 UINT16 mix_count = 0;
797 const UINT32 mix = (bpp == 15) ? 0xBA1F : 0xFFFF;
798 UINT16 fom_count = 0;
799 size_t fom_mask_len = 0;
800 const char* start = (
const char*)srcData;
801 const char* line = start + 2ULL * width * start_line;
802 const char* last_line = NULL;
804 while ((line >= start) && (out_count < 32768))
806 size_t i = Stream_GetPosition(s) + 2ULL * count;
808 if ((i - (2ULL * color_count) >= byte_limit) &&
809 (i - (2ULL * bicolor_count) >= byte_limit) && (i - (2ULL * fill_count) >= byte_limit) &&
810 (i - (2ULL * mix_count) >= byte_limit) && (i - (2ULL * 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 (fill_count > 3 && fill_count >= color_count && fill_count >= bicolor_count &&
826 fill_count >= mix_count && fill_count >= fom_count)
828 if (fill_count > count)
832 OUT_COPY_COUNT2(count, s, temp_s);
833 OUT_FILL_COUNT2(fill_count, s);
842 if (mix_count > 3 && mix_count >= fill_count && mix_count >= bicolor_count &&
843 mix_count >= color_count && mix_count >= fom_count)
845 if (mix_count > count)
849 OUT_COPY_COUNT2(count, s, temp_s);
850 OUT_MIX_COUNT2(mix_count, s);
859 if (color_count > 3 && color_count >= fill_count && color_count >= bicolor_count &&
860 color_count >= mix_count && color_count >= fom_count)
862 if (color_count > count)
865 count -= color_count;
866 OUT_COPY_COUNT2(count, s, temp_s);
867 OUT_COLOR_COUNT2(color_count, s, last_pixel);
876 if ((bicolor_count > 3) && (bicolor_count >= fill_count) &&
877 (bicolor_count >= color_count) && (bicolor_count >= mix_count) &&
878 (bicolor_count >= fom_count))
880 if ((bicolor_count % 2) != 0)
883 if (bicolor_count > count)
886 count -= bicolor_count;
887 OUT_COPY_COUNT2(count, s, temp_s);
888 OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor2, bicolor1);
893 bicolor1 = last_pixel;
895 bicolor_spin = FALSE;
900 if (fom_count > 3 && fom_count >= fill_count && fom_count >= color_count &&
901 fom_count >= mix_count && fom_count >= bicolor_count)
903 if (fom_count > count)
907 OUT_COPY_COUNT2(count, s, temp_s);
908 OUT_FOM_COUNT2(fom_count, s, fom_mask, fom_mask_len);
933 bicolor_spin = !bicolor_spin;
939 if ((fom_count % 8) == 0)
941 fom_mask[fom_mask_len] = 0;
945 if (pixel == (ypixel ^ mix))
947 const int tmp = (1 << (fom_count % 8));
948 const int val = fom_mask[fom_mask_len - 1] | tmp;
949 const int8_t ival = WINPR_ASSERTING_INT_CAST(int8_t, val);
950 fom_mask[fom_mask_len - 1] = ival;
956 Stream_Write_UINT16(temp_s, pixel);
959 last_ypixel = ypixel;
965 if (fill_count > 3 && fill_count >= color_count && fill_count >= bicolor_count &&
966 fill_count >= mix_count && fill_count >= fom_count)
968 if (fill_count > count)
972 OUT_COPY_COUNT2(count, s, temp_s);
973 OUT_FILL_COUNT2(fill_count, s);
979 if (mix_count > 3 && mix_count >= fill_count && mix_count >= bicolor_count &&
980 mix_count >= color_count && mix_count >= fom_count)
982 if (mix_count > count)
986 OUT_COPY_COUNT2(count, s, temp_s);
987 OUT_MIX_COUNT2(mix_count, s);
993 if (fom_count > 3 && fom_count >= fill_count && fom_count >= color_count &&
994 fom_count >= mix_count && fom_count >= bicolor_count)
996 if (fom_count > count)
1000 OUT_COPY_COUNT2(count, s, temp_s);
1001 OUT_FOM_COUNT2(fom_count, s, fom_mask, fom_mask_len);
1010 line = line - 2ULL * width;
1015 Stream_SetPosition(temp_s, 0);
1017 if (fill_count > 3 && fill_count >= color_count && fill_count >= bicolor_count &&
1018 fill_count >= mix_count && fill_count >= fom_count)
1020 if (fill_count > count)
1023 count -= fill_count;
1024 OUT_COPY_COUNT2(count, s, temp_s);
1025 OUT_FILL_COUNT2(fill_count, s);
1027 else if (mix_count > 3 && mix_count >= color_count && mix_count >= bicolor_count &&
1028 mix_count >= fill_count && mix_count >= fom_count)
1030 if (mix_count > count)
1034 OUT_COPY_COUNT2(count, s, temp_s);
1035 OUT_MIX_COUNT2(mix_count, s);
1037 else if (color_count > 3 && color_count >= mix_count && color_count >= bicolor_count &&
1038 color_count >= fill_count && color_count >= fom_count)
1040 if (color_count > count)
1043 count -= color_count;
1044 OUT_COPY_COUNT2(count, s, temp_s);
1045 OUT_COLOR_COUNT2(color_count, s, last_pixel);
1047 else if (bicolor_count > 3 && bicolor_count >= mix_count && bicolor_count >= color_count &&
1048 bicolor_count >= fill_count && bicolor_count >= fom_count)
1050 if ((bicolor_count % 2) != 0)
1053 if (bicolor_count > count)
1056 count -= bicolor_count;
1057 OUT_COPY_COUNT2(count, s, temp_s);
1058 OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor2, bicolor1);
1060 if (bicolor_count > count)
1063 count -= bicolor_count;
1064 OUT_COPY_COUNT2(count, s, temp_s);
1065 OUT_BICOLOR_COUNT2(bicolor_count, s, bicolor1, bicolor2);
1067 else if (fom_count > 3 && fom_count >= mix_count && fom_count >= color_count &&
1068 fom_count >= fill_count && fom_count >= bicolor_count)
1070 if (fom_count > count)
1074 OUT_COPY_COUNT2(count, s, temp_s);
1075 OUT_FOM_COUNT2(fom_count, s, fom_mask, fom_mask_len);
1079 OUT_COPY_COUNT2(count, s, temp_s);
1085SSIZE_T freerdp_bitmap_compress(
const void* WINPR_RESTRICT srcData, UINT32 width, UINT32 height,
1086 wStream* WINPR_RESTRICT s, UINT32 bpp, UINT32 byte_limit,
1087 UINT32 start_line,
wStream* WINPR_RESTRICT temp_s, UINT32 e)
1089 Stream_SetPosition(temp_s, 0);
1095 return freerdp_bitmap_compress_16(srcData, width, height, s, bpp, byte_limit,
1096 start_line, temp_s, e);
1099 return freerdp_bitmap_compress_24(srcData, width, height, s, byte_limit, start_line,