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_calloc(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) && !FreeRDPColorHasAlpha(format) && (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_scaling_supported(
void)
1288#if defined(WITH_SWSCALE) || defined(WITH_CAIRO)
1295BOOL freerdp_image_scale(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
1296 UINT32 nXDst, UINT32 nYDst, UINT32 nDstWidth, UINT32 nDstHeight,
1297 const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat, UINT32 nSrcStep,
1298 UINT32 nXSrc, UINT32 nYSrc, UINT32 nSrcWidth, UINT32 nSrcHeight)
1301 if (FreeRDPGetBitsPerPixel(SrcFormat) == 0)
1303 if (FreeRDPGetBitsPerPixel(DstFormat) == 0)
1306 WINPR_ASSERT(1ull * nXDst + nDstWidth <= UINT32_MAX);
1307 WINPR_ASSERT(1ull * nXSrc + nSrcWidth <= UINT32_MAX);
1309 nDstStep = (nXDst + nDstWidth) * FreeRDPGetBytesPerPixel(DstFormat);
1312 nSrcStep = (nXSrc + nSrcWidth) * FreeRDPGetBytesPerPixel(SrcFormat);
1314 WINPR_ASSERT(nDstStep / FreeRDPGetBytesPerPixel(DstFormat) >= nXDst + nDstWidth);
1315 WINPR_ASSERT(nSrcStep / FreeRDPGetBytesPerPixel(SrcFormat) >= nXSrc + nSrcWidth);
1317#if defined(WITH_SWSCALE) || defined(WITH_CAIRO)
1319 &pSrcData[1ULL * nXSrc * FreeRDPGetBytesPerPixel(SrcFormat) + 1ULL * nYSrc * nSrcStep];
1321 &pDstData[1ULL * nXDst * FreeRDPGetBytesPerPixel(DstFormat) + 1ULL * nYDst * nDstStep];
1325 if ((nDstWidth == nSrcWidth) && (nDstHeight == nSrcHeight))
1327 return freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nDstWidth,
1328 nDstHeight, pSrcData, SrcFormat, nSrcStep, nXSrc,
1329 nYSrc,
nullptr, FREERDP_FLIP_NONE);
1332#if defined(WITH_SWSCALE)
1335 struct SwsContext* resize =
nullptr;
1336 enum AVPixelFormat srcFormat = av_format_for_buffer(SrcFormat);
1337 enum AVPixelFormat dstFormat = av_format_for_buffer(DstFormat);
1338 const int srcStep[1] = { (int)nSrcStep };
1339 const int dstStep[1] = { (int)nDstStep };
1341 if ((srcFormat == AV_PIX_FMT_NONE) || (dstFormat == AV_PIX_FMT_NONE))
1344 if (!freerdp_swscale_available())
1346 WLog_WARN(TAG,
"swscale not available");
1353 if ((1ULL * nSrcStep * nSrcHeight > INT32_MAX) ||
1354 (1ULL * nDstStep * nDstHeight > INT32_MAX))
1357 "image too large to scale: source %" PRIu32
" x %" PRIu32
1358 " bytes, destination %" PRIu32
" x %" PRIu32
" bytes",
1359 nSrcStep, nSrcHeight, nDstStep, nDstHeight);
1363 resize = freerdp_sws_getContext((
int)nSrcWidth, (
int)nSrcHeight, srcFormat, (
int)nDstWidth,
1364 (
int)nDstHeight, dstFormat, SWS_BILINEAR,
nullptr,
nullptr,
1371 const BYTE* srcSlice[4] = { src,
nullptr,
nullptr,
nullptr };
1372 BYTE* dstSlice[4] = { dst,
nullptr,
nullptr,
nullptr };
1373 const int srcSteps[4] = { srcStep[0], 0, 0, 0 };
1374 const int dstSteps[4] = { dstStep[0], 0, 0, 0 };
1376 res = freerdp_sws_scale(resize, srcSlice, srcSteps, 0, (
int)nSrcHeight, dstSlice, dstSteps);
1377 rc = (res == ((int)nDstHeight));
1379 freerdp_sws_freeContext(resize);
1382#elif defined(WITH_CAIRO)
1384 const double sx = (double)nDstWidth / (
double)nSrcWidth;
1385 const double sy = (double)nDstHeight / (
double)nSrcHeight;
1386 cairo_t* cairo_context;
1387 cairo_surface_t *csrc, *cdst;
1389 if ((nSrcWidth > INT_MAX) || (nSrcHeight > INT_MAX) || (nSrcStep > INT_MAX))
1392 if ((nDstWidth > INT_MAX) || (nDstHeight > INT_MAX) || (nDstStep > INT_MAX))
1396 if ((1ULL * nSrcStep * nSrcHeight > INT_MAX) || (1ULL * nDstStep * nDstHeight > INT_MAX))
1399 csrc = cairo_image_surface_create_for_data((
void*)src, CAIRO_FORMAT_ARGB32, (
int)nSrcWidth,
1400 (
int)nSrcHeight, (
int)nSrcStep);
1401 cdst = cairo_image_surface_create_for_data(dst, CAIRO_FORMAT_ARGB32, (
int)nDstWidth,
1402 (
int)nDstHeight, (
int)nDstStep);
1407 cairo_context = cairo_create(cdst);
1412 cairo_scale(cairo_context, sx, sy);
1413 cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
1414 cairo_set_source_surface(cairo_context, csrc, 0, 0);
1415 cairo_paint(cairo_context);
1418 cairo_destroy(cairo_context);
1420 cairo_surface_destroy(csrc);
1421 cairo_surface_destroy(cdst);
1425 WLog_WARN(TAG,
"SmartScaling requested but compiled without libcairo support!");
1431DWORD FreeRDPAreColorFormatsEqualNoAlpha(DWORD first, DWORD second)
1433 return FreeRDPAreColorFormatsEqualNoAlpha_int(first, second);
1436const char* FreeRDPGetColorFormatName(UINT32 format)
1444 ENTRY(PIXEL_FORMAT_ARGB32)
1445 ENTRY(PIXEL_FORMAT_XRGB32)
1446 ENTRY(PIXEL_FORMAT_ABGR32)
1447 ENTRY(PIXEL_FORMAT_XBGR32)
1448 ENTRY(PIXEL_FORMAT_BGRA32)
1449 ENTRY(PIXEL_FORMAT_BGRX32)
1450 ENTRY(PIXEL_FORMAT_RGBA32)
1451 ENTRY(PIXEL_FORMAT_RGBX32)
1452 ENTRY(PIXEL_FORMAT_BGRX32_DEPTH30)
1453 ENTRY(PIXEL_FORMAT_RGBX32_DEPTH30)
1454 ENTRY(PIXEL_FORMAT_RGB24)
1455 ENTRY(PIXEL_FORMAT_BGR24)
1456 ENTRY(PIXEL_FORMAT_RGB16)
1457 ENTRY(PIXEL_FORMAT_BGR16)
1458 ENTRY(PIXEL_FORMAT_ARGB15)
1459 ENTRY(PIXEL_FORMAT_RGB15)
1460 ENTRY(PIXEL_FORMAT_ABGR15)
1461 ENTRY(PIXEL_FORMAT_BGR15)
1462 ENTRY(PIXEL_FORMAT_RGB8)
1463 ENTRY(PIXEL_FORMAT_A4)
1464 ENTRY(PIXEL_FORMAT_MONO)
1472uint32_t FreeRDPGetColorFromatFromName(
const char* name)
1475 if (strcmp(name, #x) == 0) \
1481 ENTRY(PIXEL_FORMAT_ARGB32)
1482 ENTRY(PIXEL_FORMAT_XRGB32)
1483 ENTRY(PIXEL_FORMAT_ABGR32)
1484 ENTRY(PIXEL_FORMAT_XBGR32)
1485 ENTRY(PIXEL_FORMAT_BGRA32)
1486 ENTRY(PIXEL_FORMAT_BGRX32)
1487 ENTRY(PIXEL_FORMAT_RGBA32)
1488 ENTRY(PIXEL_FORMAT_RGBX32)
1489 ENTRY(PIXEL_FORMAT_BGRX32_DEPTH30)
1490 ENTRY(PIXEL_FORMAT_RGBX32_DEPTH30)
1491 ENTRY(PIXEL_FORMAT_RGB24)
1492 ENTRY(PIXEL_FORMAT_BGR24)
1493 ENTRY(PIXEL_FORMAT_RGB16)
1494 ENTRY(PIXEL_FORMAT_BGR16)
1495 ENTRY(PIXEL_FORMAT_ARGB15)
1496 ENTRY(PIXEL_FORMAT_RGB15)
1497 ENTRY(PIXEL_FORMAT_ABGR15)
1498 ENTRY(PIXEL_FORMAT_BGR15)
1499 ENTRY(PIXEL_FORMAT_RGB8)
1500 ENTRY(PIXEL_FORMAT_A4)
1501 ENTRY(PIXEL_FORMAT_MONO)
1507void FreeRDPSplitColor(UINT32 color, UINT32 format, BYTE* _r, BYTE* _g, BYTE* _b, BYTE* _a,
1508 const gdiPalette* palette)
1515 case PIXEL_FORMAT_ARGB32:
1517 *_a = (BYTE)(color >> 24);
1520 *_r = (BYTE)(color >> 16);
1523 *_g = (BYTE)(color >> 8);
1530 case PIXEL_FORMAT_XRGB32:
1532 *_r = (BYTE)(color >> 16);
1535 *_g = (BYTE)(color >> 8);
1545 case PIXEL_FORMAT_ABGR32:
1547 *_a = (BYTE)(color >> 24);
1550 *_b = (BYTE)(color >> 16);
1553 *_g = (BYTE)(color >> 8);
1560 case PIXEL_FORMAT_XBGR32:
1562 *_b = (BYTE)(color >> 16);
1565 *_g = (BYTE)(color >> 8);
1575 case PIXEL_FORMAT_RGBA32:
1577 *_r = (BYTE)(color >> 24);
1580 *_g = (BYTE)(color >> 16);
1583 *_b = (BYTE)(color >> 8);
1590 case PIXEL_FORMAT_RGBX32:
1592 *_r = (BYTE)(color >> 24);
1595 *_g = (BYTE)(color >> 16);
1598 *_b = (BYTE)(color >> 8);
1605 case PIXEL_FORMAT_BGRA32:
1607 *_b = (BYTE)(color >> 24);
1610 *_g = (BYTE)(color >> 16);
1613 *_r = (BYTE)(color >> 8);
1620 case PIXEL_FORMAT_BGRX32:
1622 *_b = (BYTE)(color >> 24);
1625 *_g = (BYTE)(color >> 16);
1628 *_r = (BYTE)(color >> 8);
1636 case PIXEL_FORMAT_RGB24:
1638 *_r = (BYTE)(color >> 16);
1641 *_g = (BYTE)(color >> 8);
1651 case PIXEL_FORMAT_BGR24:
1653 *_b = (BYTE)(color >> 16);
1656 *_g = (BYTE)(color >> 8);
1667 case PIXEL_FORMAT_RGB16:
1670 const UINT32 c = (color >> 11) & 0x1F;
1671 const UINT32 val = (c << 3) + c / 4;
1672 *_r = (BYTE)(val > 255 ? 255 : val);
1677 const UINT32 c = (color >> 5) & 0x3F;
1678 const UINT32 val = (c << 2) + c / 4 / 2;
1679 *_g = (BYTE)(val > 255 ? 255 : val);
1684 const UINT32 c = (color)&0x1F;
1685 const UINT32 val = (c << 3) + c / 4;
1686 *_b = (BYTE)(val > 255 ? 255 : val);
1694 case PIXEL_FORMAT_BGR16:
1697 const UINT32 c = (color)&0x1F;
1698 const UINT32 val = (c << 3) + c / 4;
1699 *_r = (BYTE)(val > 255 ? 255 : val);
1704 const UINT32 c = (color >> 5) & 0x3F;
1705 const UINT32 val = (c << 2) + c / 4 / 2;
1706 *_g = (BYTE)(val > 255 ? 255 : val);
1711 const UINT32 c = (color >> 11) & 0x1F;
1712 const UINT32 val = (c << 3) + c / 4;
1713 *_b = (BYTE)(val > 255 ? 255 : val);
1721 case PIXEL_FORMAT_ARGB15:
1724 const UINT32 c = (color >> 10) & 0x1F;
1725 const UINT32 val = (c << 3) + c / 4;
1726 *_r = (BYTE)(val > 255 ? 255 : val);
1731 const UINT32 c = (color >> 5) & 0x1F;
1732 const UINT32 val = (c << 3) + c / 4;
1733 *_g = (BYTE)(val > 255 ? 255 : val);
1738 const UINT32 c = (color)&0x1F;
1739 const UINT32 val = (c << 3) + c / 4;
1740 *_b = (BYTE)(val > 255 ? 255 : val);
1744 *_a = color & 0x8000 ? 0xFF : 0x00;
1748 case PIXEL_FORMAT_ABGR15:
1751 const UINT32 c = (color)&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 >> 10) & 0x1F;
1766 const UINT32 val = (c << 3) + c / 4;
1767 *_b = (BYTE)(val > 255 ? 255 : val);
1771 *_a = color & 0x8000 ? 0xFF : 0x00;
1776 case PIXEL_FORMAT_RGB15:
1779 const UINT32 c = (color >> 10) & 0x1F;
1780 const UINT32 val = (c << 3) + c / 4;
1781 *_r = (BYTE)(val > 255 ? 255 : val);
1786 const UINT32 c = (color >> 5) & 0x1F;
1787 const UINT32 val = (c << 3) + c / 4;
1788 *_g = (BYTE)(val > 255 ? 255 : val);
1793 const UINT32 c = (color)&0x1F;
1794 const UINT32 val = (c << 3) + c / 4;
1795 *_b = (BYTE)(val > 255 ? 255 : val);
1803 case PIXEL_FORMAT_BGR15:
1806 const UINT32 c = (color)&0x1F;
1807 const UINT32 val = (c << 3) + c / 4;
1808 *_r = (BYTE)(val > 255 ? 255 : val);
1813 const UINT32 c = (color >> 5) & 0x1F;
1814 const UINT32 val = (c << 3) + c / 4;
1815 *_g = (BYTE)(val > 255 ? 255 : val);
1820 const UINT32 c = (color >> 10) & 0x1F;
1821 const UINT32 val = (c << 3) + c / 4;
1822 *_b = (BYTE)(val > 255 ? 255 : val);
1831 case PIXEL_FORMAT_RGB8:
1834 tmp = palette->palette[color];
1835 FreeRDPSplitColor(tmp, palette->format, _r, _g, _b, _a,
nullptr);
1855 case PIXEL_FORMAT_MONO:
1857 *_r = (color) ? 0xFF : 0x00;
1860 *_g = (color) ? 0xFF : 0x00;
1863 *_b = (color) ? 0xFF : 0x00;
1866 *_a = (color) ? 0xFF : 0x00;
1871 case PIXEL_FORMAT_A4:
1885 WLog_ERR(TAG,
"Unsupported format %s", FreeRDPGetColorFormatName(format));
1890BOOL FreeRDPWriteColorIgnoreAlpha(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT32 color)
1892 return FreeRDPWriteColorIgnoreAlpha_int(dst, format, color);
1895BOOL FreeRDPWriteColor(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT32 color)
1897 return FreeRDPWriteColor_int(dst, format, color);
1900UINT32 FreeRDPReadColor(
const BYTE* WINPR_RESTRICT src, UINT32 format)
1902 return FreeRDPReadColor_int(src, format);
1905UINT32 FreeRDPGetColor(UINT32 format, BYTE r, BYTE g, BYTE b, BYTE a)
1916 case PIXEL_FORMAT_ARGB32:
1917 return (_a << 24) | (_r << 16) | (_g << 8) | _b;
1919 case PIXEL_FORMAT_XRGB32:
1920 return (_r << 16) | (_g << 8) | _b;
1922 case PIXEL_FORMAT_ABGR32:
1923 return (_a << 24) | (_b << 16) | (_g << 8) | _r;
1925 case PIXEL_FORMAT_XBGR32:
1926 return (_b << 16) | (_g << 8) | _r;
1928 case PIXEL_FORMAT_RGBA32:
1929 return (_r << 24) | (_g << 16) | (_b << 8) | _a;
1931 case PIXEL_FORMAT_RGBX32:
1932 return (_r << 24) | (_g << 16) | (_b << 8) | _a;
1934 case PIXEL_FORMAT_BGRA32:
1935 return (_b << 24) | (_g << 16) | (_r << 8) | _a;
1937 case PIXEL_FORMAT_BGRX32:
1938 return (_b << 24) | (_g << 16) | (_r << 8) | _a;
1940 case PIXEL_FORMAT_RGBX32_DEPTH30:
1942 t = (_r << 22) | (_g << 12) | (_b << 2);
1944 return ((t & 0xff) << 24) | (((t >> 8) & 0xff) << 16) | (((t >> 16) & 0xff) << 8) |
1947 case PIXEL_FORMAT_BGRX32_DEPTH30:
1949 t = (_r << 22) | (_g << 12) | (_b << 2);
1951 return ((t & 0xff) << 24) | (((t >> 8) & 0xff) << 16) | (((t >> 16) & 0xff) << 8) |
1955 case PIXEL_FORMAT_RGB24:
1956 return (_r << 16) | (_g << 8) | _b;
1958 case PIXEL_FORMAT_BGR24:
1959 return (_b << 16) | (_g << 8) | _r;
1962 case PIXEL_FORMAT_RGB16:
1963 return (((_r >> 3) & 0x1F) << 11) | (((_g >> 2) & 0x3F) << 5) | ((_b >> 3) & 0x1F);
1965 case PIXEL_FORMAT_BGR16:
1966 return (((_b >> 3) & 0x1F) << 11) | (((_g >> 2) & 0x3F) << 5) | ((_r >> 3) & 0x1F);
1968 case PIXEL_FORMAT_ARGB15:
1969 return (((_r >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_b >> 3) & 0x1F) |
1970 (_a ? 0x8000 : 0x0000);
1972 case PIXEL_FORMAT_ABGR15:
1973 return (((_b >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_r >> 3) & 0x1F) |
1974 (_a ? 0x8000 : 0x0000);
1977 case PIXEL_FORMAT_RGB15:
1978 return (((_r >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_b >> 3) & 0x1F);
1980 case PIXEL_FORMAT_BGR15:
1981 return (((_b >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_r >> 3) & 0x1F);
1984 case PIXEL_FORMAT_RGB8:
1987 case PIXEL_FORMAT_A4:
1990 case PIXEL_FORMAT_MONO:
1992 WLog_ERR(TAG,
"Unsupported format %s", FreeRDPGetColorFormatName(format));
1997BOOL freerdp_image_copy_no_overlap(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
1998 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
1999 const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat,
2000 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
2001 const gdiPalette* WINPR_RESTRICT palette, UINT32 flags)
2005 prims = primitives_get();
2007 if (FreeRDPGetBitsPerPixel(SrcFormat) == 0)
2009 if (FreeRDPGetBitsPerPixel(DstFormat) == 0)
2012 if ((nWidth == 0) || (nHeight == 0))
2015 WINPR_ASSERT(1ull * nXDst + nWidth <= UINT32_MAX);
2016 WINPR_ASSERT(1ull * nXSrc + nWidth <= UINT32_MAX);
2018 nDstStep = (nXDst + nWidth) * FreeRDPGetBytesPerPixel(DstFormat);
2020 nSrcStep = (nXSrc + nWidth) * FreeRDPGetBytesPerPixel(SrcFormat);
2022 WINPR_ASSERT(nDstStep / FreeRDPGetBytesPerPixel(DstFormat) >= nXDst + nWidth);
2023 WINPR_ASSERT(nSrcStep / FreeRDPGetBytesPerPixel(SrcFormat) >= nXSrc + nWidth);
2024 WINPR_ASSERT(!overlapping(pDstData, nYDst, nDstStep, pSrcData, nYSrc, nSrcStep, nHeight));
2025 WINPR_ASSERT(prims);
2027 return prims->
copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,
2028 pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette,
2029 flags) == PRIMITIVES_SUCCESS;
WINPR_ATTR_NODISCARD fn_copy_no_overlap_t copy_no_overlap