22#include <freerdp/config.h>
30#include <freerdp/log.h>
31#include <freerdp/freerdp.h>
32#include <freerdp/primitives.h>
34#if defined(WITH_CAIRO)
38#if defined(WITH_SWSCALE)
39#include <libswscale/swscale.h>
44#define TAG FREERDP_TAG("color")
46static BOOL freerdp_image_copy_from_pointer_data_int(
47 BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
48 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
49 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength, UINT32 xorBpp,
50 const gdiPalette* WINPR_RESTRICT palette);
52#if defined(WITH_CURSOR_DUMP)
53#include <winpr/path.h>
54#include <winpr/image.h>
55static char* get_dump_name(
char* prefix,
size_t len)
57 static uint64_t count = 0;
58 _snprintf(prefix, len,
"cursor_dump_%08" PRIx64, count++);
60 return GetCombinedPath(CURSOR_DUMP_DIR, prefix);
63static void dump_binary_data(FILE* fp,
const uint8_t* data,
size_t len)
66 (void)fprintf(fp,
"0x%02" PRIx8, data[0]);
67 for (
size_t x = 1; x < len; x++)
69 (void)fprintf(fp,
", 0x%02" PRIx8, data[x]);
73static void dump_uint_data(FILE* fp,
const uint32_t* data,
size_t len)
76 (void)fprintf(fp,
"0x%08" PRIx32, data[0]);
77 for (
size_t x = 1; x < len; x++)
79 (void)fprintf(fp,
", 0x%08" PRIx32, data[x]);
83static void dump_write_header(
const char* path,
const char* prefix)
87 winpr_asprintf(&header, &headerlen,
"%s.h", path);
90 FILE* fp = fopen(header,
"w");
96 (void)fprintf(fp,
"/* FreeRDP cursor dump to use for unit tests\n");
97 (void)fprintf(fp,
" * this file was auto generated by %s\n", __func__);
98 (void)fprintf(fp,
" * do not modify manually\n");
99 (void)fprintf(fp,
" */\n");
100 (void)fprintf(fp,
"\n");
101 (void)fprintf(fp,
"#pragma once\n");
102 (void)fprintf(fp,
"\n");
103 (void)fprintf(fp,
"#include <freerdp/codec/color.h>\n");
104 (void)fprintf(fp,
"#include <freerdp/graphics.h>\n");
105 (void)fprintf(fp,
"\n");
106 (void)fprintf(fp,
"extern const gdiPalette %s_palette;\n", prefix);
107 (void)fprintf(fp,
"extern const rdpPointer %s_pointer;\n", prefix);
108 (void)fprintf(fp,
"extern const uint8_t %s_image_bgra32[];\n", prefix);
112static void dump_write_c_file(
const char* path,
const char* prefix, UINT32 nXDst, UINT32 nYDst,
113 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT xorMask,
114 UINT32 xorMaskLength,
const BYTE* WINPR_RESTRICT andMask,
115 UINT32 andMaskLength, UINT32 xorBpp,
const gdiPalette* palette,
118 const uint32_t format = PIXEL_FORMAT_BGRA32;
119 const uint32_t bpp = FreeRDPGetBytesPerPixel(format);
120 const uint32_t step = nWidth * bpp;
123 size_t headerlen = 0;
124 winpr_asprintf(&header, &headerlen,
"%s.c", path);
127 FILE* fp = fopen(header,
"w");
132 (void)fprintf(fp,
"/* FreeRDP cursor dump to use for unit tests\n");
133 (void)fprintf(fp,
" * this file was auto generated by %s\n", __func__);
134 (void)fprintf(fp,
" * do not modify manually\n");
135 (void)fprintf(fp,
" */\n");
136 (void)fprintf(fp,
"\n");
137 (void)fprintf(fp,
"#include \"%s.h\"\n", prefix);
138 (void)fprintf(fp,
"\n");
140 (void)fprintf(fp,
"static const uint8_t andmask[] = {\n");
141 dump_binary_data(fp, andMask, andMaskLength);
142 (void)fprintf(fp,
"};\n");
143 (void)fprintf(fp,
"\n");
145 (void)fprintf(fp,
"static const uint8_t xormask[] = {\n");
146 dump_binary_data(fp, xorMask, xorMaskLength);
147 (void)fprintf(fp,
"};\n");
148 (void)fprintf(fp,
"\n");
149 (void)fprintf(fp,
"const gdiPalette %s_palette = {\n", prefix);
152 (void)fprintf(fp,
".format=%" PRIu32
",", palette->format);
153 (void)fprintf(fp,
".palette={");
154 dump_uint_data(fp, palette->palette, ARRAYSIZE(palette->palette));
155 (void)fprintf(fp,
"}\n");
158 (
void)fprintf(fp,
"0");
160 (void)fprintf(fp,
"};\n");
162 (void)fprintf(fp,
"\n");
163 (void)fprintf(fp,
"const rdpPointer %s_pointer = {\n", prefix);
164 (void)fprintf(fp,
".size = 0,\n");
165 (void)fprintf(fp,
".New = NULL,\n");
166 (void)fprintf(fp,
".Free = NULL,\n");
167 (void)fprintf(fp,
".Set = NULL,\n");
168 (void)fprintf(fp,
".SetNull = NULL,\n");
169 (void)fprintf(fp,
".SetDefault = NULL,\n");
170 (void)fprintf(fp,
".SetPosition = NULL,\n");
171 (void)fprintf(fp,
".paddingA = {0},\n");
172 (void)fprintf(fp,
".xPos = %" PRIu32
",\n", nXDst);
173 (void)fprintf(fp,
".yPos = %" PRIu32
",\n", nYDst);
174 (void)fprintf(fp,
".width = %" PRIu32
",\n", nWidth);
175 (void)fprintf(fp,
".height = %" PRIu32
",\n", nHeight);
176 (void)fprintf(fp,
".xorBpp = %" PRIu32
",\n", xorBpp);
177 (void)fprintf(fp,
".lengthAndMask = ARRAYSIZE(andmask),\n");
178 (void)fprintf(fp,
".lengthXorMask = ARRAYSIZE(xormask),\n");
179 (void)fprintf(fp,
".xorMaskData = xormask,\n");
180 (void)fprintf(fp,
".andMaskData = andmask,\n");
181 (void)fprintf(fp,
".paddingB = {0}\n");
182 (void)fprintf(fp,
"};\n");
183 (void)fprintf(fp,
"\n");
184 (void)fprintf(fp,
"const uint8_t %s_image_bgra32[]={\n", prefix);
185 dump_binary_data(fp, bmp, step * nHeight);
186 (void)fprintf(fp,
"};\n");
190 wImage* img = winpr_image_new();
193 img->data = WINPR_CAST_CONST_PTR_AWAY(bmp, BYTE*);
194 img->bitsPerPixel = 32;
195 img->bytesPerPixel = 4;
196 img->height = nHeight;
198 img->scanline = step;
199 img->type = WINPR_IMAGE_PNG;
200 char* imgname = NULL;
201 size_t imgnamesize = 0;
202 winpr_asprintf(&imgname, &imgnamesize,
"%s.png", path);
204 winpr_image_write(img, imgname);
206 winpr_image_free(img, FALSE);
215static void dump_pointer_data(UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
216 const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
217 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength,
218 UINT32 xorBpp,
const gdiPalette* palette)
220 const uint32_t format = PIXEL_FORMAT_BGRA32;
221 const uint32_t bpp = FreeRDPGetBytesPerPixel(format);
222 const uint32_t step = nWidth * bpp;
223 BYTE* bmp = calloc(step * 2, nHeight);
224 char prefix[64] = { 0 };
225 char* path = get_dump_name(prefix,
sizeof(prefix));
230 if (!freerdp_image_copy_from_pointer_data_int(bmp, format, step, 0, 0, nWidth, nHeight, xorMask,
231 xorMaskLength, andMask, andMaskLength, xorBpp,
235 dump_write_header(path, prefix);
236 dump_write_c_file(path, prefix, nXDst, nYDst, nWidth, nHeight, xorMask, xorMaskLength, andMask,
237 andMaskLength, xorBpp, palette, bmp);
245#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
246BYTE* freerdp_glyph_convert(UINT32 width, UINT32 height,
const BYTE* WINPR_RESTRICT data)
248 const size_t scanline = (width + 7ull) / 8ull;
249 const size_t required = scanline * height;
250 return freerdp_glyph_convert_ex(width, height, data, required);
254BYTE* freerdp_glyph_convert_ex(UINT32 width, UINT32 height,
const BYTE* WINPR_RESTRICT data,
262 const size_t scanline = (width + 7ull) / 8ull;
263 const size_t required = scanline * height;
267 if ((len == 0) || (width == 0) || (height == 0))
272 BYTE* dstData = (BYTE*)winpr_aligned_malloc(1ull * width * height, 16);
277 ZeroMemory(dstData, 1ULL * width * height);
278 BYTE* dstp = dstData;
280 for (UINT32 y = 0; y < height; y++)
282 const BYTE* srcp = &data[1ull * y * scanline];
284 for (UINT32 x = 0; x < width; x++)
286 if ((*srcp & (0x80 >> (x % 8))) != 0)
291 if (((x + 1) % 8 == 0) && x != 0)
299BOOL freerdp_image_copy_from_monochrome(BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,
300 UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT32 nWidth,
301 UINT32 nHeight,
const BYTE* WINPR_RESTRICT pSrcData,
302 UINT32 backColor, UINT32 foreColor,
303 const gdiPalette* WINPR_RESTRICT palette)
305 const UINT32 dstBytesPerPixel = FreeRDPGetBytesPerPixel(DstFormat);
307 if (!pDstData || !pSrcData || !palette)
311 nDstStep = dstBytesPerPixel * nWidth;
313 const UINT32 monoStep = (nWidth + 7) / 8;
315 for (
size_t y = 0; y < nHeight; y++)
317 BYTE* pDstLine = &pDstData[((nYDst + y) * nDstStep)];
318 UINT32 monoBit = 0x80;
319 const BYTE* monoBits = &pSrcData[monoStep * y];
321 for (
size_t x = 0; x < nWidth; x++)
323 BYTE* pDstPixel = &pDstLine[((nXDst + x) * FreeRDPGetBytesPerPixel(DstFormat))];
324 BOOL monoPixel = (*monoBits & monoBit) ? TRUE : FALSE;
326 if (!(monoBit >>= 1))
333 FreeRDPWriteColor_int(pDstPixel, DstFormat, backColor);
335 FreeRDPWriteColor_int(pDstPixel, DstFormat, foreColor);
342static inline UINT32 freerdp_image_inverted_pointer_color(UINT32 x, UINT32 y, UINT32 format)
353 BYTE fill = (x + y) & 1 ? 0x00 : 0xFF;
354 return FreeRDPGetColor(format, fill, fill, fill, 0xFF);
361static void fill_gdi_palette_for_icon(
const BYTE* colorTable, UINT16 cbColorTable,
364 WINPR_ASSERT(palette);
366 palette->format = PIXEL_FORMAT_BGRX32;
367 ZeroMemory(palette->palette,
sizeof(palette->palette));
372 if ((cbColorTable % 4 != 0) || (cbColorTable / 4 > 256))
374 WLog_WARN(TAG,
"weird palette size: %u", cbColorTable);
378 for (UINT16 i = 0; i < cbColorTable / 4; i++)
380 palette->palette[i] = FreeRDPReadColor_int(&colorTable[4ULL * i], palette->format);
384static inline UINT32 div_ceil(UINT32 a, UINT32 b)
386 return (a + (b - 1)) / b;
389static inline UINT32 round_up(UINT32 a, UINT32 b)
391 return b * div_ceil(a, b);
394BOOL freerdp_image_copy_from_icon_data(BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,
395 UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT16 nWidth,
396 UINT16 nHeight,
const BYTE* WINPR_RESTRICT bitsColor,
397 UINT16 cbBitsColor,
const BYTE* WINPR_RESTRICT bitsMask,
398 UINT16 cbBitsMask,
const BYTE* WINPR_RESTRICT colorTable,
399 UINT16 cbColorTable, UINT32 bpp)
404 if (!pDstData || !bitsColor)
423 WLog_WARN(TAG,
"1bpp and 4bpp icons are not supported");
427 format = PIXEL_FORMAT_RGB8;
431 format = PIXEL_FORMAT_RGB15;
435 format = PIXEL_FORMAT_RGB24;
439 format = PIXEL_FORMAT_BGRA32;
443 WLog_WARN(TAG,
"invalid icon bpp: %" PRIu32, bpp);
448 if (cbBitsColor < nWidth * nHeight * FreeRDPGetBytesPerPixel(format))
451 fill_gdi_palette_for_icon(colorTable, cbColorTable, &palette);
452 if (!freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,
453 bitsColor, format, 0, 0, 0, &palette, FREERDP_FLIP_VERTICAL))
457 if (FreeRDPColorHasAlpha(DstFormat) && cbBitsMask)
460 const BYTE* maskByte = NULL;
465 BYTE* dstBuf = pDstData;
466 UINT32 dstBpp = FreeRDPGetBytesPerPixel(DstFormat);
473 stride = round_up(div_ceil(nWidth, 8), 4);
475 for (UINT32 y = 0; y < nHeight; y++)
477 maskByte = &bitsMask[1ULL * stride * (nHeight - 1 - y)];
480 for (UINT32 x = 0; x < nWidth; x++)
483 BYTE alpha = (*maskByte & nextBit) ? 0x00 : 0xFF;
486 color = FreeRDPReadColor_int(dstBuf, DstFormat);
487 FreeRDPSplitColor(color, DstFormat, &r, &g, &b, NULL, &palette);
488 color = FreeRDPGetColor(DstFormat, r, g, b, alpha);
489 FreeRDPWriteColor_int(dstBuf, DstFormat, color);
505static BOOL freerdp_image_copy_from_pointer_data_1bpp(
506 BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
507 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
508 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength, UINT32 xorBpp)
518 vFlip = (xorBpp == 1) ? FALSE : TRUE;
519 andStep = (nWidth + 7) / 8;
520 andStep += (andStep % 2);
522 if (!xorMask || (xorMaskLength == 0))
524 if (!andMask || (andMaskLength == 0))
527 xorStep = (nWidth + 7) / 8;
528 xorStep += (xorStep % 2);
530 if (xorStep * nHeight > xorMaskLength)
533 if (andStep * nHeight > andMaskLength)
536 for (UINT32 y = 0; y < nHeight; y++)
538 const BYTE* andBits = NULL;
539 const BYTE* xorBits = NULL;
540 BYTE* pDstPixel = &pDstData[((1ULL * nYDst + y) * nDstStep) +
541 (1ULL * nXDst * FreeRDPGetBytesPerPixel(DstFormat))];
542 xorBit = andBit = 0x80;
546 xorBits = &xorMask[1ULL * xorStep * y];
547 andBits = &andMask[1ULL * andStep * y];
551 xorBits = &xorMask[1ULL * xorStep * (nHeight - y - 1)];
552 andBits = &andMask[1ULL * andStep * (nHeight - y - 1)];
555 for (UINT32 x = 0; x < nWidth; x++)
558 xorPixel = (*xorBits & xorBit) ? 1 : 0;
566 andPixel = (*andBits & andBit) ? 1 : 0;
574 if (!andPixel && !xorPixel)
575 color = FreeRDPGetColor(DstFormat, 0, 0, 0, 0xFF);
576 else if (!andPixel && xorPixel)
577 color = FreeRDPGetColor(DstFormat, 0xFF, 0xFF, 0xFF, 0xFF);
578 else if (andPixel && !xorPixel)
579 color = FreeRDPGetColor(DstFormat, 0, 0, 0, 0);
580 else if (andPixel && xorPixel)
581 color = freerdp_image_inverted_pointer_color(x, y, DstFormat);
583 FreeRDPWriteColor_int(pDstPixel, DstFormat, color);
584 pDstPixel += FreeRDPGetBytesPerPixel(DstFormat);
591static BOOL freerdp_image_copy_from_pointer_data_xbpp(
592 BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
593 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
594 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength, UINT32 xorBpp,
595 const gdiPalette* palette)
603 UINT32 dstBitsPerPixel = 0;
604 UINT32 xorBytesPerPixel = 0;
605 dstBitsPerPixel = FreeRDPGetBitsPerPixel(DstFormat);
607 vFlip = (xorBpp == 1) ? FALSE : TRUE;
608 andStep = (nWidth + 7) / 8;
609 andStep += (andStep % 2);
611 if (!xorMask || (xorMaskLength == 0))
614 xorBytesPerPixel = xorBpp >> 3;
615 xorStep = 1ULL * nWidth * xorBytesPerPixel;
616 xorStep += (xorStep % 2);
618 if (xorBpp == 8 && !palette)
620 WLog_ERR(TAG,
"null palette in conversion from %" PRIu32
" bpp to %" PRIu32
" bpp", xorBpp,
625 if (xorStep * nHeight > xorMaskLength)
630 if (andStep * nHeight > andMaskLength)
634 for (UINT32 y = 0; y < nHeight; y++)
636 const BYTE* xorBits = NULL;
637 const BYTE* andBits = NULL;
638 BYTE* pDstPixel = &pDstData[((1ULL * nYDst + y) * nDstStep) +
639 (1ULL * nXDst * FreeRDPGetBytesPerPixel(DstFormat))];
645 andBits = &andMask[andStep * y];
647 xorBits = &xorMask[xorStep * y];
652 andBits = &andMask[1ULL * andStep * (nHeight - y - 1)];
654 xorBits = &xorMask[1ULL * xorStep * (nHeight - y - 1)];
657 for (UINT32 x = 0; x < nWidth; x++)
659 UINT32 pixelFormat = 0;
666 andPixel = (*andBits & andBit) ? 1 : 0;
677 pixelFormat = PIXEL_FORMAT_BGRA32;
678 xorPixel = FreeRDPReadColor_int(xorBits, pixelFormat);
680 else if (xorBpp == 16)
682 pixelFormat = PIXEL_FORMAT_RGB15;
683 xorPixel = FreeRDPReadColor_int(xorBits, pixelFormat);
685 else if (xorBpp == 8)
687 pixelFormat = palette->format;
688 xorPixel = palette->palette[xorBits[0]];
692 pixelFormat = PIXEL_FORMAT_BGR24;
693 xorPixel = FreeRDPReadColor_int(xorBits, pixelFormat);
697 if (xorPixel == 0x00FFFFFFUL)
698 xorPixel |= 0xFF000000UL;
703 xorPixel |= 0xFF000000UL;
706 pixelFormat = PIXEL_FORMAT_ABGR32;
709 xorPixel = FreeRDPConvertColor(xorPixel, pixelFormat, PIXEL_FORMAT_ARGB32, palette);
710 xorBits += xorBytesPerPixel;
714 if (xorPixel == 0xFF000000UL)
715 xorPixel = 0x00000000;
716 else if (xorPixel == 0xFFFFFFFFUL)
717 xorPixel = freerdp_image_inverted_pointer_color(x, y, PIXEL_FORMAT_ARGB32);
720 color = FreeRDPConvertColor(xorPixel, PIXEL_FORMAT_ARGB32, DstFormat, palette);
721 FreeRDPWriteColor_int(pDstPixel, DstFormat, color);
722 pDstPixel += FreeRDPGetBytesPerPixel(DstFormat);
737BOOL freerdp_image_copy_from_pointer_data_int(
738 BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
739 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
740 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength, UINT32 xorBpp,
741 const gdiPalette* WINPR_RESTRICT palette)
743 UINT32 dstBitsPerPixel = 0;
744 UINT32 dstBytesPerPixel = 0;
745 dstBitsPerPixel = FreeRDPGetBitsPerPixel(DstFormat);
746 dstBytesPerPixel = FreeRDPGetBytesPerPixel(DstFormat);
749 nDstStep = dstBytesPerPixel * nWidth;
751 for (UINT32 y = nYDst; y < nHeight; y++)
753 BYTE* WINPR_RESTRICT pDstLine = &pDstData[y * nDstStep + nXDst * dstBytesPerPixel];
754 memset(pDstLine, 0, 1ull * dstBytesPerPixel * (nWidth - nXDst));
760 return freerdp_image_copy_from_pointer_data_1bpp(
761 pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, xorMask,
762 xorMaskLength, andMask, andMaskLength, xorBpp);
768 return freerdp_image_copy_from_pointer_data_xbpp(
769 pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, xorMask,
770 xorMaskLength, andMask, andMaskLength, xorBpp, palette);
773 WLog_ERR(TAG,
"failed to convert from %" PRIu32
" bpp to %" PRIu32
" bpp", xorBpp,
779BOOL freerdp_image_copy_from_pointer_data(BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,
780 UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
781 UINT32 nWidth, UINT32 nHeight,
782 const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
783 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength,
784 UINT32 xorBpp,
const gdiPalette* WINPR_RESTRICT palette)
786#if defined(WITH_CURSOR_DUMP)
787 dump_pointer_data(nXDst, nYDst, nWidth, nHeight, xorMask, xorMaskLength, andMask, andMaskLength,
790 return freerdp_image_copy_from_pointer_data_int(pDstData, DstFormat, nDstStep, nXDst, nYDst,
791 nWidth, nHeight, xorMask, xorMaskLength,
792 andMask, andMaskLength, xorBpp, palette);
795static inline BOOL overlapping(
const BYTE* pDstData, UINT32 nYDst, UINT32 nDstStep,
796 const BYTE* pSrcData, UINT32 nYSrc, UINT32 nSrcStep, UINT32 nHeight)
798 const uintptr_t src = (uintptr_t)pSrcData;
799 const uintptr_t srcstart = src + 1ULL * nSrcStep * nYSrc;
800 const uintptr_t srcend = srcstart + 1ULL * nSrcStep * nHeight;
801 const uintptr_t dst = (uintptr_t)pDstData;
802 const uintptr_t dststart = dst + 1ULL * nDstStep * nYDst;
803 const uintptr_t dstend = dststart + 1ULL * nDstStep * nHeight;
805 if ((dststart >= srcstart) && (dststart <= srcend))
808 if ((dstend >= srcstart) && (dstend <= srcend))
814static inline BOOL freerdp_image_copy_bgr24_bgrx32(BYTE* WINPR_RESTRICT pDstData, UINT32 nDstStep,
815 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth,
817 const BYTE* WINPR_RESTRICT pSrcData,
818 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
819 int64_t srcVMultiplier, int64_t srcVOffset,
820 int64_t dstVMultiplier, int64_t dstVOffset)
823 const int64_t srcByte = 3;
824 const int64_t dstByte = 4;
826 for (int64_t y = 0; y < nHeight; y++)
828 const BYTE* WINPR_RESTRICT srcLine =
829 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
830 BYTE* WINPR_RESTRICT dstLine =
831 &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
833 for (int64_t x = 0; x < nWidth; x++)
835 dstLine[(x + nXDst) * dstByte + 0] = srcLine[(x + nXSrc) * srcByte + 0];
836 dstLine[(x + nXDst) * dstByte + 1] = srcLine[(x + nXSrc) * srcByte + 1];
837 dstLine[(x + nXDst) * dstByte + 2] = srcLine[(x + nXSrc) * srcByte + 2];
844static inline BOOL freerdp_image_copy_bgrx32_bgrx32(BYTE* WINPR_RESTRICT pDstData, UINT32 nDstStep,
845 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth,
847 const BYTE* WINPR_RESTRICT pSrcData,
848 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
849 int64_t srcVMultiplier, int64_t srcVOffset,
850 int64_t dstVMultiplier, int64_t dstVOffset)
853 const int64_t srcByte = 4;
854 const int64_t dstByte = 4;
856 for (int64_t y = 0; y < nHeight; y++)
858 const BYTE* WINPR_RESTRICT srcLine =
859 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
860 BYTE* WINPR_RESTRICT dstLine =
861 &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
863 for (int64_t x = 0; x < nWidth; x++)
865 dstLine[(x + nXDst) * dstByte + 0] = srcLine[(x + nXSrc) * srcByte + 0];
866 dstLine[(x + nXDst) * dstByte + 1] = srcLine[(x + nXSrc) * srcByte + 1];
867 dstLine[(x + nXDst) * dstByte + 2] = srcLine[(x + nXSrc) * srcByte + 2];
874static inline BOOL freerdp_image_copy_generic(
875 BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
876 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcFormat,
877 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
const gdiPalette* WINPR_RESTRICT palette,
878 int64_t srcVMultiplier, int64_t srcVOffset, int64_t dstVMultiplier, int64_t dstVOffset)
881 const int64_t srcByte = 4;
882 const int64_t dstByte = 4;
884 for (int64_t y = 0; y < nHeight; y++)
886 const BYTE* WINPR_RESTRICT srcLine =
887 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
888 BYTE* WINPR_RESTRICT dstLine =
889 &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
891 UINT32 color = FreeRDPReadColor_int(&srcLine[nXSrc * srcByte], SrcFormat);
892 UINT32 oldColor = color;
893 UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette);
894 FreeRDPWriteColorIgnoreAlpha_int(&dstLine[nXDst * dstByte], DstFormat, dstColor);
895 for (int64_t x = 1; x < nWidth; x++)
897 color = FreeRDPReadColor_int(&srcLine[(x + nXSrc) * srcByte], SrcFormat);
898 if (color == oldColor)
900 FreeRDPWriteColorIgnoreAlpha_int(&dstLine[(x + nXDst) * dstByte], DstFormat,
906 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette);
907 FreeRDPWriteColorIgnoreAlpha_int(&dstLine[(x + nXDst) * dstByte], DstFormat,
916static inline BOOL freerdp_image_copy_no_overlap_dst_alpha(
917 BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
918 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat,
919 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
const gdiPalette* WINPR_RESTRICT palette,
920 int64_t srcVMultiplier, int64_t srcVOffset, int64_t dstVMultiplier, int64_t dstVOffset)
922 WINPR_ASSERT(pDstData);
923 WINPR_ASSERT(pSrcData);
927 case PIXEL_FORMAT_BGR24:
930 case PIXEL_FORMAT_BGRX32:
931 case PIXEL_FORMAT_BGRA32:
932 return freerdp_image_copy_bgr24_bgrx32(
933 pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, pSrcData, nSrcStep,
934 nXSrc, nYSrc, srcVMultiplier, srcVOffset, dstVMultiplier, dstVOffset);
939 case PIXEL_FORMAT_BGRX32:
940 case PIXEL_FORMAT_BGRA32:
943 case PIXEL_FORMAT_BGRX32:
944 case PIXEL_FORMAT_BGRA32:
945 return freerdp_image_copy_bgrx32_bgrx32(
946 pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, pSrcData, nSrcStep,
947 nXSrc, nYSrc, srcVMultiplier, srcVOffset, dstVMultiplier, dstVOffset);
956 return freerdp_image_copy_generic(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,
957 pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette,
958 srcVMultiplier, srcVOffset, dstVMultiplier, dstVOffset);
961BOOL freerdp_image_copy_overlap(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst,
962 UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
const BYTE* pSrcData,
963 DWORD SrcFormat, UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
964 const gdiPalette* WINPR_RESTRICT palette, UINT32 flags)
966 const UINT32 dstByte = FreeRDPGetBytesPerPixel(DstFormat);
967 const UINT32 srcByte = FreeRDPGetBytesPerPixel(SrcFormat);
968 const UINT32 copyDstWidth = nWidth * dstByte;
969 const UINT32 xSrcOffset = nXSrc * srcByte;
970 const UINT32 xDstOffset = nXDst * dstByte;
971 const BOOL vSrcVFlip = (flags & FREERDP_FLIP_VERTICAL) ? TRUE : FALSE;
972 int64_t srcVOffset = 0;
973 int64_t srcVMultiplier = 1;
974 int64_t dstVOffset = 0;
975 int64_t dstVMultiplier = 1;
977 WINPR_ASSERT(overlapping(pDstData, nYDst, nDstStep, pSrcData, nYSrc, nSrcStep, nHeight));
979 if ((nWidth == 0) || (nHeight == 0))
982 if ((nHeight > INT32_MAX) || (nWidth > INT32_MAX))
985 if (!pDstData || !pSrcData)
989 nDstStep = nWidth * FreeRDPGetBytesPerPixel(DstFormat);
992 nSrcStep = nWidth * FreeRDPGetBytesPerPixel(SrcFormat);
996 srcVOffset = (nHeight - 1ll) * nSrcStep;
1000 if (((flags & FREERDP_KEEP_DST_ALPHA) != 0) && FreeRDPColorHasAlpha(DstFormat))
1002 return freerdp_image_copy_no_overlap_dst_alpha(
1003 pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, pSrcData, SrcFormat,
1004 nSrcStep, nXSrc, nYSrc, palette, srcVMultiplier, srcVOffset, dstVMultiplier,
1007 else if (FreeRDPAreColorFormatsEqualNoAlpha_int(SrcFormat, DstFormat))
1012 for (int64_t y = 0; y < nHeight; y++)
1014 const BYTE* srcLine =
1015 &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset];
1016 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1017 memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
1021 else if (nYDst > nYSrc)
1023 for (int64_t y = nHeight - 1; y >= 0; y--)
1025 const BYTE* srcLine =
1026 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
1027 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1028 memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
1032 else if (nXSrc > nXDst)
1034 for (int64_t y = 0; y < nHeight; y++)
1036 const BYTE* srcLine =
1037 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
1038 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1039 memmove(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
1043 else if (nXSrc < nXDst)
1045 for (int64_t y = nHeight - 1; y >= 0; y--)
1047 const BYTE* srcLine =
1048 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
1049 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1050 memmove(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
1060 for (int64_t y = 0; y < nHeight; y++)
1062 const BYTE* srcLine = &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
1063 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1065 UINT32 color = FreeRDPReadColor_int(&srcLine[1ULL * nXSrc * srcByte], SrcFormat);
1066 UINT32 oldColor = color;
1067 UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette);
1068 FreeRDPWriteColor_int(&dstLine[1ULL * nXDst * dstByte], DstFormat, dstColor);
1069 for (int64_t x = 1; x < nWidth; x++)
1071 color = FreeRDPReadColor_int(&srcLine[(x + nXSrc) * srcByte], SrcFormat);
1072 if (color == oldColor)
1074 FreeRDPWriteColor_int(&dstLine[(x + nXDst) * dstByte], DstFormat, dstColor);
1079 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette);
1080 FreeRDPWriteColor_int(&dstLine[(x + nXDst) * dstByte], DstFormat, dstColor);
1089BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst,
1090 UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
const BYTE* pSrcData,
1091 DWORD SrcFormat, UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
1092 const gdiPalette* WINPR_RESTRICT palette, UINT32 flags)
1094 if ((nHeight > INT32_MAX) || (nWidth > INT32_MAX))
1097 if (!pDstData || !pSrcData)
1100 if ((nWidth == 0) || (nHeight == 0))
1104 nDstStep = nWidth * FreeRDPGetBytesPerPixel(DstFormat);
1107 nSrcStep = nWidth * FreeRDPGetBytesPerPixel(SrcFormat);
1109 const BOOL ovl = overlapping(pDstData, nYDst, nDstStep, pSrcData, nYSrc, nSrcStep, nHeight);
1111 return freerdp_image_copy_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth,
1112 nHeight, pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc,
1114 return freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth,
1115 nHeight, pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc,
1119BOOL freerdp_image_fill(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
1120 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight, UINT32 color)
1122 if ((nWidth == 0) || (nHeight == 0))
1124 const UINT32 bpp = FreeRDPGetBytesPerPixel(DstFormat);
1125 BYTE* WINPR_RESTRICT pFirstDstLine = NULL;
1126 BYTE* WINPR_RESTRICT pFirstDstLineXOffset = NULL;
1129 nDstStep = (nXDst + nWidth) * FreeRDPGetBytesPerPixel(DstFormat);
1131 pFirstDstLine = &pDstData[1ULL * nYDst * nDstStep];
1132 pFirstDstLineXOffset = &pFirstDstLine[1ULL * nXDst * bpp];
1134 for (
size_t x = 0; x < nWidth; x++)
1136 BYTE* pDst = &pFirstDstLine[(x + nXDst) * bpp];
1137 FreeRDPWriteColor_int(pDst, DstFormat, color);
1140 for (
size_t y = 1; y < nHeight; y++)
1142 BYTE* pDstLine = &pDstData[(y + nYDst) * nDstStep + 1ULL * nXDst * bpp];
1143 memcpy(pDstLine, pFirstDstLineXOffset, 1ull * nWidth * bpp);
1149BOOL freerdp_image_fill_ex(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
1150 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight, UINT32 color,
1153 if (FreeRDPColorHasAlpha(DstFormat) && ((flags & FREERDP_IMAGE_FILL_IGNORE_ALPHA) != 0))
1155 const UINT32 bpp = FreeRDPGetBytesPerPixel(DstFormat);
1159 FreeRDPSplitColor(color, DstFormat, &r, &g, &b, NULL, NULL);
1161 for (
size_t y = 0; y < nHeight; y++)
1163 BYTE* WINPR_RESTRICT line = &pDstData[(y + nYDst) * nDstStep];
1165 for (
size_t x = 0; x < nWidth; x++)
1167 BYTE* WINPR_RESTRICT dst = &line[x * bpp];
1168 const UINT32 dcolor = FreeRDPReadColor_int(dst, DstFormat);
1170 FreeRDPSplitColor(dcolor, DstFormat, NULL, NULL, NULL, &a, NULL);
1171 const UINT32 scolor = FreeRDPGetColor(DstFormat, r, g, b, a);
1172 if (!FreeRDPWriteColor_int(dst, DstFormat, scolor))
1178 return freerdp_image_fill(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, color);
1181#if defined(WITH_SWSCALE)
1182static enum AVPixelFormat av_format_for_buffer(UINT32 format)
1186 case PIXEL_FORMAT_ARGB32:
1187 return AV_PIX_FMT_BGRA;
1189 case PIXEL_FORMAT_XRGB32:
1190 return AV_PIX_FMT_BGR0;
1192 case PIXEL_FORMAT_BGRA32:
1193 return AV_PIX_FMT_RGBA;
1195 case PIXEL_FORMAT_BGRX32:
1196 return AV_PIX_FMT_RGB0;
1199 return AV_PIX_FMT_NONE;
1204BOOL freerdp_image_scale(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
1205 UINT32 nXDst, UINT32 nYDst, UINT32 nDstWidth, UINT32 nDstHeight,
1206 const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat, UINT32 nSrcStep,
1207 UINT32 nXSrc, UINT32 nYSrc, UINT32 nSrcWidth, UINT32 nSrcHeight)
1212 nDstStep = nDstWidth * FreeRDPGetBytesPerPixel(DstFormat);
1215 nSrcStep = nSrcWidth * FreeRDPGetBytesPerPixel(SrcFormat);
1217#if defined(WITH_SWSCALE) || defined(WITH_CAIRO)
1218 const BYTE* src = &pSrcData[nXSrc * FreeRDPGetBytesPerPixel(SrcFormat) + nYSrc * nSrcStep];
1219 BYTE* dst = &pDstData[nXDst * FreeRDPGetBytesPerPixel(DstFormat) + nYDst * nDstStep];
1223 if ((nDstWidth == nSrcWidth) && (nDstHeight == nSrcHeight))
1225 return freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nDstWidth,
1226 nDstHeight, pSrcData, SrcFormat, nSrcStep, nXSrc,
1227 nYSrc, NULL, FREERDP_FLIP_NONE);
1230#if defined(WITH_SWSCALE)
1233 struct SwsContext* resize = NULL;
1234 enum AVPixelFormat srcFormat = av_format_for_buffer(SrcFormat);
1235 enum AVPixelFormat dstFormat = av_format_for_buffer(DstFormat);
1236 const int srcStep[1] = { (int)nSrcStep };
1237 const int dstStep[1] = { (int)nDstStep };
1239 if ((srcFormat == AV_PIX_FMT_NONE) || (dstFormat == AV_PIX_FMT_NONE))
1242 resize = sws_getContext((
int)nSrcWidth, (
int)nSrcHeight, srcFormat, (
int)nDstWidth,
1243 (
int)nDstHeight, dstFormat, SWS_BILINEAR, NULL, NULL, NULL);
1248 res = sws_scale(resize, &src, srcStep, 0, (
int)nSrcHeight, &dst, dstStep);
1249 rc = (res == ((int)nDstHeight));
1251 sws_freeContext(resize);
1254#elif defined(WITH_CAIRO)
1256 const double sx = (double)nDstWidth / (
double)nSrcWidth;
1257 const double sy = (double)nDstHeight / (
double)nSrcHeight;
1258 cairo_t* cairo_context;
1259 cairo_surface_t *csrc, *cdst;
1261 if ((nSrcWidth > INT_MAX) || (nSrcHeight > INT_MAX) || (nSrcStep > INT_MAX))
1264 if ((nDstWidth > INT_MAX) || (nDstHeight > INT_MAX) || (nDstStep > INT_MAX))
1267 csrc = cairo_image_surface_create_for_data((
void*)src, CAIRO_FORMAT_ARGB32, (
int)nSrcWidth,
1268 (
int)nSrcHeight, (
int)nSrcStep);
1269 cdst = cairo_image_surface_create_for_data(dst, CAIRO_FORMAT_ARGB32, (
int)nDstWidth,
1270 (
int)nDstHeight, (
int)nDstStep);
1275 cairo_context = cairo_create(cdst);
1280 cairo_scale(cairo_context, sx, sy);
1281 cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
1282 cairo_set_source_surface(cairo_context, csrc, 0, 0);
1283 cairo_paint(cairo_context);
1286 cairo_destroy(cairo_context);
1288 cairo_surface_destroy(csrc);
1289 cairo_surface_destroy(cdst);
1293 WLog_WARN(TAG,
"SmartScaling requested but compiled without libcairo support!");
1299DWORD FreeRDPAreColorFormatsEqualNoAlpha(DWORD first, DWORD second)
1301 return FreeRDPAreColorFormatsEqualNoAlpha_int(first, second);
1304const char* FreeRDPGetColorFormatName(UINT32 format)
1312 ENTRY(PIXEL_FORMAT_ARGB32)
1313 ENTRY(PIXEL_FORMAT_XRGB32)
1314 ENTRY(PIXEL_FORMAT_ABGR32)
1315 ENTRY(PIXEL_FORMAT_XBGR32)
1316 ENTRY(PIXEL_FORMAT_BGRA32)
1317 ENTRY(PIXEL_FORMAT_BGRX32)
1318 ENTRY(PIXEL_FORMAT_RGBA32)
1319 ENTRY(PIXEL_FORMAT_RGBX32)
1320 ENTRY(PIXEL_FORMAT_BGRX32_DEPTH30)
1321 ENTRY(PIXEL_FORMAT_RGBX32_DEPTH30)
1322 ENTRY(PIXEL_FORMAT_RGB24)
1323 ENTRY(PIXEL_FORMAT_BGR24)
1324 ENTRY(PIXEL_FORMAT_RGB16)
1325 ENTRY(PIXEL_FORMAT_BGR16)
1326 ENTRY(PIXEL_FORMAT_ARGB15)
1327 ENTRY(PIXEL_FORMAT_RGB15)
1328 ENTRY(PIXEL_FORMAT_ABGR15)
1329 ENTRY(PIXEL_FORMAT_BGR15)
1330 ENTRY(PIXEL_FORMAT_RGB8)
1331 ENTRY(PIXEL_FORMAT_A4)
1332 ENTRY(PIXEL_FORMAT_MONO)
1340uint32_t FreeRDPGetColorFromatFromName(
const char* name)
1343 if (strcmp(name, #x) == 0) \
1349 ENTRY(PIXEL_FORMAT_ARGB32)
1350 ENTRY(PIXEL_FORMAT_XRGB32)
1351 ENTRY(PIXEL_FORMAT_ABGR32)
1352 ENTRY(PIXEL_FORMAT_XBGR32)
1353 ENTRY(PIXEL_FORMAT_BGRA32)
1354 ENTRY(PIXEL_FORMAT_BGRX32)
1355 ENTRY(PIXEL_FORMAT_RGBA32)
1356 ENTRY(PIXEL_FORMAT_RGBX32)
1357 ENTRY(PIXEL_FORMAT_BGRX32_DEPTH30)
1358 ENTRY(PIXEL_FORMAT_RGBX32_DEPTH30)
1359 ENTRY(PIXEL_FORMAT_RGB24)
1360 ENTRY(PIXEL_FORMAT_BGR24)
1361 ENTRY(PIXEL_FORMAT_RGB16)
1362 ENTRY(PIXEL_FORMAT_BGR16)
1363 ENTRY(PIXEL_FORMAT_ARGB15)
1364 ENTRY(PIXEL_FORMAT_RGB15)
1365 ENTRY(PIXEL_FORMAT_ABGR15)
1366 ENTRY(PIXEL_FORMAT_BGR15)
1367 ENTRY(PIXEL_FORMAT_RGB8)
1368 ENTRY(PIXEL_FORMAT_A4)
1369 ENTRY(PIXEL_FORMAT_MONO)
1375void FreeRDPSplitColor(UINT32 color, UINT32 format, BYTE* _r, BYTE* _g, BYTE* _b, BYTE* _a,
1376 const gdiPalette* palette)
1383 case PIXEL_FORMAT_ARGB32:
1385 *_a = (BYTE)(color >> 24);
1388 *_r = (BYTE)(color >> 16);
1391 *_g = (BYTE)(color >> 8);
1398 case PIXEL_FORMAT_XRGB32:
1400 *_r = (BYTE)(color >> 16);
1403 *_g = (BYTE)(color >> 8);
1413 case PIXEL_FORMAT_ABGR32:
1415 *_a = (BYTE)(color >> 24);
1418 *_b = (BYTE)(color >> 16);
1421 *_g = (BYTE)(color >> 8);
1428 case PIXEL_FORMAT_XBGR32:
1430 *_b = (BYTE)(color >> 16);
1433 *_g = (BYTE)(color >> 8);
1443 case PIXEL_FORMAT_RGBA32:
1445 *_r = (BYTE)(color >> 24);
1448 *_g = (BYTE)(color >> 16);
1451 *_b = (BYTE)(color >> 8);
1458 case PIXEL_FORMAT_RGBX32:
1460 *_r = (BYTE)(color >> 24);
1463 *_g = (BYTE)(color >> 16);
1466 *_b = (BYTE)(color >> 8);
1473 case PIXEL_FORMAT_BGRA32:
1475 *_b = (BYTE)(color >> 24);
1478 *_g = (BYTE)(color >> 16);
1481 *_r = (BYTE)(color >> 8);
1488 case PIXEL_FORMAT_BGRX32:
1490 *_b = (BYTE)(color >> 24);
1493 *_g = (BYTE)(color >> 16);
1496 *_r = (BYTE)(color >> 8);
1504 case PIXEL_FORMAT_RGB24:
1506 *_r = (BYTE)(color >> 16);
1509 *_g = (BYTE)(color >> 8);
1519 case PIXEL_FORMAT_BGR24:
1521 *_b = (BYTE)(color >> 16);
1524 *_g = (BYTE)(color >> 8);
1535 case PIXEL_FORMAT_RGB16:
1538 const UINT32 c = (color >> 11) & 0x1F;
1539 const UINT32 val = (c << 3) + c / 4;
1540 *_r = (BYTE)(val > 255 ? 255 : val);
1545 const UINT32 c = (color >> 5) & 0x3F;
1546 const UINT32 val = (c << 2) + c / 4 / 2;
1547 *_g = (BYTE)(val > 255 ? 255 : val);
1552 const UINT32 c = (color)&0x1F;
1553 const UINT32 val = (c << 3) + c / 4;
1554 *_b = (BYTE)(val > 255 ? 255 : val);
1562 case PIXEL_FORMAT_BGR16:
1565 const UINT32 c = (color)&0x1F;
1566 const UINT32 val = (c << 3) + c / 4;
1567 *_r = (BYTE)(val > 255 ? 255 : val);
1572 const UINT32 c = (color >> 5) & 0x3F;
1573 const UINT32 val = (c << 2) + c / 4 / 2;
1574 *_g = (BYTE)(val > 255 ? 255 : val);
1579 const UINT32 c = (color >> 11) & 0x1F;
1580 const UINT32 val = (c << 3) + c / 4;
1581 *_b = (BYTE)(val > 255 ? 255 : val);
1589 case PIXEL_FORMAT_ARGB15:
1592 const UINT32 c = (color >> 10) & 0x1F;
1593 const UINT32 val = (c << 3) + c / 4;
1594 *_r = (BYTE)(val > 255 ? 255 : val);
1599 const UINT32 c = (color >> 5) & 0x1F;
1600 const UINT32 val = (c << 3) + c / 4;
1601 *_g = (BYTE)(val > 255 ? 255 : val);
1606 const UINT32 c = (color)&0x1F;
1607 const UINT32 val = (c << 3) + c / 4;
1608 *_b = (BYTE)(val > 255 ? 255 : val);
1612 *_a = color & 0x8000 ? 0xFF : 0x00;
1616 case PIXEL_FORMAT_ABGR15:
1619 const UINT32 c = (color)&0x1F;
1620 const UINT32 val = (c << 3) + c / 4;
1621 *_r = (BYTE)(val > 255 ? 255 : val);
1626 const UINT32 c = (color >> 5) & 0x1F;
1627 const UINT32 val = (c << 3) + c / 4;
1628 *_g = (BYTE)(val > 255 ? 255 : val);
1633 const UINT32 c = (color >> 10) & 0x1F;
1634 const UINT32 val = (c << 3) + c / 4;
1635 *_b = (BYTE)(val > 255 ? 255 : val);
1639 *_a = color & 0x8000 ? 0xFF : 0x00;
1644 case PIXEL_FORMAT_RGB15:
1647 const UINT32 c = (color >> 10) & 0x1F;
1648 const UINT32 val = (c << 3) + c / 4;
1649 *_r = (BYTE)(val > 255 ? 255 : val);
1654 const UINT32 c = (color >> 5) & 0x1F;
1655 const UINT32 val = (c << 3) + c / 4;
1656 *_g = (BYTE)(val > 255 ? 255 : val);
1661 const UINT32 c = (color)&0x1F;
1662 const UINT32 val = (c << 3) + c / 4;
1663 *_b = (BYTE)(val > 255 ? 255 : val);
1671 case PIXEL_FORMAT_BGR15:
1674 const UINT32 c = (color)&0x1F;
1675 const UINT32 val = (c << 3) + c / 4;
1676 *_r = (BYTE)(val > 255 ? 255 : val);
1681 const UINT32 c = (color >> 5) & 0x1F;
1682 const UINT32 val = (c << 3) + c / 4;
1683 *_g = (BYTE)(val > 255 ? 255 : val);
1688 const UINT32 c = (color >> 10) & 0x1F;
1689 const UINT32 val = (c << 3) + c / 4;
1690 *_b = (BYTE)(val > 255 ? 255 : val);
1699 case PIXEL_FORMAT_RGB8:
1702 tmp = palette->palette[color];
1703 FreeRDPSplitColor(tmp, palette->format, _r, _g, _b, _a, NULL);
1723 case PIXEL_FORMAT_MONO:
1725 *_r = (color) ? 0xFF : 0x00;
1728 *_g = (color) ? 0xFF : 0x00;
1731 *_b = (color) ? 0xFF : 0x00;
1734 *_a = (color) ? 0xFF : 0x00;
1739 case PIXEL_FORMAT_A4:
1753 WLog_ERR(TAG,
"Unsupported format %s", FreeRDPGetColorFormatName(format));
1758BOOL FreeRDPWriteColorIgnoreAlpha(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT32 color)
1760 return FreeRDPWriteColorIgnoreAlpha_int(dst, format, color);
1763BOOL FreeRDPWriteColor(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT32 color)
1765 return FreeRDPWriteColor_int(dst, format, color);
1768UINT32 FreeRDPReadColor(
const BYTE* WINPR_RESTRICT src, UINT32 format)
1770 return FreeRDPReadColor_int(src, format);
1773UINT32 FreeRDPGetColor(UINT32 format, BYTE r, BYTE g, BYTE b, BYTE a)
1784 case PIXEL_FORMAT_ARGB32:
1785 return (_a << 24) | (_r << 16) | (_g << 8) | _b;
1787 case PIXEL_FORMAT_XRGB32:
1788 return (_r << 16) | (_g << 8) | _b;
1790 case PIXEL_FORMAT_ABGR32:
1791 return (_a << 24) | (_b << 16) | (_g << 8) | _r;
1793 case PIXEL_FORMAT_XBGR32:
1794 return (_b << 16) | (_g << 8) | _r;
1796 case PIXEL_FORMAT_RGBA32:
1797 return (_r << 24) | (_g << 16) | (_b << 8) | _a;
1799 case PIXEL_FORMAT_RGBX32:
1800 return (_r << 24) | (_g << 16) | (_b << 8) | _a;
1802 case PIXEL_FORMAT_BGRA32:
1803 return (_b << 24) | (_g << 16) | (_r << 8) | _a;
1805 case PIXEL_FORMAT_BGRX32:
1806 return (_b << 24) | (_g << 16) | (_r << 8) | _a;
1808 case PIXEL_FORMAT_RGBX32_DEPTH30:
1810 t = (_r << 22) | (_g << 12) | (_b << 2);
1812 return ((t & 0xff) << 24) | (((t >> 8) & 0xff) << 16) | (((t >> 16) & 0xff) << 8) |
1815 case PIXEL_FORMAT_BGRX32_DEPTH30:
1817 t = (_r << 22) | (_g << 12) | (_b << 2);
1819 return ((t & 0xff) << 24) | (((t >> 8) & 0xff) << 16) | (((t >> 16) & 0xff) << 8) |
1823 case PIXEL_FORMAT_RGB24:
1824 return (_r << 16) | (_g << 8) | _b;
1826 case PIXEL_FORMAT_BGR24:
1827 return (_b << 16) | (_g << 8) | _r;
1830 case PIXEL_FORMAT_RGB16:
1831 return (((_r >> 3) & 0x1F) << 11) | (((_g >> 2) & 0x3F) << 5) | ((_b >> 3) & 0x1F);
1833 case PIXEL_FORMAT_BGR16:
1834 return (((_b >> 3) & 0x1F) << 11) | (((_g >> 2) & 0x3F) << 5) | ((_r >> 3) & 0x1F);
1836 case PIXEL_FORMAT_ARGB15:
1837 return (((_r >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_b >> 3) & 0x1F) |
1838 (_a ? 0x8000 : 0x0000);
1840 case PIXEL_FORMAT_ABGR15:
1841 return (((_b >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_r >> 3) & 0x1F) |
1842 (_a ? 0x8000 : 0x0000);
1845 case PIXEL_FORMAT_RGB15:
1846 return (((_r >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_b >> 3) & 0x1F);
1848 case PIXEL_FORMAT_BGR15:
1849 return (((_b >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_r >> 3) & 0x1F);
1852 case PIXEL_FORMAT_RGB8:
1855 case PIXEL_FORMAT_A4:
1858 case PIXEL_FORMAT_MONO:
1860 WLog_ERR(TAG,
"Unsupported format %s", FreeRDPGetColorFormatName(format));
1865BOOL freerdp_image_copy_no_overlap(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
1866 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
1867 const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat,
1868 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
1869 const gdiPalette* WINPR_RESTRICT palette, UINT32 flags)
1873 prims = primitives_get();
1875 WINPR_ASSERT(!overlapping(pDstData, nYDst, nDstStep, pSrcData, nYSrc, nSrcStep, nHeight));
1876 WINPR_ASSERT(prims);
1878 return prims->
copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,
1879 pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette,
1880 flags) == PRIMITIVES_SUCCESS;
fn_copy_no_overlap_t copy_no_overlap