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);
245BYTE* freerdp_glyph_convert(UINT32 width, UINT32 height,
const BYTE* WINPR_RESTRICT data)
252 const UINT32 scanline = (width + 7) / 8;
253 BYTE* dstData = (BYTE*)winpr_aligned_malloc(1ull * width * height, 16);
258 ZeroMemory(dstData, 1ULL * width * height);
259 BYTE* dstp = dstData;
261 for (UINT32 y = 0; y < height; y++)
263 const BYTE* srcp = &data[1ull * y * scanline];
265 for (UINT32 x = 0; x < width; x++)
267 if ((*srcp & (0x80 >> (x % 8))) != 0)
272 if (((x + 1) % 8 == 0) && x != 0)
280BOOL freerdp_image_copy_from_monochrome(BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,
281 UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT32 nWidth,
282 UINT32 nHeight,
const BYTE* WINPR_RESTRICT pSrcData,
283 UINT32 backColor, UINT32 foreColor,
284 const gdiPalette* WINPR_RESTRICT palette)
286 const UINT32 dstBytesPerPixel = FreeRDPGetBytesPerPixel(DstFormat);
288 if (!pDstData || !pSrcData || !palette)
292 nDstStep = dstBytesPerPixel * nWidth;
294 const UINT32 monoStep = (nWidth + 7) / 8;
296 for (
size_t y = 0; y < nHeight; y++)
298 BYTE* pDstLine = &pDstData[((nYDst + y) * nDstStep)];
299 UINT32 monoBit = 0x80;
300 const BYTE* monoBits = &pSrcData[monoStep * y];
302 for (
size_t x = 0; x < nWidth; x++)
304 BYTE* pDstPixel = &pDstLine[((nXDst + x) * FreeRDPGetBytesPerPixel(DstFormat))];
305 BOOL monoPixel = (*monoBits & monoBit) ? TRUE : FALSE;
307 if (!(monoBit >>= 1))
314 FreeRDPWriteColor_int(pDstPixel, DstFormat, backColor);
316 FreeRDPWriteColor_int(pDstPixel, DstFormat, foreColor);
323static INLINE UINT32 freerdp_image_inverted_pointer_color(UINT32 x, UINT32 y, UINT32 format)
334 BYTE fill = (x + y) & 1 ? 0x00 : 0xFF;
335 return FreeRDPGetColor(format, fill, fill, fill, 0xFF);
342static void fill_gdi_palette_for_icon(
const BYTE* colorTable, UINT16 cbColorTable,
345 WINPR_ASSERT(palette);
347 palette->format = PIXEL_FORMAT_BGRX32;
348 ZeroMemory(palette->palette,
sizeof(palette->palette));
353 if ((cbColorTable % 4 != 0) || (cbColorTable / 4 > 256))
355 WLog_WARN(TAG,
"weird palette size: %u", cbColorTable);
359 for (UINT16 i = 0; i < cbColorTable / 4; i++)
361 palette->palette[i] = FreeRDPReadColor_int(&colorTable[4ULL * i], palette->format);
365static INLINE UINT32 div_ceil(UINT32 a, UINT32 b)
367 return (a + (b - 1)) / b;
370static INLINE UINT32 round_up(UINT32 a, UINT32 b)
372 return b * div_ceil(a, b);
375BOOL freerdp_image_copy_from_icon_data(BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,
376 UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT16 nWidth,
377 UINT16 nHeight,
const BYTE* WINPR_RESTRICT bitsColor,
378 UINT16 cbBitsColor,
const BYTE* WINPR_RESTRICT bitsMask,
379 UINT16 cbBitsMask,
const BYTE* WINPR_RESTRICT colorTable,
380 UINT16 cbColorTable, UINT32 bpp)
385 if (!pDstData || !bitsColor)
404 WLog_WARN(TAG,
"1bpp and 4bpp icons are not supported");
408 format = PIXEL_FORMAT_RGB8;
412 format = PIXEL_FORMAT_RGB15;
416 format = PIXEL_FORMAT_RGB24;
420 format = PIXEL_FORMAT_BGRA32;
424 WLog_WARN(TAG,
"invalid icon bpp: %" PRIu32, bpp);
429 if (cbBitsColor < nWidth * nHeight * FreeRDPGetBytesPerPixel(format))
432 fill_gdi_palette_for_icon(colorTable, cbColorTable, &palette);
433 if (!freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,
434 bitsColor, format, 0, 0, 0, &palette, FREERDP_FLIP_VERTICAL))
438 if (FreeRDPColorHasAlpha(DstFormat) && cbBitsMask)
441 const BYTE* maskByte = NULL;
446 BYTE* dstBuf = pDstData;
447 UINT32 dstBpp = FreeRDPGetBytesPerPixel(DstFormat);
454 stride = round_up(div_ceil(nWidth, 8), 4);
456 for (UINT32 y = 0; y < nHeight; y++)
458 maskByte = &bitsMask[1ULL * stride * (nHeight - 1 - y)];
461 for (UINT32 x = 0; x < nWidth; x++)
464 BYTE alpha = (*maskByte & nextBit) ? 0x00 : 0xFF;
467 color = FreeRDPReadColor_int(dstBuf, DstFormat);
468 FreeRDPSplitColor(color, DstFormat, &r, &g, &b, NULL, &palette);
469 color = FreeRDPGetColor(DstFormat, r, g, b, alpha);
470 FreeRDPWriteColor_int(dstBuf, DstFormat, color);
486static BOOL freerdp_image_copy_from_pointer_data_1bpp(
487 BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
488 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
489 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength, UINT32 xorBpp)
499 vFlip = (xorBpp == 1) ? FALSE : TRUE;
500 andStep = (nWidth + 7) / 8;
501 andStep += (andStep % 2);
503 if (!xorMask || (xorMaskLength == 0))
505 if (!andMask || (andMaskLength == 0))
508 xorStep = (nWidth + 7) / 8;
509 xorStep += (xorStep % 2);
511 if (xorStep * nHeight > xorMaskLength)
514 if (andStep * nHeight > andMaskLength)
517 for (UINT32 y = 0; y < nHeight; y++)
519 const BYTE* andBits = NULL;
520 const BYTE* xorBits = NULL;
521 BYTE* pDstPixel = &pDstData[((1ULL * nYDst + y) * nDstStep) +
522 (1ULL * nXDst * FreeRDPGetBytesPerPixel(DstFormat))];
523 xorBit = andBit = 0x80;
527 xorBits = &xorMask[1ULL * xorStep * y];
528 andBits = &andMask[1ULL * andStep * y];
532 xorBits = &xorMask[1ULL * xorStep * (nHeight - y - 1)];
533 andBits = &andMask[1ULL * andStep * (nHeight - y - 1)];
536 for (UINT32 x = 0; x < nWidth; x++)
539 xorPixel = (*xorBits & xorBit) ? 1 : 0;
547 andPixel = (*andBits & andBit) ? 1 : 0;
555 if (!andPixel && !xorPixel)
556 color = FreeRDPGetColor(DstFormat, 0, 0, 0, 0xFF);
557 else if (!andPixel && xorPixel)
558 color = FreeRDPGetColor(DstFormat, 0xFF, 0xFF, 0xFF, 0xFF);
559 else if (andPixel && !xorPixel)
560 color = FreeRDPGetColor(DstFormat, 0, 0, 0, 0);
561 else if (andPixel && xorPixel)
562 color = freerdp_image_inverted_pointer_color(x, y, DstFormat);
564 FreeRDPWriteColor_int(pDstPixel, DstFormat, color);
565 pDstPixel += FreeRDPGetBytesPerPixel(DstFormat);
572static BOOL freerdp_image_copy_from_pointer_data_xbpp(
573 BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
574 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
575 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength, UINT32 xorBpp,
576 const gdiPalette* palette)
584 UINT32 dstBitsPerPixel = 0;
585 UINT32 xorBytesPerPixel = 0;
586 dstBitsPerPixel = FreeRDPGetBitsPerPixel(DstFormat);
588 vFlip = (xorBpp == 1) ? FALSE : TRUE;
589 andStep = (nWidth + 7) / 8;
590 andStep += (andStep % 2);
592 if (!xorMask || (xorMaskLength == 0))
595 xorBytesPerPixel = xorBpp >> 3;
596 xorStep = 1ULL * nWidth * xorBytesPerPixel;
597 xorStep += (xorStep % 2);
599 if (xorBpp == 8 && !palette)
601 WLog_ERR(TAG,
"null palette in conversion from %" PRIu32
" bpp to %" PRIu32
" bpp", xorBpp,
606 if (xorStep * nHeight > xorMaskLength)
611 if (andStep * nHeight > andMaskLength)
615 for (UINT32 y = 0; y < nHeight; y++)
617 const BYTE* xorBits = NULL;
618 const BYTE* andBits = NULL;
619 BYTE* pDstPixel = &pDstData[((1ULL * nYDst + y) * nDstStep) +
620 (1ULL * nXDst * FreeRDPGetBytesPerPixel(DstFormat))];
626 andBits = &andMask[andStep * y];
628 xorBits = &xorMask[xorStep * y];
633 andBits = &andMask[1ULL * andStep * (nHeight - y - 1)];
635 xorBits = &xorMask[1ULL * xorStep * (nHeight - y - 1)];
638 for (UINT32 x = 0; x < nWidth; x++)
640 UINT32 pixelFormat = 0;
647 andPixel = (*andBits & andBit) ? 1 : 0;
658 pixelFormat = PIXEL_FORMAT_BGRA32;
659 xorPixel = FreeRDPReadColor_int(xorBits, pixelFormat);
661 else if (xorBpp == 16)
663 pixelFormat = PIXEL_FORMAT_RGB15;
664 xorPixel = FreeRDPReadColor_int(xorBits, pixelFormat);
666 else if (xorBpp == 8)
668 pixelFormat = palette->format;
669 xorPixel = palette->palette[xorBits[0]];
673 pixelFormat = PIXEL_FORMAT_BGR24;
674 xorPixel = FreeRDPReadColor_int(xorBits, pixelFormat);
678 if (xorPixel == 0x00FFFFFFUL)
679 xorPixel |= 0xFF000000UL;
684 xorPixel |= 0xFF000000UL;
687 pixelFormat = PIXEL_FORMAT_ABGR32;
690 xorPixel = FreeRDPConvertColor(xorPixel, pixelFormat, PIXEL_FORMAT_ARGB32, palette);
691 xorBits += xorBytesPerPixel;
695 if (xorPixel == 0xFF000000UL)
696 xorPixel = 0x00000000;
697 else if (xorPixel == 0xFFFFFFFFUL)
698 xorPixel = freerdp_image_inverted_pointer_color(x, y, PIXEL_FORMAT_ARGB32);
701 color = FreeRDPConvertColor(xorPixel, PIXEL_FORMAT_ARGB32, DstFormat, palette);
702 FreeRDPWriteColor_int(pDstPixel, DstFormat, color);
703 pDstPixel += FreeRDPGetBytesPerPixel(DstFormat);
718BOOL freerdp_image_copy_from_pointer_data_int(
719 BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
720 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
721 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength, UINT32 xorBpp,
722 const gdiPalette* WINPR_RESTRICT palette)
724 UINT32 dstBitsPerPixel = 0;
725 UINT32 dstBytesPerPixel = 0;
726 dstBitsPerPixel = FreeRDPGetBitsPerPixel(DstFormat);
727 dstBytesPerPixel = FreeRDPGetBytesPerPixel(DstFormat);
730 nDstStep = dstBytesPerPixel * nWidth;
732 for (UINT32 y = nYDst; y < nHeight; y++)
734 BYTE* WINPR_RESTRICT pDstLine = &pDstData[y * nDstStep + nXDst * dstBytesPerPixel];
735 memset(pDstLine, 0, 1ull * dstBytesPerPixel * (nWidth - nXDst));
741 return freerdp_image_copy_from_pointer_data_1bpp(
742 pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, xorMask,
743 xorMaskLength, andMask, andMaskLength, xorBpp);
749 return freerdp_image_copy_from_pointer_data_xbpp(
750 pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, xorMask,
751 xorMaskLength, andMask, andMaskLength, xorBpp, palette);
754 WLog_ERR(TAG,
"failed to convert from %" PRIu32
" bpp to %" PRIu32
" bpp", xorBpp,
760BOOL freerdp_image_copy_from_pointer_data(BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,
761 UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
762 UINT32 nWidth, UINT32 nHeight,
763 const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
764 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength,
765 UINT32 xorBpp,
const gdiPalette* WINPR_RESTRICT palette)
767#if defined(WITH_CURSOR_DUMP)
768 dump_pointer_data(nXDst, nYDst, nWidth, nHeight, xorMask, xorMaskLength, andMask, andMaskLength,
771 return freerdp_image_copy_from_pointer_data_int(pDstData, DstFormat, nDstStep, nXDst, nYDst,
772 nWidth, nHeight, xorMask, xorMaskLength,
773 andMask, andMaskLength, xorBpp, palette);
776static INLINE BOOL overlapping(
const BYTE* pDstData, UINT32 nYDst, UINT32 nDstStep,
777 const BYTE* pSrcData, UINT32 nYSrc, UINT32 nSrcStep, UINT32 nHeight)
779 const uintptr_t src = (uintptr_t)pSrcData;
780 const uintptr_t srcstart = src + 1ULL * nSrcStep * nYSrc;
781 const uintptr_t srcend = srcstart + 1ULL * nSrcStep * nHeight;
782 const uintptr_t dst = (uintptr_t)pDstData;
783 const uintptr_t dststart = dst + 1ULL * nDstStep * nYDst;
784 const uintptr_t dstend = dststart + 1ULL * nDstStep * nHeight;
786 if ((dststart >= srcstart) && (dststart <= srcend))
789 if ((dstend >= srcstart) && (dstend <= srcend))
795static INLINE BOOL freerdp_image_copy_bgr24_bgrx32(BYTE* WINPR_RESTRICT pDstData, UINT32 nDstStep,
796 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth,
798 const BYTE* WINPR_RESTRICT pSrcData,
799 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
800 int64_t srcVMultiplier, int64_t srcVOffset,
801 int64_t dstVMultiplier, int64_t dstVOffset)
804 const int64_t srcByte = 3;
805 const int64_t dstByte = 4;
807 for (int64_t y = 0; y < nHeight; y++)
809 const BYTE* WINPR_RESTRICT srcLine =
810 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
811 BYTE* WINPR_RESTRICT dstLine =
812 &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
814 for (int64_t x = 0; x < nWidth; x++)
816 dstLine[(x + nXDst) * dstByte + 0] = srcLine[(x + nXSrc) * srcByte + 0];
817 dstLine[(x + nXDst) * dstByte + 1] = srcLine[(x + nXSrc) * srcByte + 1];
818 dstLine[(x + nXDst) * dstByte + 2] = srcLine[(x + nXSrc) * srcByte + 2];
825static INLINE BOOL freerdp_image_copy_bgrx32_bgrx32(BYTE* WINPR_RESTRICT pDstData, UINT32 nDstStep,
826 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth,
828 const BYTE* WINPR_RESTRICT pSrcData,
829 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
830 int64_t srcVMultiplier, int64_t srcVOffset,
831 int64_t dstVMultiplier, int64_t dstVOffset)
834 const int64_t srcByte = 4;
835 const int64_t dstByte = 4;
837 for (int64_t y = 0; y < nHeight; y++)
839 const BYTE* WINPR_RESTRICT srcLine =
840 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
841 BYTE* WINPR_RESTRICT dstLine =
842 &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
844 for (int64_t x = 0; x < nWidth; x++)
846 dstLine[(x + nXDst) * dstByte + 0] = srcLine[(x + nXSrc) * srcByte + 0];
847 dstLine[(x + nXDst) * dstByte + 1] = srcLine[(x + nXSrc) * srcByte + 1];
848 dstLine[(x + nXDst) * dstByte + 2] = srcLine[(x + nXSrc) * srcByte + 2];
855static INLINE BOOL freerdp_image_copy_generic(
856 BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
857 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcFormat,
858 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
const gdiPalette* WINPR_RESTRICT palette,
859 int64_t srcVMultiplier, int64_t srcVOffset, int64_t dstVMultiplier, int64_t dstVOffset)
862 const int64_t srcByte = 4;
863 const int64_t dstByte = 4;
865 for (int64_t y = 0; y < nHeight; y++)
867 const BYTE* WINPR_RESTRICT srcLine =
868 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
869 BYTE* WINPR_RESTRICT dstLine =
870 &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
872 UINT32 color = FreeRDPReadColor_int(&srcLine[nXSrc * srcByte], SrcFormat);
873 UINT32 oldColor = color;
874 UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette);
875 FreeRDPWriteColorIgnoreAlpha_int(&dstLine[nXDst * dstByte], DstFormat, dstColor);
876 for (int64_t x = 1; x < nWidth; x++)
878 color = FreeRDPReadColor_int(&srcLine[(x + nXSrc) * srcByte], SrcFormat);
879 if (color == oldColor)
881 FreeRDPWriteColorIgnoreAlpha_int(&dstLine[(x + nXDst) * dstByte], DstFormat,
887 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette);
888 FreeRDPWriteColorIgnoreAlpha_int(&dstLine[(x + nXDst) * dstByte], DstFormat,
897static INLINE BOOL freerdp_image_copy_no_overlap_dst_alpha(
898 BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
899 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat,
900 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
const gdiPalette* WINPR_RESTRICT palette,
901 int64_t srcVMultiplier, int64_t srcVOffset, int64_t dstVMultiplier, int64_t dstVOffset)
903 WINPR_ASSERT(pDstData);
904 WINPR_ASSERT(pSrcData);
908 case PIXEL_FORMAT_BGR24:
911 case PIXEL_FORMAT_BGRX32:
912 case PIXEL_FORMAT_BGRA32:
913 return freerdp_image_copy_bgr24_bgrx32(
914 pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, pSrcData, nSrcStep,
915 nXSrc, nYSrc, srcVMultiplier, srcVOffset, dstVMultiplier, dstVOffset);
920 case PIXEL_FORMAT_BGRX32:
921 case PIXEL_FORMAT_BGRA32:
924 case PIXEL_FORMAT_BGRX32:
925 case PIXEL_FORMAT_BGRA32:
926 return freerdp_image_copy_bgrx32_bgrx32(
927 pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, pSrcData, nSrcStep,
928 nXSrc, nYSrc, srcVMultiplier, srcVOffset, dstVMultiplier, dstVOffset);
937 return freerdp_image_copy_generic(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,
938 pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette,
939 srcVMultiplier, srcVOffset, dstVMultiplier, dstVOffset);
942BOOL freerdp_image_copy_overlap(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst,
943 UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
const BYTE* pSrcData,
944 DWORD SrcFormat, UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
945 const gdiPalette* WINPR_RESTRICT palette, UINT32 flags)
947 const UINT32 dstByte = FreeRDPGetBytesPerPixel(DstFormat);
948 const UINT32 srcByte = FreeRDPGetBytesPerPixel(SrcFormat);
949 const UINT32 copyDstWidth = nWidth * dstByte;
950 const UINT32 xSrcOffset = nXSrc * srcByte;
951 const UINT32 xDstOffset = nXDst * dstByte;
952 const BOOL vSrcVFlip = (flags & FREERDP_FLIP_VERTICAL) ? TRUE : FALSE;
953 int64_t srcVOffset = 0;
954 int64_t srcVMultiplier = 1;
955 int64_t dstVOffset = 0;
956 int64_t dstVMultiplier = 1;
958 WINPR_ASSERT(overlapping(pDstData, nYDst, nDstStep, pSrcData, nYSrc, nSrcStep, nHeight));
960 if ((nWidth == 0) || (nHeight == 0))
963 if ((nHeight > INT32_MAX) || (nWidth > INT32_MAX))
966 if (!pDstData || !pSrcData)
970 nDstStep = nWidth * FreeRDPGetBytesPerPixel(DstFormat);
973 nSrcStep = nWidth * FreeRDPGetBytesPerPixel(SrcFormat);
977 srcVOffset = (nHeight - 1ll) * nSrcStep;
981 if (((flags & FREERDP_KEEP_DST_ALPHA) != 0) && FreeRDPColorHasAlpha(DstFormat))
983 return freerdp_image_copy_no_overlap_dst_alpha(
984 pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, pSrcData, SrcFormat,
985 nSrcStep, nXSrc, nYSrc, palette, srcVMultiplier, srcVOffset, dstVMultiplier,
988 else if (FreeRDPAreColorFormatsEqualNoAlpha_int(SrcFormat, DstFormat))
993 for (int64_t y = 0; y < nHeight; y++)
995 const BYTE* srcLine =
996 &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset];
997 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
998 memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
1002 else if (nYDst > nYSrc)
1004 for (int64_t y = nHeight - 1; y >= 0; y--)
1006 const BYTE* srcLine =
1007 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
1008 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1009 memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
1013 else if (nXSrc > nXDst)
1015 for (int64_t y = 0; y < nHeight; y++)
1017 const BYTE* srcLine =
1018 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
1019 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1020 memmove(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
1024 else if (nXSrc < nXDst)
1026 for (int64_t y = nHeight - 1; y >= 0; y--)
1028 const BYTE* srcLine =
1029 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
1030 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1031 memmove(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
1041 for (int64_t y = 0; y < nHeight; y++)
1043 const BYTE* srcLine = &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
1044 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1046 UINT32 color = FreeRDPReadColor_int(&srcLine[1ULL * nXSrc * srcByte], SrcFormat);
1047 UINT32 oldColor = color;
1048 UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette);
1049 FreeRDPWriteColor_int(&dstLine[1ULL * nXDst * dstByte], DstFormat, dstColor);
1050 for (int64_t x = 1; x < nWidth; x++)
1052 color = FreeRDPReadColor_int(&srcLine[(x + nXSrc) * srcByte], SrcFormat);
1053 if (color == oldColor)
1055 FreeRDPWriteColor_int(&dstLine[(x + nXDst) * dstByte], DstFormat, dstColor);
1060 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette);
1061 FreeRDPWriteColor_int(&dstLine[(x + nXDst) * dstByte], DstFormat, dstColor);
1070BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst,
1071 UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
const BYTE* pSrcData,
1072 DWORD SrcFormat, UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
1073 const gdiPalette* WINPR_RESTRICT palette, UINT32 flags)
1075 if ((nHeight > INT32_MAX) || (nWidth > INT32_MAX))
1078 if (!pDstData || !pSrcData)
1081 if ((nWidth == 0) || (nHeight == 0))
1085 nDstStep = nWidth * FreeRDPGetBytesPerPixel(DstFormat);
1088 nSrcStep = nWidth * FreeRDPGetBytesPerPixel(SrcFormat);
1090 const BOOL ovl = overlapping(pDstData, nYDst, nDstStep, pSrcData, nYSrc, nSrcStep, nHeight);
1092 return freerdp_image_copy_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth,
1093 nHeight, pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc,
1095 return freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth,
1096 nHeight, pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc,
1100BOOL freerdp_image_fill(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
1101 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight, UINT32 color)
1103 if ((nWidth == 0) || (nHeight == 0))
1105 const UINT32 bpp = FreeRDPGetBytesPerPixel(DstFormat);
1106 BYTE* WINPR_RESTRICT pFirstDstLine = NULL;
1107 BYTE* WINPR_RESTRICT pFirstDstLineXOffset = NULL;
1110 nDstStep = (nXDst + nWidth) * FreeRDPGetBytesPerPixel(DstFormat);
1112 pFirstDstLine = &pDstData[1ULL * nYDst * nDstStep];
1113 pFirstDstLineXOffset = &pFirstDstLine[1ULL * nXDst * bpp];
1115 for (
size_t x = 0; x < nWidth; x++)
1117 BYTE* pDst = &pFirstDstLine[(x + nXDst) * bpp];
1118 FreeRDPWriteColor_int(pDst, DstFormat, color);
1121 for (
size_t y = 1; y < nHeight; y++)
1123 BYTE* pDstLine = &pDstData[(y + nYDst) * nDstStep + 1ULL * nXDst * bpp];
1124 memcpy(pDstLine, pFirstDstLineXOffset, 1ull * nWidth * bpp);
1130BOOL freerdp_image_fill_ex(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
1131 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight, UINT32 color,
1134 if (FreeRDPColorHasAlpha(DstFormat) && ((flags & FREERDP_IMAGE_FILL_IGNORE_ALPHA) != 0))
1136 const UINT32 bpp = FreeRDPGetBytesPerPixel(DstFormat);
1140 FreeRDPSplitColor(color, DstFormat, &r, &g, &b, NULL, NULL);
1142 for (
size_t y = 0; y < nHeight; y++)
1144 BYTE* WINPR_RESTRICT line = &pDstData[(y + nYDst) * nDstStep];
1146 for (
size_t x = 0; x < nWidth; x++)
1148 BYTE* WINPR_RESTRICT dst = &line[x * bpp];
1149 const UINT32 dcolor = FreeRDPReadColor_int(dst, DstFormat);
1151 FreeRDPSplitColor(dcolor, DstFormat, NULL, NULL, NULL, &a, NULL);
1152 const UINT32 scolor = FreeRDPGetColor(DstFormat, r, g, b, a);
1153 if (!FreeRDPWriteColor_int(dst, DstFormat, scolor))
1159 return freerdp_image_fill(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, color);
1162#if defined(WITH_SWSCALE)
1163static int av_format_for_buffer(UINT32 format)
1167 case PIXEL_FORMAT_ARGB32:
1168 return AV_PIX_FMT_BGRA;
1170 case PIXEL_FORMAT_XRGB32:
1171 return AV_PIX_FMT_BGR0;
1173 case PIXEL_FORMAT_BGRA32:
1174 return AV_PIX_FMT_RGBA;
1176 case PIXEL_FORMAT_BGRX32:
1177 return AV_PIX_FMT_RGB0;
1180 return AV_PIX_FMT_NONE;
1185BOOL freerdp_image_scale(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
1186 UINT32 nXDst, UINT32 nYDst, UINT32 nDstWidth, UINT32 nDstHeight,
1187 const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat, UINT32 nSrcStep,
1188 UINT32 nXSrc, UINT32 nYSrc, UINT32 nSrcWidth, UINT32 nSrcHeight)
1193 nDstStep = nDstWidth * FreeRDPGetBytesPerPixel(DstFormat);
1196 nSrcStep = nSrcWidth * FreeRDPGetBytesPerPixel(SrcFormat);
1198#if defined(WITH_SWSCALE) || defined(WITH_CAIRO)
1199 const BYTE* src = &pSrcData[nXSrc * FreeRDPGetBytesPerPixel(SrcFormat) + nYSrc * nSrcStep];
1200 BYTE* dst = &pDstData[nXDst * FreeRDPGetBytesPerPixel(DstFormat) + nYDst * nDstStep];
1204 if ((nDstWidth == nSrcWidth) && (nDstHeight == nSrcHeight))
1206 return freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nDstWidth,
1207 nDstHeight, pSrcData, SrcFormat, nSrcStep, nXSrc,
1208 nYSrc, NULL, FREERDP_FLIP_NONE);
1211#if defined(WITH_SWSCALE)
1214 struct SwsContext* resize = NULL;
1215 int srcFormat = av_format_for_buffer(SrcFormat);
1216 int dstFormat = av_format_for_buffer(DstFormat);
1217 const int srcStep[1] = { (int)nSrcStep };
1218 const int dstStep[1] = { (int)nDstStep };
1220 if ((srcFormat == AV_PIX_FMT_NONE) || (dstFormat == AV_PIX_FMT_NONE))
1223 resize = sws_getContext((
int)nSrcWidth, (
int)nSrcHeight, srcFormat, (
int)nDstWidth,
1224 (
int)nDstHeight, dstFormat, SWS_BILINEAR, NULL, NULL, NULL);
1229 res = sws_scale(resize, &src, srcStep, 0, (
int)nSrcHeight, &dst, dstStep);
1230 rc = (res == ((int)nDstHeight));
1232 sws_freeContext(resize);
1235#elif defined(WITH_CAIRO)
1237 const double sx = (double)nDstWidth / (
double)nSrcWidth;
1238 const double sy = (double)nDstHeight / (
double)nSrcHeight;
1239 cairo_t* cairo_context;
1240 cairo_surface_t *csrc, *cdst;
1242 if ((nSrcWidth > INT_MAX) || (nSrcHeight > INT_MAX) || (nSrcStep > INT_MAX))
1245 if ((nDstWidth > INT_MAX) || (nDstHeight > INT_MAX) || (nDstStep > INT_MAX))
1248 csrc = cairo_image_surface_create_for_data((
void*)src, CAIRO_FORMAT_ARGB32, (
int)nSrcWidth,
1249 (
int)nSrcHeight, (
int)nSrcStep);
1250 cdst = cairo_image_surface_create_for_data(dst, CAIRO_FORMAT_ARGB32, (
int)nDstWidth,
1251 (
int)nDstHeight, (
int)nDstStep);
1256 cairo_context = cairo_create(cdst);
1261 cairo_scale(cairo_context, sx, sy);
1262 cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
1263 cairo_set_source_surface(cairo_context, csrc, 0, 0);
1264 cairo_paint(cairo_context);
1267 cairo_destroy(cairo_context);
1269 cairo_surface_destroy(csrc);
1270 cairo_surface_destroy(cdst);
1274 WLog_WARN(TAG,
"SmartScaling requested but compiled without libcairo support!");
1280DWORD FreeRDPAreColorFormatsEqualNoAlpha(DWORD first, DWORD second)
1282 return FreeRDPAreColorFormatsEqualNoAlpha_int(first, second);
1285const char* FreeRDPGetColorFormatName(UINT32 format)
1290 case PIXEL_FORMAT_ARGB32:
1291 return "PIXEL_FORMAT_ARGB32";
1293 case PIXEL_FORMAT_XRGB32:
1294 return "PIXEL_FORMAT_XRGB32";
1296 case PIXEL_FORMAT_ABGR32:
1297 return "PIXEL_FORMAT_ABGR32";
1299 case PIXEL_FORMAT_XBGR32:
1300 return "PIXEL_FORMAT_XBGR32";
1302 case PIXEL_FORMAT_BGRA32:
1303 return "PIXEL_FORMAT_BGRA32";
1305 case PIXEL_FORMAT_BGRX32:
1306 return "PIXEL_FORMAT_BGRX32";
1308 case PIXEL_FORMAT_RGBA32:
1309 return "PIXEL_FORMAT_RGBA32";
1311 case PIXEL_FORMAT_RGBX32:
1312 return "PIXEL_FORMAT_RGBX32";
1314 case PIXEL_FORMAT_BGRX32_DEPTH30:
1315 return "PIXEL_FORMAT_BGRX32_DEPTH30";
1317 case PIXEL_FORMAT_RGBX32_DEPTH30:
1318 return "PIXEL_FORMAT_RGBX32_DEPTH30";
1321 case PIXEL_FORMAT_RGB24:
1322 return "PIXEL_FORMAT_RGB24";
1324 case PIXEL_FORMAT_BGR24:
1325 return "PIXEL_FORMAT_BGR24";
1328 case PIXEL_FORMAT_RGB16:
1329 return "PIXEL_FORMAT_RGB16";
1331 case PIXEL_FORMAT_BGR16:
1332 return "PIXEL_FORMAT_BGR16";
1334 case PIXEL_FORMAT_ARGB15:
1335 return "PIXEL_FORMAT_ARGB15";
1337 case PIXEL_FORMAT_RGB15:
1338 return "PIXEL_FORMAT_RGB15";
1340 case PIXEL_FORMAT_ABGR15:
1341 return "PIXEL_FORMAT_ABGR15";
1343 case PIXEL_FORMAT_BGR15:
1344 return "PIXEL_FORMAT_BGR15";
1347 case PIXEL_FORMAT_RGB8:
1348 return "PIXEL_FORMAT_RGB8";
1351 case PIXEL_FORMAT_A4:
1352 return "PIXEL_FORMAT_A4";
1355 case PIXEL_FORMAT_MONO:
1356 return "PIXEL_FORMAT_MONO";
1363void FreeRDPSplitColor(UINT32 color, UINT32 format, BYTE* _r, BYTE* _g, BYTE* _b, BYTE* _a,
1364 const gdiPalette* palette)
1371 case PIXEL_FORMAT_ARGB32:
1373 *_a = (BYTE)(color >> 24);
1376 *_r = (BYTE)(color >> 16);
1379 *_g = (BYTE)(color >> 8);
1386 case PIXEL_FORMAT_XRGB32:
1388 *_r = (BYTE)(color >> 16);
1391 *_g = (BYTE)(color >> 8);
1401 case PIXEL_FORMAT_ABGR32:
1403 *_a = (BYTE)(color >> 24);
1406 *_b = (BYTE)(color >> 16);
1409 *_g = (BYTE)(color >> 8);
1416 case PIXEL_FORMAT_XBGR32:
1418 *_b = (BYTE)(color >> 16);
1421 *_g = (BYTE)(color >> 8);
1431 case PIXEL_FORMAT_RGBA32:
1433 *_r = (BYTE)(color >> 24);
1436 *_g = (BYTE)(color >> 16);
1439 *_b = (BYTE)(color >> 8);
1446 case PIXEL_FORMAT_RGBX32:
1448 *_r = (BYTE)(color >> 24);
1451 *_g = (BYTE)(color >> 16);
1454 *_b = (BYTE)(color >> 8);
1461 case PIXEL_FORMAT_BGRA32:
1463 *_b = (BYTE)(color >> 24);
1466 *_g = (BYTE)(color >> 16);
1469 *_r = (BYTE)(color >> 8);
1476 case PIXEL_FORMAT_BGRX32:
1478 *_b = (BYTE)(color >> 24);
1481 *_g = (BYTE)(color >> 16);
1484 *_r = (BYTE)(color >> 8);
1492 case PIXEL_FORMAT_RGB24:
1494 *_r = (BYTE)(color >> 16);
1497 *_g = (BYTE)(color >> 8);
1507 case PIXEL_FORMAT_BGR24:
1509 *_b = (BYTE)(color >> 16);
1512 *_g = (BYTE)(color >> 8);
1523 case PIXEL_FORMAT_RGB16:
1526 const UINT32 c = (color >> 11) & 0x1F;
1527 const UINT32 val = (c << 3) + c / 4;
1528 *_r = (BYTE)(val > 255 ? 255 : val);
1533 const UINT32 c = (color >> 5) & 0x3F;
1534 const UINT32 val = (c << 2) + c / 4 / 2;
1535 *_g = (BYTE)(val > 255 ? 255 : val);
1540 const UINT32 c = (color)&0x1F;
1541 const UINT32 val = (c << 3) + c / 4;
1542 *_b = (BYTE)(val > 255 ? 255 : val);
1550 case PIXEL_FORMAT_BGR16:
1553 const UINT32 c = (color)&0x1F;
1554 const UINT32 val = (c << 3) + c / 4;
1555 *_r = (BYTE)(val > 255 ? 255 : val);
1560 const UINT32 c = (color >> 5) & 0x3F;
1561 const UINT32 val = (c << 2) + c / 4 / 2;
1562 *_g = (BYTE)(val > 255 ? 255 : val);
1567 const UINT32 c = (color >> 11) & 0x1F;
1568 const UINT32 val = (c << 3) + c / 4;
1569 *_b = (BYTE)(val > 255 ? 255 : val);
1577 case PIXEL_FORMAT_ARGB15:
1580 const UINT32 c = (color >> 10) & 0x1F;
1581 const UINT32 val = (c << 3) + c / 4;
1582 *_r = (BYTE)(val > 255 ? 255 : val);
1587 const UINT32 c = (color >> 5) & 0x1F;
1588 const UINT32 val = (c << 3) + c / 4;
1589 *_g = (BYTE)(val > 255 ? 255 : val);
1594 const UINT32 c = (color)&0x1F;
1595 const UINT32 val = (c << 3) + c / 4;
1596 *_b = (BYTE)(val > 255 ? 255 : val);
1600 *_a = color & 0x8000 ? 0xFF : 0x00;
1604 case PIXEL_FORMAT_ABGR15:
1607 const UINT32 c = (color)&0x1F;
1608 const UINT32 val = (c << 3) + c / 4;
1609 *_r = (BYTE)(val > 255 ? 255 : val);
1614 const UINT32 c = (color >> 5) & 0x1F;
1615 const UINT32 val = (c << 3) + c / 4;
1616 *_g = (BYTE)(val > 255 ? 255 : val);
1621 const UINT32 c = (color >> 10) & 0x1F;
1622 const UINT32 val = (c << 3) + c / 4;
1623 *_b = (BYTE)(val > 255 ? 255 : val);
1627 *_a = color & 0x8000 ? 0xFF : 0x00;
1632 case PIXEL_FORMAT_RGB15:
1635 const UINT32 c = (color >> 10) & 0x1F;
1636 const UINT32 val = (c << 3) + c / 4;
1637 *_r = (BYTE)(val > 255 ? 255 : val);
1642 const UINT32 c = (color >> 5) & 0x1F;
1643 const UINT32 val = (c << 3) + c / 4;
1644 *_g = (BYTE)(val > 255 ? 255 : val);
1649 const UINT32 c = (color)&0x1F;
1650 const UINT32 val = (c << 3) + c / 4;
1651 *_b = (BYTE)(val > 255 ? 255 : val);
1659 case PIXEL_FORMAT_BGR15:
1662 const UINT32 c = (color)&0x1F;
1663 const UINT32 val = (c << 3) + c / 4;
1664 *_r = (BYTE)(val > 255 ? 255 : val);
1669 const UINT32 c = (color >> 5) & 0x1F;
1670 const UINT32 val = (c << 3) + c / 4;
1671 *_g = (BYTE)(val > 255 ? 255 : val);
1676 const UINT32 c = (color >> 10) & 0x1F;
1677 const UINT32 val = (c << 3) + c / 4;
1678 *_b = (BYTE)(val > 255 ? 255 : val);
1687 case PIXEL_FORMAT_RGB8:
1690 tmp = palette->palette[color];
1691 FreeRDPSplitColor(tmp, palette->format, _r, _g, _b, _a, NULL);
1711 case PIXEL_FORMAT_MONO:
1713 *_r = (color) ? 0xFF : 0x00;
1716 *_g = (color) ? 0xFF : 0x00;
1719 *_b = (color) ? 0xFF : 0x00;
1722 *_a = (color) ? 0xFF : 0x00;
1727 case PIXEL_FORMAT_A4:
1741 WLog_ERR(TAG,
"Unsupported format %s", FreeRDPGetColorFormatName(format));
1746BOOL FreeRDPWriteColorIgnoreAlpha(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT32 color)
1748 return FreeRDPWriteColorIgnoreAlpha_int(dst, format, color);
1751BOOL FreeRDPWriteColor(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT32 color)
1753 return FreeRDPWriteColor_int(dst, format, color);
1756UINT32 FreeRDPReadColor(
const BYTE* WINPR_RESTRICT src, UINT32 format)
1758 return FreeRDPReadColor_int(src, format);
1761UINT32 FreeRDPGetColor(UINT32 format, BYTE r, BYTE g, BYTE b, BYTE a)
1772 case PIXEL_FORMAT_ARGB32:
1773 return (_a << 24) | (_r << 16) | (_g << 8) | _b;
1775 case PIXEL_FORMAT_XRGB32:
1776 return (_r << 16) | (_g << 8) | _b;
1778 case PIXEL_FORMAT_ABGR32:
1779 return (_a << 24) | (_b << 16) | (_g << 8) | _r;
1781 case PIXEL_FORMAT_XBGR32:
1782 return (_b << 16) | (_g << 8) | _r;
1784 case PIXEL_FORMAT_RGBA32:
1785 return (_r << 24) | (_g << 16) | (_b << 8) | _a;
1787 case PIXEL_FORMAT_RGBX32:
1788 return (_r << 24) | (_g << 16) | (_b << 8) | _a;
1790 case PIXEL_FORMAT_BGRA32:
1791 return (_b << 24) | (_g << 16) | (_r << 8) | _a;
1793 case PIXEL_FORMAT_BGRX32:
1794 return (_b << 24) | (_g << 16) | (_r << 8) | _a;
1796 case PIXEL_FORMAT_RGBX32_DEPTH30:
1798 t = (_r << 22) | (_g << 12) | (_b << 2);
1800 return ((t & 0xff) << 24) | (((t >> 8) & 0xff) << 16) | (((t >> 16) & 0xff) << 8) |
1803 case PIXEL_FORMAT_BGRX32_DEPTH30:
1805 t = (_r << 22) | (_g << 12) | (_b << 2);
1807 return ((t & 0xff) << 24) | (((t >> 8) & 0xff) << 16) | (((t >> 16) & 0xff) << 8) |
1811 case PIXEL_FORMAT_RGB24:
1812 return (_r << 16) | (_g << 8) | _b;
1814 case PIXEL_FORMAT_BGR24:
1815 return (_b << 16) | (_g << 8) | _r;
1818 case PIXEL_FORMAT_RGB16:
1819 return (((_r >> 3) & 0x1F) << 11) | (((_g >> 2) & 0x3F) << 5) | ((_b >> 3) & 0x1F);
1821 case PIXEL_FORMAT_BGR16:
1822 return (((_b >> 3) & 0x1F) << 11) | (((_g >> 2) & 0x3F) << 5) | ((_r >> 3) & 0x1F);
1824 case PIXEL_FORMAT_ARGB15:
1825 return (((_r >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_b >> 3) & 0x1F) |
1826 (_a ? 0x8000 : 0x0000);
1828 case PIXEL_FORMAT_ABGR15:
1829 return (((_b >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_r >> 3) & 0x1F) |
1830 (_a ? 0x8000 : 0x0000);
1833 case PIXEL_FORMAT_RGB15:
1834 return (((_r >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_b >> 3) & 0x1F);
1836 case PIXEL_FORMAT_BGR15:
1837 return (((_b >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_r >> 3) & 0x1F);
1840 case PIXEL_FORMAT_RGB8:
1843 case PIXEL_FORMAT_A4:
1846 case PIXEL_FORMAT_MONO:
1848 WLog_ERR(TAG,
"Unsupported format %s", FreeRDPGetColorFormatName(format));
1853BOOL freerdp_image_copy_no_overlap(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
1854 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
1855 const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat,
1856 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
1857 const gdiPalette* WINPR_RESTRICT palette, UINT32 flags)
1861 prims = primitives_get();
1863 WINPR_ASSERT(!overlapping(pDstData, nYDst, nDstStep, pSrcData, nYSrc, nSrcStep, nHeight));
1864 WINPR_ASSERT(prims);
1866 return prims->
copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,
1867 pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette,
1868 flags) == PRIMITIVES_SUCCESS;
fn_copy_no_overlap_t copy_no_overlap