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 "image_ffmpeg.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>
56WINPR_ATTR_MALLOC(free, 1)
57static
char* get_dump_name(
char* prefix,
size_t len)
59 static uint64_t count = 0;
60 if (_snprintf(prefix, len,
"cursor_dump_%08" PRIx64, count++) < 0)
63 return GetCombinedPath(CURSOR_DUMP_DIR, prefix);
66static void dump_binary_data(FILE* fp,
const uint8_t* data,
size_t len)
69 (void)fprintf(fp,
"0x%02" PRIx8, data[0]);
70 for (
size_t x = 1; x < len; x++)
72 (void)fprintf(fp,
", 0x%02" PRIx8, data[x]);
76static void dump_uint_data(FILE* fp,
const uint32_t* data,
size_t len)
79 (void)fprintf(fp,
"0x%08" PRIx32, data[0]);
80 for (
size_t x = 1; x < len; x++)
82 (void)fprintf(fp,
", 0x%08" PRIx32, data[x]);
86static void dump_write_header(
const char* path,
const char* prefix)
88 char* header =
nullptr;
90 winpr_asprintf(&header, &headerlen,
"%s.h", path);
93 FILE* fp = fopen(header,
"w");
99 (void)fprintf(fp,
"/* FreeRDP cursor dump to use for unit tests\n");
100 (void)fprintf(fp,
" * this file was auto generated by %s\n", __func__);
101 (void)fprintf(fp,
" * do not modify manually\n");
102 (void)fprintf(fp,
" */\n");
103 (void)fprintf(fp,
"\n");
104 (void)fprintf(fp,
"#pragma once\n");
105 (void)fprintf(fp,
"\n");
106 (void)fprintf(fp,
"#include <freerdp/codec/color.h>\n");
107 (void)fprintf(fp,
"#include <freerdp/graphics.h>\n");
108 (void)fprintf(fp,
"\n");
109 (void)fprintf(fp,
"extern const gdiPalette %s_palette;\n", prefix);
110 (void)fprintf(fp,
"extern const rdpPointer %s_pointer;\n", prefix);
111 (void)fprintf(fp,
"extern const uint8_t %s_image_bgra32[];\n", prefix);
115static void dump_write_c_file(
const char* path,
const char* prefix, UINT32 nXDst, UINT32 nYDst,
116 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT xorMask,
117 UINT32 xorMaskLength,
const BYTE* WINPR_RESTRICT andMask,
118 UINT32 andMaskLength, UINT32 xorBpp,
const gdiPalette* palette,
121 const uint32_t format = PIXEL_FORMAT_BGRA32;
122 const uint32_t bpp = FreeRDPGetBytesPerPixel(format);
123 const uint32_t step = nWidth * bpp;
125 char* header =
nullptr;
126 size_t headerlen = 0;
127 winpr_asprintf(&header, &headerlen,
"%s.c", path);
130 FILE* fp = fopen(header,
"w");
135 (void)fprintf(fp,
"/* FreeRDP cursor dump to use for unit tests\n");
136 (void)fprintf(fp,
" * this file was auto generated by %s\n", __func__);
137 (void)fprintf(fp,
" * do not modify manually\n");
138 (void)fprintf(fp,
" */\n");
139 (void)fprintf(fp,
"\n");
140 (void)fprintf(fp,
"#include \"%s.h\"\n", prefix);
141 (void)fprintf(fp,
"\n");
143 (void)fprintf(fp,
"static const uint8_t andmask[] = {\n");
144 dump_binary_data(fp, andMask, andMaskLength);
145 (void)fprintf(fp,
"};\n");
146 (void)fprintf(fp,
"\n");
148 (void)fprintf(fp,
"static const uint8_t xormask[] = {\n");
149 dump_binary_data(fp, xorMask, xorMaskLength);
150 (void)fprintf(fp,
"};\n");
151 (void)fprintf(fp,
"\n");
152 (void)fprintf(fp,
"const gdiPalette %s_palette = {\n", prefix);
155 (void)fprintf(fp,
".format=%" PRIu32
",", palette->format);
156 (void)fprintf(fp,
".palette={");
157 dump_uint_data(fp, palette->palette, ARRAYSIZE(palette->palette));
158 (void)fprintf(fp,
"}\n");
161 (
void)fprintf(fp,
"0");
163 (void)fprintf(fp,
"};\n");
165 (void)fprintf(fp,
"\n");
166 (void)fprintf(fp,
"const rdpPointer %s_pointer = {\n", prefix);
167 (void)fprintf(fp,
".size = 0,\n");
168 (void)fprintf(fp,
".New = nullptr,\n");
169 (void)fprintf(fp,
".Free = nullptr,\n");
170 (void)fprintf(fp,
".Set = nullptr,\n");
171 (void)fprintf(fp,
".SetNull = nullptr,\n");
172 (void)fprintf(fp,
".SetDefault = nullptr,\n");
173 (void)fprintf(fp,
".SetPosition = nullptr,\n");
174 (void)fprintf(fp,
".paddingA = {0},\n");
175 (void)fprintf(fp,
".xPos = %" PRIu32
",\n", nXDst);
176 (void)fprintf(fp,
".yPos = %" PRIu32
",\n", nYDst);
177 (void)fprintf(fp,
".width = %" PRIu32
",\n", nWidth);
178 (void)fprintf(fp,
".height = %" PRIu32
",\n", nHeight);
179 (void)fprintf(fp,
".xorBpp = %" PRIu32
",\n", xorBpp);
180 (void)fprintf(fp,
".lengthAndMask = ARRAYSIZE(andmask),\n");
181 (void)fprintf(fp,
".lengthXorMask = ARRAYSIZE(xormask),\n");
182 (void)fprintf(fp,
".xorMaskData = xormask,\n");
183 (void)fprintf(fp,
".andMaskData = andmask,\n");
184 (void)fprintf(fp,
".paddingB = {0}\n");
185 (void)fprintf(fp,
"};\n");
186 (void)fprintf(fp,
"\n");
187 (void)fprintf(fp,
"const uint8_t %s_image_bgra32[]={\n", prefix);
188 dump_binary_data(fp, bmp, step * nHeight);
189 (void)fprintf(fp,
"};\n");
193 wImage* img = winpr_image_new();
196 img->data = WINPR_CAST_CONST_PTR_AWAY(bmp, BYTE*);
197 img->bitsPerPixel = 32;
198 img->bytesPerPixel = 4;
199 img->height = nHeight;
201 img->scanline = step;
202 img->type = WINPR_IMAGE_PNG;
203 char* imgname =
nullptr;
204 size_t imgnamesize = 0;
205 winpr_asprintf(&imgname, &imgnamesize,
"%s.png", path);
207 winpr_image_write(img, imgname);
209 winpr_image_free(img, FALSE);
218static void dump_pointer_data(UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
219 const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
220 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength,
221 UINT32 xorBpp,
const gdiPalette* palette)
223 const uint32_t format = PIXEL_FORMAT_BGRA32;
224 const uint32_t bpp = FreeRDPGetBytesPerPixel(format);
225 const uint32_t step = nWidth * bpp;
226 BYTE* bmp = calloc(step * 2, nHeight);
227 char prefix[64] = WINPR_C_ARRAY_INIT;
228 char* path = get_dump_name(prefix,
sizeof(prefix));
233 if (!freerdp_image_copy_from_pointer_data_int(bmp, format, step, 0, 0, nWidth, nHeight, xorMask,
234 xorMaskLength, andMask, andMaskLength, xorBpp,
238 dump_write_header(path, prefix);
239 dump_write_c_file(path, prefix, nXDst, nYDst, nWidth, nHeight, xorMask, xorMaskLength, andMask,
240 andMaskLength, xorBpp, palette, bmp);
248#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
249BYTE* freerdp_glyph_convert(UINT32 width, UINT32 height,
const BYTE* WINPR_RESTRICT data)
251 const size_t scanline = (width + 7ull) / 8ull;
252 const size_t required = scanline * height;
253 return freerdp_glyph_convert_ex(width, height, data, required);
257BYTE* freerdp_glyph_convert_ex(UINT32 width, UINT32 height,
const BYTE* WINPR_RESTRICT data,
265 const size_t scanline = (width + 7ull) / 8ull;
266 const size_t required = scanline * height;
270 if ((len == 0) || (width == 0) || (height == 0))
275 BYTE* dstData = (BYTE*)winpr_aligned_malloc(1ull * width * height, 16);
280 ZeroMemory(dstData, 1ULL * width * height);
281 BYTE* dstp = dstData;
283 for (UINT32 y = 0; y < height; y++)
285 const BYTE* srcp = &data[1ull * y * scanline];
287 for (UINT32 x = 0; x < width; x++)
289 if ((*srcp & (0x80 >> (x % 8))) != 0)
294 if (((x + 1) % 8 == 0) && x != 0)
302BOOL freerdp_image_copy_from_monochrome(BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,
303 UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT32 nWidth,
304 UINT32 nHeight,
const BYTE* WINPR_RESTRICT pSrcData,
305 UINT32 backColor, UINT32 foreColor,
306 const gdiPalette* WINPR_RESTRICT palette)
308 if (FreeRDPGetBitsPerPixel(DstFormat) == 0)
310 const UINT32 dstBytesPerPixel = FreeRDPGetBytesPerPixel(DstFormat);
312 if (!pDstData || !pSrcData || !palette)
316 nDstStep = dstBytesPerPixel * nWidth;
318 WINPR_ASSERT(1ull * nXDst + nWidth <= UINT32_MAX);
319 WINPR_ASSERT(nDstStep / FreeRDPGetBytesPerPixel(DstFormat) >= nXDst + nWidth);
321 const UINT32 monoStep = (nWidth + 7) / 8;
323 for (
size_t y = 0; y < nHeight; y++)
325 BYTE* pDstLine = &pDstData[((nYDst + y) * nDstStep)];
326 UINT32 monoBit = 0x80;
327 const BYTE* monoBits = &pSrcData[monoStep * y];
329 for (
size_t x = 0; x < nWidth; x++)
331 BYTE* pDstPixel = &pDstLine[((nXDst + x) * FreeRDPGetBytesPerPixel(DstFormat))];
332 BOOL monoPixel = (*monoBits & monoBit) != 0;
334 if (!(monoBit >>= 1))
342 if (!FreeRDPWriteColor_int(pDstPixel, DstFormat, backColor))
345 else if (!FreeRDPWriteColor_int(pDstPixel, DstFormat, foreColor))
353static inline UINT32 freerdp_image_inverted_pointer_color(UINT32 x, UINT32 y, UINT32 format)
364 BYTE fill = (x + y) & 1 ? 0x00 : 0xFF;
365 return FreeRDPGetColor(format, fill, fill, fill, 0xFF);
372static void fill_gdi_palette_for_icon(
const BYTE* colorTable, UINT16 cbColorTable,
375 WINPR_ASSERT(palette);
377 palette->format = PIXEL_FORMAT_BGRX32;
378 ZeroMemory(palette->palette,
sizeof(palette->palette));
383 if ((cbColorTable % 4 != 0) || (cbColorTable / 4 > 256))
385 WLog_WARN(TAG,
"weird palette size: %u", cbColorTable);
389 for (UINT16 i = 0; i < cbColorTable / 4; i++)
391 palette->palette[i] = FreeRDPReadColor_int(&colorTable[4ULL * i], palette->format);
395static inline UINT32 div_ceil(UINT32 a, UINT32 b)
397 return (a + (b - 1)) / b;
400static inline UINT32 round_up(UINT32 a, UINT32 b)
402 return b * div_ceil(a, b);
405BOOL freerdp_image_copy_from_icon_data(BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,
406 UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT16 nWidth,
407 UINT16 nHeight,
const BYTE* WINPR_RESTRICT bitsColor,
408 UINT16 cbBitsColor,
const BYTE* WINPR_RESTRICT bitsMask,
409 UINT16 cbBitsMask,
const BYTE* WINPR_RESTRICT colorTable,
410 UINT16 cbColorTable, UINT32 bpp)
415 if (!pDstData || !bitsColor)
418 if ((nWidth == 0) || (nHeight == 0))
420 if (FreeRDPGetBitsPerPixel(DstFormat) == 0)
423 WINPR_ASSERT((nDstStep == 0) || (nDstStep / FreeRDPGetBytesPerPixel(DstFormat) >= nWidth));
441 WLog_WARN(TAG,
"1bpp and 4bpp icons are not supported");
445 format = PIXEL_FORMAT_RGB8;
449 format = PIXEL_FORMAT_RGB15;
453 format = PIXEL_FORMAT_RGB24;
457 format = PIXEL_FORMAT_BGRA32;
461 WLog_WARN(TAG,
"invalid icon bpp: %" PRIu32, bpp);
466 if ((1ul * cbBitsColor) / nHeight < (1ul * FreeRDPGetBytesPerPixel(format) * nWidth))
469 "cbBitsColor{%" PRIu16
"} < nWidth{%" PRIu16
"} * nHeight{%" PRIu16
470 "} * bpp{%" PRIu32
"}",
471 cbBitsColor, nWidth, nHeight, FreeRDPGetBytesPerPixel(format));
475 fill_gdi_palette_for_icon(colorTable, cbColorTable, &palette);
476 if (!freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,
477 bitsColor, format, 0, 0, 0, &palette, FREERDP_FLIP_VERTICAL))
481 if (FreeRDPColorHasAlpha(DstFormat) && (cbBitsMask > 0))
483 BYTE* dstBuf = pDstData;
484 UINT32 dstBpp = FreeRDPGetBytesPerPixel(DstFormat);
491 const size_t stride = round_up(div_ceil(nWidth, 8), 4);
492 const size_t maskSize = stride * (nHeight - 1ULL) + div_ceil(nWidth, 8);
493 if (cbBitsMask < maskSize)
495 WLog_ERR(TAG,
"cbBitsMask{%" PRIu32
"} < required mask size{%" PRIuz
"}", cbBitsMask,
500 for (UINT32 y = 0; y < nHeight; y++)
502 const BYTE* maskByte = &bitsMask[stride * (nHeight - 1ULL - y)];
505 for (UINT32 x = 0; x < nWidth; x++)
510 BYTE alpha = (*maskByte & nextBit) ? 0x00 : 0xFF;
513 UINT32 color = FreeRDPReadColor_int(dstBuf, DstFormat);
514 FreeRDPSplitColor(color, DstFormat, &r, &g, &b,
nullptr, &palette);
515 color = FreeRDPGetColor(DstFormat, r, g, b, alpha);
516 if (!FreeRDPWriteColor_int(dstBuf, DstFormat, color))
533static BOOL freerdp_image_copy_from_pointer_data_1bpp(
534 BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
535 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
536 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength, UINT32 xorBpp)
546 vFlip = (xorBpp != 1);
547 andStep = (nWidth + 7) / 8;
548 andStep += (andStep % 2);
550 if (!xorMask || (xorMaskLength == 0))
552 if (!andMask || (andMaskLength == 0))
555 xorStep = (nWidth + 7) / 8;
556 xorStep += (xorStep % 2);
558 if (xorStep * nHeight > xorMaskLength)
561 if (andStep * nHeight > andMaskLength)
564 for (UINT32 y = 0; y < nHeight; y++)
566 const BYTE* andBits =
nullptr;
567 const BYTE* xorBits =
nullptr;
568 BYTE* pDstPixel = &pDstData[((1ULL * nYDst + y) * nDstStep) +
569 (1ULL * nXDst * FreeRDPGetBytesPerPixel(DstFormat))];
570 xorBit = andBit = 0x80;
574 xorBits = &xorMask[1ULL * xorStep * y];
575 andBits = &andMask[1ULL * andStep * y];
579 xorBits = &xorMask[1ULL * xorStep * (nHeight - y - 1)];
580 andBits = &andMask[1ULL * andStep * (nHeight - y - 1)];
583 for (UINT32 x = 0; x < nWidth; x++)
586 xorPixel = (*xorBits & xorBit) ? 1 : 0;
594 andPixel = (*andBits & andBit) ? 1 : 0;
602 if (!andPixel && !xorPixel)
603 color = FreeRDPGetColor(DstFormat, 0, 0, 0, 0xFF);
604 else if (!andPixel && xorPixel)
605 color = FreeRDPGetColor(DstFormat, 0xFF, 0xFF, 0xFF, 0xFF);
606 else if (andPixel && !xorPixel)
607 color = FreeRDPGetColor(DstFormat, 0, 0, 0, 0);
608 else if (andPixel && xorPixel)
609 color = freerdp_image_inverted_pointer_color(x, y, DstFormat);
611 if (!FreeRDPWriteColor_int(pDstPixel, DstFormat, color))
613 pDstPixel += FreeRDPGetBytesPerPixel(DstFormat);
620static BOOL freerdp_image_copy_from_pointer_data_xbpp(
621 BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
622 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
623 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength, UINT32 xorBpp,
624 const gdiPalette* palette)
632 UINT32 dstBitsPerPixel = 0;
633 UINT32 xorBytesPerPixel = 0;
634 dstBitsPerPixel = FreeRDPGetBitsPerPixel(DstFormat);
636 vFlip = (xorBpp != 1);
637 andStep = (nWidth + 7) / 8;
638 andStep += (andStep % 2);
640 if (!xorMask || (xorMaskLength == 0))
643 xorBytesPerPixel = xorBpp >> 3;
644 xorStep = 1ULL * nWidth * xorBytesPerPixel;
645 xorStep += (xorStep % 2);
647 if (xorBpp == 8 && !palette)
649 WLog_ERR(TAG,
"null palette in conversion from %" PRIu32
" bpp to %" PRIu32
" bpp", xorBpp,
654 if (xorStep * nHeight > xorMaskLength)
659 if (andStep * nHeight > andMaskLength)
663 for (UINT32 y = 0; y < nHeight; y++)
665 const BYTE* xorBits =
nullptr;
666 const BYTE* andBits =
nullptr;
667 BYTE* pDstPixel = &pDstData[((1ULL * nYDst + y) * nDstStep) +
668 (1ULL * nXDst * FreeRDPGetBytesPerPixel(DstFormat))];
674 andBits = &andMask[andStep * y];
676 xorBits = &xorMask[xorStep * y];
681 andBits = &andMask[1ULL * andStep * (nHeight - y - 1)];
683 xorBits = &xorMask[1ULL * xorStep * (nHeight - y - 1)];
686 for (UINT32 x = 0; x < nWidth; x++)
688 UINT32 pixelFormat = 0;
695 andPixel = (*andBits & andBit) ? 1 : 0;
706 pixelFormat = PIXEL_FORMAT_BGRA32;
707 xorPixel = FreeRDPReadColor_int(xorBits, pixelFormat);
709 else if (xorBpp == 16)
711 pixelFormat = PIXEL_FORMAT_RGB15;
712 xorPixel = FreeRDPReadColor_int(xorBits, pixelFormat);
714 else if (xorBpp == 8)
716 pixelFormat = palette->format;
717 xorPixel = palette->palette[xorBits[0]];
721 pixelFormat = PIXEL_FORMAT_BGR24;
722 xorPixel = FreeRDPReadColor_int(xorBits, pixelFormat);
726 if (xorPixel == 0x00FFFFFFUL)
727 xorPixel |= 0xFF000000UL;
732 xorPixel |= 0xFF000000UL;
735 pixelFormat = PIXEL_FORMAT_ABGR32;
738 xorPixel = FreeRDPConvertColor(xorPixel, pixelFormat, PIXEL_FORMAT_ARGB32, palette);
739 xorBits += xorBytesPerPixel;
743 if (xorPixel == 0xFF000000UL)
744 xorPixel = 0x00000000;
745 else if (xorPixel == 0xFFFFFFFFUL)
746 xorPixel = freerdp_image_inverted_pointer_color(x, y, PIXEL_FORMAT_ARGB32);
749 color = FreeRDPConvertColor(xorPixel, PIXEL_FORMAT_ARGB32, DstFormat, palette);
750 if (!FreeRDPWriteColor_int(pDstPixel, DstFormat, color))
752 pDstPixel += FreeRDPGetBytesPerPixel(DstFormat);
767BOOL freerdp_image_copy_from_pointer_data_int(
768 BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
769 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
770 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength, UINT32 xorBpp,
771 const gdiPalette* WINPR_RESTRICT palette)
773 if (FreeRDPGetBitsPerPixel(DstFormat) == 0)
776 UINT32 dstBitsPerPixel = FreeRDPGetBitsPerPixel(DstFormat);
777 UINT32 dstBytesPerPixel = FreeRDPGetBytesPerPixel(DstFormat);
779 WINPR_ASSERT(1ull * nXDst + nWidth <= UINT32_MAX);
781 nDstStep = dstBytesPerPixel * (1ull * nXDst + nWidth);
783 WINPR_ASSERT(nDstStep / FreeRDPGetBytesPerPixel(DstFormat) >= (1ull * nXDst + nWidth));
785 for (UINT32 y = nYDst; y < nHeight; y++)
787 BYTE* WINPR_RESTRICT pDstLine = &pDstData[y * nDstStep + nXDst * dstBytesPerPixel];
788 memset(pDstLine, 0, 1ull * dstBytesPerPixel * (nWidth - nXDst));
794 return freerdp_image_copy_from_pointer_data_1bpp(
795 pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, xorMask,
796 xorMaskLength, andMask, andMaskLength, xorBpp);
802 return freerdp_image_copy_from_pointer_data_xbpp(
803 pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, xorMask,
804 xorMaskLength, andMask, andMaskLength, xorBpp, palette);
807 WLog_ERR(TAG,
"failed to convert from %" PRIu32
" bpp to %" PRIu32
" bpp", xorBpp,
813BOOL freerdp_image_copy_from_pointer_data(BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,
814 UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
815 UINT32 nWidth, UINT32 nHeight,
816 const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
817 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength,
818 UINT32 xorBpp,
const gdiPalette* WINPR_RESTRICT palette)
820#if defined(WITH_CURSOR_DUMP)
821 dump_pointer_data(nXDst, nYDst, nWidth, nHeight, xorMask, xorMaskLength, andMask, andMaskLength,
824 return freerdp_image_copy_from_pointer_data_int(pDstData, DstFormat, nDstStep, nXDst, nYDst,
825 nWidth, nHeight, xorMask, xorMaskLength,
826 andMask, andMaskLength, xorBpp, palette);
829static inline BOOL overlapping(
const BYTE* pDstData, UINT32 nYDst, UINT32 nDstStep,
830 const BYTE* pSrcData, UINT32 nYSrc, UINT32 nSrcStep, UINT32 nHeight)
832 const uintptr_t src = (uintptr_t)pSrcData;
833 const uintptr_t srcstart = src + 1ULL * nSrcStep * nYSrc;
834 const uintptr_t srcend = srcstart + 1ULL * nSrcStep * nHeight;
835 const uintptr_t dst = (uintptr_t)pDstData;
836 const uintptr_t dststart = dst + 1ULL * nDstStep * nYDst;
837 const uintptr_t dstend = dststart + 1ULL * nDstStep * nHeight;
839 WINPR_ASSERT(nDstStep > 0);
840 WINPR_ASSERT(nSrcStep > 0);
841 if ((dststart >= srcstart) && (dststart < srcend))
844 if ((dstend > srcstart) && (dstend <= srcend))
850static inline BOOL freerdp_image_copy_bgr24_bgrx32(BYTE* WINPR_RESTRICT pDstData, UINT32 nDstStep,
851 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth,
853 const BYTE* WINPR_RESTRICT pSrcData,
854 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
855 int64_t srcVMultiplier, int64_t srcVOffset,
856 int64_t dstVMultiplier, int64_t dstVOffset)
859 const int64_t srcByte = 3;
860 const int64_t dstByte = 4;
862 for (int64_t y = 0; y < nHeight; y++)
864 const BYTE* WINPR_RESTRICT srcLine =
865 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
866 BYTE* WINPR_RESTRICT dstLine =
867 &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
869 for (int64_t x = 0; x < nWidth; x++)
871 dstLine[(x + nXDst) * dstByte + 0] = srcLine[(x + nXSrc) * srcByte + 0];
872 dstLine[(x + nXDst) * dstByte + 1] = srcLine[(x + nXSrc) * srcByte + 1];
873 dstLine[(x + nXDst) * dstByte + 2] = srcLine[(x + nXSrc) * srcByte + 2];
880static inline BOOL freerdp_image_copy_bgrx32_bgrx32(BYTE* WINPR_RESTRICT pDstData, UINT32 nDstStep,
881 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth,
883 const BYTE* WINPR_RESTRICT pSrcData,
884 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
885 int64_t srcVMultiplier, int64_t srcVOffset,
886 int64_t dstVMultiplier, int64_t dstVOffset)
889 const int64_t srcByte = 4;
890 const int64_t dstByte = 4;
892 for (int64_t y = 0; y < nHeight; y++)
894 const BYTE* WINPR_RESTRICT srcLine =
895 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
896 BYTE* WINPR_RESTRICT dstLine =
897 &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
899 for (int64_t x = 0; x < nWidth; x++)
901 dstLine[(x + nXDst) * dstByte + 0] = srcLine[(x + nXSrc) * srcByte + 0];
902 dstLine[(x + nXDst) * dstByte + 1] = srcLine[(x + nXSrc) * srcByte + 1];
903 dstLine[(x + nXDst) * dstByte + 2] = srcLine[(x + nXSrc) * srcByte + 2];
910static inline BOOL freerdp_image_copy_generic(
911 BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
912 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcFormat,
913 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
const gdiPalette* WINPR_RESTRICT palette,
914 int64_t srcVMultiplier, int64_t srcVOffset, int64_t dstVMultiplier, int64_t dstVOffset)
917 const int64_t srcByte = 4;
918 const int64_t dstByte = 4;
920 for (int64_t y = 0; y < nHeight; y++)
922 const BYTE* WINPR_RESTRICT srcLine =
923 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
924 BYTE* WINPR_RESTRICT dstLine =
925 &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
927 UINT32 color = FreeRDPReadColor_int(&srcLine[nXSrc * srcByte], SrcFormat);
928 UINT32 oldColor = color;
929 UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette);
930 if (!FreeRDPWriteColorIgnoreAlpha_int(&dstLine[nXDst * dstByte], DstFormat, dstColor))
933 for (int64_t x = 1; x < nWidth; x++)
935 color = FreeRDPReadColor_int(&srcLine[(x + nXSrc) * srcByte], SrcFormat);
936 if (color == oldColor)
938 if (!FreeRDPWriteColorIgnoreAlpha_int(&dstLine[(x + nXDst) * dstByte], DstFormat,
945 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette);
946 if (!FreeRDPWriteColorIgnoreAlpha_int(&dstLine[(x + nXDst) * dstByte], DstFormat,
956static inline BOOL freerdp_image_copy_no_overlap_dst_alpha(
957 BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
958 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat,
959 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
const gdiPalette* WINPR_RESTRICT palette,
960 int64_t srcVMultiplier, int64_t srcVOffset, int64_t dstVMultiplier, int64_t dstVOffset)
962 WINPR_ASSERT(pDstData);
963 WINPR_ASSERT(pSrcData);
967 case PIXEL_FORMAT_BGR24:
970 case PIXEL_FORMAT_BGRX32:
971 case PIXEL_FORMAT_BGRA32:
972 return freerdp_image_copy_bgr24_bgrx32(
973 pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, pSrcData, nSrcStep,
974 nXSrc, nYSrc, srcVMultiplier, srcVOffset, dstVMultiplier, dstVOffset);
979 case PIXEL_FORMAT_BGRX32:
980 case PIXEL_FORMAT_BGRA32:
983 case PIXEL_FORMAT_BGRX32:
984 case PIXEL_FORMAT_BGRA32:
985 return freerdp_image_copy_bgrx32_bgrx32(
986 pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, pSrcData, nSrcStep,
987 nXSrc, nYSrc, srcVMultiplier, srcVOffset, dstVMultiplier, dstVOffset);
996 return freerdp_image_copy_generic(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,
997 pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette,
998 srcVMultiplier, srcVOffset, dstVMultiplier, dstVOffset);
1001BOOL freerdp_image_copy_overlap(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst,
1002 UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
const BYTE* pSrcData,
1003 DWORD SrcFormat, UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
1004 const gdiPalette* WINPR_RESTRICT palette, UINT32 flags)
1006 const UINT32 dstByte = FreeRDPGetBytesPerPixel(DstFormat);
1007 const UINT32 srcByte = FreeRDPGetBytesPerPixel(SrcFormat);
1008 const UINT32 copyDstWidth = nWidth * dstByte;
1009 const UINT32 xSrcOffset = nXSrc * srcByte;
1010 const UINT32 xDstOffset = nXDst * dstByte;
1011 const BOOL vSrcVFlip = (flags & FREERDP_FLIP_VERTICAL) != 0;
1012 int64_t srcVOffset = 0;
1013 int64_t srcVMultiplier = 1;
1014 int64_t dstVOffset = 0;
1015 int64_t dstVMultiplier = 1;
1017 if ((nWidth == 0) || (nHeight == 0))
1020 if (FreeRDPGetBitsPerPixel(SrcFormat) == 0)
1022 if (FreeRDPGetBitsPerPixel(DstFormat) == 0)
1025 WINPR_ASSERT(1ull * nXDst + nWidth <= UINT32_MAX);
1026 WINPR_ASSERT(1ull * nXSrc + nWidth <= UINT32_MAX);
1027 WINPR_ASSERT(nDstStep / FreeRDPGetBytesPerPixel(DstFormat) >= nXDst + nWidth);
1028 WINPR_ASSERT(nSrcStep / FreeRDPGetBytesPerPixel(SrcFormat) >= nXSrc + nWidth);
1029 WINPR_ASSERT(overlapping(pDstData, nYDst, nDstStep, pSrcData, nYSrc, nSrcStep, nHeight));
1031 if ((nWidth == 0) || (nHeight == 0))
1034 if ((nHeight > INT32_MAX) || (nWidth > INT32_MAX))
1037 if (!pDstData || !pSrcData)
1041 nDstStep = (nXDst + nWidth) * FreeRDPGetBytesPerPixel(DstFormat);
1044 nSrcStep = (nXSrc + nWidth) * FreeRDPGetBytesPerPixel(SrcFormat);
1048 srcVOffset = (nHeight - 1ll) * nSrcStep;
1049 srcVMultiplier = -1;
1052 if (((flags & FREERDP_KEEP_DST_ALPHA) != 0) && FreeRDPColorHasAlpha(DstFormat))
1054 return freerdp_image_copy_no_overlap_dst_alpha(
1055 pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, pSrcData, SrcFormat,
1056 nSrcStep, nXSrc, nYSrc, palette, srcVMultiplier, srcVOffset, dstVMultiplier,
1059 else if (FreeRDPAreColorFormatsEqualNoAlpha_int(SrcFormat, DstFormat))
1064 for (int64_t y = 0; y < nHeight; y++)
1066 const BYTE* srcLine =
1067 &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset];
1068 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1069 memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
1073 else if (nYDst > nYSrc)
1075 for (int64_t y = nHeight - 1; y >= 0; y--)
1077 const BYTE* srcLine =
1078 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
1079 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1080 memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
1084 else if (nXSrc > nXDst)
1086 for (int64_t y = 0; y < nHeight; y++)
1088 const BYTE* srcLine =
1089 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
1090 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1091 memmove(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
1095 else if (nXSrc < nXDst)
1097 for (int64_t y = nHeight - 1; y >= 0; y--)
1099 const BYTE* srcLine =
1100 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
1101 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1102 memmove(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
1112 for (int64_t y = 0; y < nHeight; y++)
1114 const BYTE* srcLine = &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
1115 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1117 UINT32 color = FreeRDPReadColor_int(&srcLine[1ULL * nXSrc * srcByte], SrcFormat);
1118 UINT32 oldColor = color;
1119 UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette);
1120 if (!FreeRDPWriteColor_int(&dstLine[1ULL * nXDst * dstByte], DstFormat, dstColor))
1123 for (int64_t x = 1; x < nWidth; x++)
1125 color = FreeRDPReadColor_int(&srcLine[(x + nXSrc) * srcByte], SrcFormat);
1126 if (color == oldColor)
1128 if (!FreeRDPWriteColor_int(&dstLine[(x + nXDst) * dstByte], DstFormat,
1135 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette);
1136 if (!FreeRDPWriteColor_int(&dstLine[(x + nXDst) * dstByte], DstFormat,
1147BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst,
1148 UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
const BYTE* pSrcData,
1149 DWORD SrcFormat, UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
1150 const gdiPalette* WINPR_RESTRICT palette, UINT32 flags)
1152 if ((nHeight > INT32_MAX) || (nWidth > INT32_MAX))
1155 if (!pDstData || !pSrcData)
1158 if ((nWidth == 0) || (nHeight == 0))
1161 if (FreeRDPGetBitsPerPixel(SrcFormat) == 0)
1163 if (FreeRDPGetBitsPerPixel(DstFormat) == 0)
1166 WINPR_ASSERT(1ull * nXDst + nWidth <= UINT32_MAX);
1167 WINPR_ASSERT(1ull * nXSrc + nWidth <= UINT32_MAX);
1169 nDstStep = (nXDst + nWidth) * FreeRDPGetBytesPerPixel(DstFormat);
1172 nSrcStep = (nXSrc + nWidth) * FreeRDPGetBytesPerPixel(SrcFormat);
1174 WINPR_ASSERT(nDstStep / FreeRDPGetBytesPerPixel(DstFormat) >= nXDst + nWidth);
1175 WINPR_ASSERT(nSrcStep / FreeRDPGetBytesPerPixel(SrcFormat) >= nXSrc + nWidth);
1177 const BOOL ovl = overlapping(pDstData, nYDst, nDstStep, pSrcData, nYSrc, nSrcStep, nHeight);
1179 return freerdp_image_copy_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth,
1180 nHeight, pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc,
1182 return freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth,
1183 nHeight, pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc,
1187BOOL freerdp_image_fill(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
1188 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight, UINT32 color)
1190 if ((nWidth == 0) || (nHeight == 0))
1193 if (FreeRDPGetBitsPerPixel(DstFormat) == 0)
1196 const UINT32 bpp = FreeRDPGetBytesPerPixel(DstFormat);
1197 BYTE* WINPR_RESTRICT pFirstDstLine =
nullptr;
1198 BYTE* WINPR_RESTRICT pFirstDstLineXOffset =
nullptr;
1200 WINPR_ASSERT(1ull * nXDst + nWidth <= UINT32_MAX);
1202 nDstStep = (nXDst + nWidth) * FreeRDPGetBytesPerPixel(DstFormat);
1204 WINPR_ASSERT(nDstStep / FreeRDPGetBytesPerPixel(DstFormat) >= nXDst + nWidth);
1205 pFirstDstLine = &pDstData[1ULL * nYDst * nDstStep];
1206 pFirstDstLineXOffset = &pFirstDstLine[1ULL * nXDst * bpp];
1208 for (
size_t x = 0; x < nWidth; x++)
1210 BYTE* pDst = &pFirstDstLine[(x + nXDst) * bpp];
1211 if (!FreeRDPWriteColor_int(pDst, DstFormat, color))
1215 for (
size_t y = 1; y < nHeight; y++)
1217 BYTE* pDstLine = &pDstData[(y + nYDst) * nDstStep + 1ULL * nXDst * bpp];
1218 memcpy(pDstLine, pFirstDstLineXOffset, 1ull * nWidth * bpp);
1224BOOL freerdp_image_fill_ex(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
1225 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight, UINT32 color,
1228 if (FreeRDPGetBitsPerPixel(DstFormat) == 0)
1231 WINPR_ASSERT(pDstData);
1232 WINPR_ASSERT(1ull * nXDst + nWidth <= UINT32_MAX);
1233 WINPR_ASSERT(nDstStep / FreeRDPGetBytesPerPixel(DstFormat) >= nXDst + nWidth);
1235 if (FreeRDPColorHasAlpha(DstFormat) && ((flags & FREERDP_IMAGE_FILL_IGNORE_ALPHA) != 0))
1237 const UINT32 bpp = FreeRDPGetBytesPerPixel(DstFormat);
1241 FreeRDPSplitColor(color, DstFormat, &r, &g, &b,
nullptr,
nullptr);
1243 for (
size_t y = 0; y < nHeight; y++)
1245 BYTE* WINPR_RESTRICT line = &pDstData[(y + nYDst) * nDstStep];
1247 for (
size_t x = 0; x < nWidth; x++)
1249 BYTE* WINPR_RESTRICT dst = &line[x * bpp];
1250 const UINT32 dcolor = FreeRDPReadColor_int(dst, DstFormat);
1252 FreeRDPSplitColor(dcolor, DstFormat,
nullptr,
nullptr,
nullptr, &a,
nullptr);
1253 const UINT32 scolor = FreeRDPGetColor(DstFormat, r, g, b, a);
1254 if (!FreeRDPWriteColor_int(dst, DstFormat, scolor))
1260 return freerdp_image_fill(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, color);
1263#if defined(WITH_SWSCALE)
1264static enum AVPixelFormat av_format_for_buffer(UINT32 format)
1268 case PIXEL_FORMAT_ARGB32:
1269 return AV_PIX_FMT_BGRA;
1271 case PIXEL_FORMAT_XRGB32:
1272 return AV_PIX_FMT_BGR0;
1274 case PIXEL_FORMAT_BGRA32:
1275 return AV_PIX_FMT_RGBA;
1277 case PIXEL_FORMAT_BGRX32:
1278 return AV_PIX_FMT_RGB0;
1281 return AV_PIX_FMT_NONE;
1286BOOL freerdp_image_scale(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
1287 UINT32 nXDst, UINT32 nYDst, UINT32 nDstWidth, UINT32 nDstHeight,
1288 const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat, UINT32 nSrcStep,
1289 UINT32 nXSrc, UINT32 nYSrc, UINT32 nSrcWidth, UINT32 nSrcHeight)
1292 if (FreeRDPGetBitsPerPixel(SrcFormat) == 0)
1294 if (FreeRDPGetBitsPerPixel(DstFormat) == 0)
1297 WINPR_ASSERT(1ull * nXDst + nDstWidth <= UINT32_MAX);
1298 WINPR_ASSERT(1ull * nXSrc + nSrcWidth <= UINT32_MAX);
1300 nDstStep = (nXDst + nDstWidth) * FreeRDPGetBytesPerPixel(DstFormat);
1303 nSrcStep = (nXSrc + nSrcWidth) * FreeRDPGetBytesPerPixel(SrcFormat);
1305 WINPR_ASSERT(nDstStep / FreeRDPGetBytesPerPixel(DstFormat) >= nXDst + nDstWidth);
1306 WINPR_ASSERT(nSrcStep / FreeRDPGetBytesPerPixel(SrcFormat) >= nXSrc + nSrcWidth);
1308#if defined(WITH_SWSCALE) || defined(WITH_CAIRO)
1309 const BYTE* src = &pSrcData[nXSrc * FreeRDPGetBytesPerPixel(SrcFormat) + nYSrc * nSrcStep];
1310 BYTE* dst = &pDstData[nXDst * FreeRDPGetBytesPerPixel(DstFormat) + nYDst * nDstStep];
1314 if ((nDstWidth == nSrcWidth) && (nDstHeight == nSrcHeight))
1316 return freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nDstWidth,
1317 nDstHeight, pSrcData, SrcFormat, nSrcStep, nXSrc,
1318 nYSrc,
nullptr, FREERDP_FLIP_NONE);
1321#if defined(WITH_SWSCALE)
1324 struct SwsContext* resize =
nullptr;
1325 enum AVPixelFormat srcFormat = av_format_for_buffer(SrcFormat);
1326 enum AVPixelFormat dstFormat = av_format_for_buffer(DstFormat);
1327 const int srcStep[1] = { (int)nSrcStep };
1328 const int dstStep[1] = { (int)nDstStep };
1330 if ((srcFormat == AV_PIX_FMT_NONE) || (dstFormat == AV_PIX_FMT_NONE))
1333 if (!freerdp_swscale_available())
1335 WLog_WARN(TAG,
"swscale not available");
1339 resize = freerdp_sws_getContext((
int)nSrcWidth, (
int)nSrcHeight, srcFormat, (
int)nDstWidth,
1340 (
int)nDstHeight, dstFormat, SWS_BILINEAR,
nullptr,
nullptr,
1347 const BYTE* srcSlice[4] = { src,
nullptr,
nullptr,
nullptr };
1348 BYTE* dstSlice[4] = { dst,
nullptr,
nullptr,
nullptr };
1349 const int srcSteps[4] = { srcStep[0], 0, 0, 0 };
1350 const int dstSteps[4] = { dstStep[0], 0, 0, 0 };
1352 res = freerdp_sws_scale(resize, srcSlice, srcSteps, 0, (
int)nSrcHeight, dstSlice, dstSteps);
1353 rc = (res == ((int)nDstHeight));
1355 freerdp_sws_freeContext(resize);
1358#elif defined(WITH_CAIRO)
1360 const double sx = (double)nDstWidth / (
double)nSrcWidth;
1361 const double sy = (double)nDstHeight / (
double)nSrcHeight;
1362 cairo_t* cairo_context;
1363 cairo_surface_t *csrc, *cdst;
1365 if ((nSrcWidth > INT_MAX) || (nSrcHeight > INT_MAX) || (nSrcStep > INT_MAX))
1368 if ((nDstWidth > INT_MAX) || (nDstHeight > INT_MAX) || (nDstStep > INT_MAX))
1371 csrc = cairo_image_surface_create_for_data((
void*)src, CAIRO_FORMAT_ARGB32, (
int)nSrcWidth,
1372 (
int)nSrcHeight, (
int)nSrcStep);
1373 cdst = cairo_image_surface_create_for_data(dst, CAIRO_FORMAT_ARGB32, (
int)nDstWidth,
1374 (
int)nDstHeight, (
int)nDstStep);
1379 cairo_context = cairo_create(cdst);
1384 cairo_scale(cairo_context, sx, sy);
1385 cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
1386 cairo_set_source_surface(cairo_context, csrc, 0, 0);
1387 cairo_paint(cairo_context);
1390 cairo_destroy(cairo_context);
1392 cairo_surface_destroy(csrc);
1393 cairo_surface_destroy(cdst);
1397 WLog_WARN(TAG,
"SmartScaling requested but compiled without libcairo support!");
1403DWORD FreeRDPAreColorFormatsEqualNoAlpha(DWORD first, DWORD second)
1405 return FreeRDPAreColorFormatsEqualNoAlpha_int(first, second);
1408const char* FreeRDPGetColorFormatName(UINT32 format)
1416 ENTRY(PIXEL_FORMAT_ARGB32)
1417 ENTRY(PIXEL_FORMAT_XRGB32)
1418 ENTRY(PIXEL_FORMAT_ABGR32)
1419 ENTRY(PIXEL_FORMAT_XBGR32)
1420 ENTRY(PIXEL_FORMAT_BGRA32)
1421 ENTRY(PIXEL_FORMAT_BGRX32)
1422 ENTRY(PIXEL_FORMAT_RGBA32)
1423 ENTRY(PIXEL_FORMAT_RGBX32)
1424 ENTRY(PIXEL_FORMAT_BGRX32_DEPTH30)
1425 ENTRY(PIXEL_FORMAT_RGBX32_DEPTH30)
1426 ENTRY(PIXEL_FORMAT_RGB24)
1427 ENTRY(PIXEL_FORMAT_BGR24)
1428 ENTRY(PIXEL_FORMAT_RGB16)
1429 ENTRY(PIXEL_FORMAT_BGR16)
1430 ENTRY(PIXEL_FORMAT_ARGB15)
1431 ENTRY(PIXEL_FORMAT_RGB15)
1432 ENTRY(PIXEL_FORMAT_ABGR15)
1433 ENTRY(PIXEL_FORMAT_BGR15)
1434 ENTRY(PIXEL_FORMAT_RGB8)
1435 ENTRY(PIXEL_FORMAT_A4)
1436 ENTRY(PIXEL_FORMAT_MONO)
1444uint32_t FreeRDPGetColorFromatFromName(
const char* name)
1447 if (strcmp(name, #x) == 0) \
1453 ENTRY(PIXEL_FORMAT_ARGB32)
1454 ENTRY(PIXEL_FORMAT_XRGB32)
1455 ENTRY(PIXEL_FORMAT_ABGR32)
1456 ENTRY(PIXEL_FORMAT_XBGR32)
1457 ENTRY(PIXEL_FORMAT_BGRA32)
1458 ENTRY(PIXEL_FORMAT_BGRX32)
1459 ENTRY(PIXEL_FORMAT_RGBA32)
1460 ENTRY(PIXEL_FORMAT_RGBX32)
1461 ENTRY(PIXEL_FORMAT_BGRX32_DEPTH30)
1462 ENTRY(PIXEL_FORMAT_RGBX32_DEPTH30)
1463 ENTRY(PIXEL_FORMAT_RGB24)
1464 ENTRY(PIXEL_FORMAT_BGR24)
1465 ENTRY(PIXEL_FORMAT_RGB16)
1466 ENTRY(PIXEL_FORMAT_BGR16)
1467 ENTRY(PIXEL_FORMAT_ARGB15)
1468 ENTRY(PIXEL_FORMAT_RGB15)
1469 ENTRY(PIXEL_FORMAT_ABGR15)
1470 ENTRY(PIXEL_FORMAT_BGR15)
1471 ENTRY(PIXEL_FORMAT_RGB8)
1472 ENTRY(PIXEL_FORMAT_A4)
1473 ENTRY(PIXEL_FORMAT_MONO)
1479void FreeRDPSplitColor(UINT32 color, UINT32 format, BYTE* _r, BYTE* _g, BYTE* _b, BYTE* _a,
1480 const gdiPalette* palette)
1487 case PIXEL_FORMAT_ARGB32:
1489 *_a = (BYTE)(color >> 24);
1492 *_r = (BYTE)(color >> 16);
1495 *_g = (BYTE)(color >> 8);
1502 case PIXEL_FORMAT_XRGB32:
1504 *_r = (BYTE)(color >> 16);
1507 *_g = (BYTE)(color >> 8);
1517 case PIXEL_FORMAT_ABGR32:
1519 *_a = (BYTE)(color >> 24);
1522 *_b = (BYTE)(color >> 16);
1525 *_g = (BYTE)(color >> 8);
1532 case PIXEL_FORMAT_XBGR32:
1534 *_b = (BYTE)(color >> 16);
1537 *_g = (BYTE)(color >> 8);
1547 case PIXEL_FORMAT_RGBA32:
1549 *_r = (BYTE)(color >> 24);
1552 *_g = (BYTE)(color >> 16);
1555 *_b = (BYTE)(color >> 8);
1562 case PIXEL_FORMAT_RGBX32:
1564 *_r = (BYTE)(color >> 24);
1567 *_g = (BYTE)(color >> 16);
1570 *_b = (BYTE)(color >> 8);
1577 case PIXEL_FORMAT_BGRA32:
1579 *_b = (BYTE)(color >> 24);
1582 *_g = (BYTE)(color >> 16);
1585 *_r = (BYTE)(color >> 8);
1592 case PIXEL_FORMAT_BGRX32:
1594 *_b = (BYTE)(color >> 24);
1597 *_g = (BYTE)(color >> 16);
1600 *_r = (BYTE)(color >> 8);
1608 case PIXEL_FORMAT_RGB24:
1610 *_r = (BYTE)(color >> 16);
1613 *_g = (BYTE)(color >> 8);
1623 case PIXEL_FORMAT_BGR24:
1625 *_b = (BYTE)(color >> 16);
1628 *_g = (BYTE)(color >> 8);
1639 case PIXEL_FORMAT_RGB16:
1642 const UINT32 c = (color >> 11) & 0x1F;
1643 const UINT32 val = (c << 3) + c / 4;
1644 *_r = (BYTE)(val > 255 ? 255 : val);
1649 const UINT32 c = (color >> 5) & 0x3F;
1650 const UINT32 val = (c << 2) + c / 4 / 2;
1651 *_g = (BYTE)(val > 255 ? 255 : val);
1656 const UINT32 c = (color)&0x1F;
1657 const UINT32 val = (c << 3) + c / 4;
1658 *_b = (BYTE)(val > 255 ? 255 : val);
1666 case PIXEL_FORMAT_BGR16:
1669 const UINT32 c = (color)&0x1F;
1670 const UINT32 val = (c << 3) + c / 4;
1671 *_r = (BYTE)(val > 255 ? 255 : val);
1676 const UINT32 c = (color >> 5) & 0x3F;
1677 const UINT32 val = (c << 2) + c / 4 / 2;
1678 *_g = (BYTE)(val > 255 ? 255 : val);
1683 const UINT32 c = (color >> 11) & 0x1F;
1684 const UINT32 val = (c << 3) + c / 4;
1685 *_b = (BYTE)(val > 255 ? 255 : val);
1693 case PIXEL_FORMAT_ARGB15:
1696 const UINT32 c = (color >> 10) & 0x1F;
1697 const UINT32 val = (c << 3) + c / 4;
1698 *_r = (BYTE)(val > 255 ? 255 : val);
1703 const UINT32 c = (color >> 5) & 0x1F;
1704 const UINT32 val = (c << 3) + c / 4;
1705 *_g = (BYTE)(val > 255 ? 255 : val);
1710 const UINT32 c = (color)&0x1F;
1711 const UINT32 val = (c << 3) + c / 4;
1712 *_b = (BYTE)(val > 255 ? 255 : val);
1716 *_a = color & 0x8000 ? 0xFF : 0x00;
1720 case PIXEL_FORMAT_ABGR15:
1723 const UINT32 c = (color)&0x1F;
1724 const UINT32 val = (c << 3) + c / 4;
1725 *_r = (BYTE)(val > 255 ? 255 : val);
1730 const UINT32 c = (color >> 5) & 0x1F;
1731 const UINT32 val = (c << 3) + c / 4;
1732 *_g = (BYTE)(val > 255 ? 255 : val);
1737 const UINT32 c = (color >> 10) & 0x1F;
1738 const UINT32 val = (c << 3) + c / 4;
1739 *_b = (BYTE)(val > 255 ? 255 : val);
1743 *_a = color & 0x8000 ? 0xFF : 0x00;
1748 case PIXEL_FORMAT_RGB15:
1751 const UINT32 c = (color >> 10) & 0x1F;
1752 const UINT32 val = (c << 3) + c / 4;
1753 *_r = (BYTE)(val > 255 ? 255 : val);
1758 const UINT32 c = (color >> 5) & 0x1F;
1759 const UINT32 val = (c << 3) + c / 4;
1760 *_g = (BYTE)(val > 255 ? 255 : val);
1765 const UINT32 c = (color)&0x1F;
1766 const UINT32 val = (c << 3) + c / 4;
1767 *_b = (BYTE)(val > 255 ? 255 : val);
1775 case PIXEL_FORMAT_BGR15:
1778 const UINT32 c = (color)&0x1F;
1779 const UINT32 val = (c << 3) + c / 4;
1780 *_r = (BYTE)(val > 255 ? 255 : val);
1785 const UINT32 c = (color >> 5) & 0x1F;
1786 const UINT32 val = (c << 3) + c / 4;
1787 *_g = (BYTE)(val > 255 ? 255 : val);
1792 const UINT32 c = (color >> 10) & 0x1F;
1793 const UINT32 val = (c << 3) + c / 4;
1794 *_b = (BYTE)(val > 255 ? 255 : val);
1803 case PIXEL_FORMAT_RGB8:
1806 tmp = palette->palette[color];
1807 FreeRDPSplitColor(tmp, palette->format, _r, _g, _b, _a,
nullptr);
1827 case PIXEL_FORMAT_MONO:
1829 *_r = (color) ? 0xFF : 0x00;
1832 *_g = (color) ? 0xFF : 0x00;
1835 *_b = (color) ? 0xFF : 0x00;
1838 *_a = (color) ? 0xFF : 0x00;
1843 case PIXEL_FORMAT_A4:
1857 WLog_ERR(TAG,
"Unsupported format %s", FreeRDPGetColorFormatName(format));
1862BOOL FreeRDPWriteColorIgnoreAlpha(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT32 color)
1864 return FreeRDPWriteColorIgnoreAlpha_int(dst, format, color);
1867BOOL FreeRDPWriteColor(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT32 color)
1869 return FreeRDPWriteColor_int(dst, format, color);
1872UINT32 FreeRDPReadColor(
const BYTE* WINPR_RESTRICT src, UINT32 format)
1874 return FreeRDPReadColor_int(src, format);
1877UINT32 FreeRDPGetColor(UINT32 format, BYTE r, BYTE g, BYTE b, BYTE a)
1888 case PIXEL_FORMAT_ARGB32:
1889 return (_a << 24) | (_r << 16) | (_g << 8) | _b;
1891 case PIXEL_FORMAT_XRGB32:
1892 return (_r << 16) | (_g << 8) | _b;
1894 case PIXEL_FORMAT_ABGR32:
1895 return (_a << 24) | (_b << 16) | (_g << 8) | _r;
1897 case PIXEL_FORMAT_XBGR32:
1898 return (_b << 16) | (_g << 8) | _r;
1900 case PIXEL_FORMAT_RGBA32:
1901 return (_r << 24) | (_g << 16) | (_b << 8) | _a;
1903 case PIXEL_FORMAT_RGBX32:
1904 return (_r << 24) | (_g << 16) | (_b << 8) | _a;
1906 case PIXEL_FORMAT_BGRA32:
1907 return (_b << 24) | (_g << 16) | (_r << 8) | _a;
1909 case PIXEL_FORMAT_BGRX32:
1910 return (_b << 24) | (_g << 16) | (_r << 8) | _a;
1912 case PIXEL_FORMAT_RGBX32_DEPTH30:
1914 t = (_r << 22) | (_g << 12) | (_b << 2);
1916 return ((t & 0xff) << 24) | (((t >> 8) & 0xff) << 16) | (((t >> 16) & 0xff) << 8) |
1919 case PIXEL_FORMAT_BGRX32_DEPTH30:
1921 t = (_r << 22) | (_g << 12) | (_b << 2);
1923 return ((t & 0xff) << 24) | (((t >> 8) & 0xff) << 16) | (((t >> 16) & 0xff) << 8) |
1927 case PIXEL_FORMAT_RGB24:
1928 return (_r << 16) | (_g << 8) | _b;
1930 case PIXEL_FORMAT_BGR24:
1931 return (_b << 16) | (_g << 8) | _r;
1934 case PIXEL_FORMAT_RGB16:
1935 return (((_r >> 3) & 0x1F) << 11) | (((_g >> 2) & 0x3F) << 5) | ((_b >> 3) & 0x1F);
1937 case PIXEL_FORMAT_BGR16:
1938 return (((_b >> 3) & 0x1F) << 11) | (((_g >> 2) & 0x3F) << 5) | ((_r >> 3) & 0x1F);
1940 case PIXEL_FORMAT_ARGB15:
1941 return (((_r >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_b >> 3) & 0x1F) |
1942 (_a ? 0x8000 : 0x0000);
1944 case PIXEL_FORMAT_ABGR15:
1945 return (((_b >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_r >> 3) & 0x1F) |
1946 (_a ? 0x8000 : 0x0000);
1949 case PIXEL_FORMAT_RGB15:
1950 return (((_r >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_b >> 3) & 0x1F);
1952 case PIXEL_FORMAT_BGR15:
1953 return (((_b >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_r >> 3) & 0x1F);
1956 case PIXEL_FORMAT_RGB8:
1959 case PIXEL_FORMAT_A4:
1962 case PIXEL_FORMAT_MONO:
1964 WLog_ERR(TAG,
"Unsupported format %s", FreeRDPGetColorFormatName(format));
1969BOOL freerdp_image_copy_no_overlap(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
1970 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
1971 const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat,
1972 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
1973 const gdiPalette* WINPR_RESTRICT palette, UINT32 flags)
1977 prims = primitives_get();
1979 if (FreeRDPGetBitsPerPixel(SrcFormat) == 0)
1981 if (FreeRDPGetBitsPerPixel(DstFormat) == 0)
1984 if ((nWidth == 0) || (nHeight == 0))
1987 WINPR_ASSERT(1ull * nXDst + nWidth <= UINT32_MAX);
1988 WINPR_ASSERT(1ull * nXSrc + nWidth <= UINT32_MAX);
1990 nDstStep = (nXDst + nWidth) * FreeRDPGetBytesPerPixel(DstFormat);
1992 nSrcStep = (nXSrc + nWidth) * FreeRDPGetBytesPerPixel(SrcFormat);
1994 WINPR_ASSERT(nDstStep / FreeRDPGetBytesPerPixel(DstFormat) >= nXDst + nWidth);
1995 WINPR_ASSERT(nSrcStep / FreeRDPGetBytesPerPixel(SrcFormat) >= nXSrc + nWidth);
1996 WINPR_ASSERT(!overlapping(pDstData, nYDst, nDstStep, pSrcData, nYSrc, nSrcStep, nHeight));
1997 WINPR_ASSERT(prims);
1999 return prims->
copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,
2000 pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette,
2001 flags) == PRIMITIVES_SUCCESS;
WINPR_ATTR_NODISCARD fn_copy_no_overlap_t copy_no_overlap