FreeRDP
Loading...
Searching...
No Matches
color.c
1
22#include <freerdp/config.h>
23
24#include <stdio.h>
25#include <string.h>
26#include <stdlib.h>
27
28#include <winpr/crt.h>
29
30#include <freerdp/log.h>
31#include <freerdp/freerdp.h>
32#include <freerdp/primitives.h>
33
34#if defined(WITH_CAIRO)
35#include <cairo.h>
36#endif
37
38#if defined(WITH_SWSCALE)
39#include <libswscale/swscale.h>
40#endif
41
42#include "color.h"
43
44#define TAG FREERDP_TAG("color")
45
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);
51
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)
56{
57 static uint64_t count = 0;
58 _snprintf(prefix, len, "cursor_dump_%08" PRIx64, count++);
59
60 return GetCombinedPath(CURSOR_DUMP_DIR, prefix);
61}
62
63static void dump_binary_data(FILE* fp, const uint8_t* data, size_t len)
64{
65 if (len > 0)
66 (void)fprintf(fp, "0x%02" PRIx8, data[0]);
67 for (size_t x = 1; x < len; x++)
68 {
69 (void)fprintf(fp, ", 0x%02" PRIx8, data[x]);
70 }
71}
72
73static void dump_uint_data(FILE* fp, const uint32_t* data, size_t len)
74{
75 if (len > 0)
76 (void)fprintf(fp, "0x%08" PRIx32, data[0]);
77 for (size_t x = 1; x < len; x++)
78 {
79 (void)fprintf(fp, ", 0x%08" PRIx32, data[x]);
80 }
81}
82
83static void dump_write_header(const char* path, const char* prefix)
84{
85 char* header = NULL;
86 size_t headerlen = 0;
87 winpr_asprintf(&header, &headerlen, "%s.h", path);
88 if (!header)
89 return;
90 FILE* fp = fopen(header, "w");
91 free(header);
92
93 if (!fp)
94 return;
95
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);
109 fclose(fp);
110}
111
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,
116 const uint8_t* bmp)
117{
118 const uint32_t format = PIXEL_FORMAT_BGRA32;
119 const uint32_t bpp = FreeRDPGetBytesPerPixel(format);
120 const uint32_t step = nWidth * bpp;
121
122 char* header = NULL;
123 size_t headerlen = 0;
124 winpr_asprintf(&header, &headerlen, "%s.c", path);
125 if (!header)
126 return;
127 FILE* fp = fopen(header, "w");
128 free(header);
129
130 if (fp)
131 {
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");
139
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");
144
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);
150 if (palette)
151 {
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");
156 }
157 else
158 (void)fprintf(fp, "0");
159
160 (void)fprintf(fp, "};\n");
161
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");
187 fclose(fp);
188 }
189
190 wImage* img = winpr_image_new();
191 if (img)
192 {
193 img->data = WINPR_CAST_CONST_PTR_AWAY(bmp, BYTE*);
194 img->bitsPerPixel = 32;
195 img->bytesPerPixel = 4;
196 img->height = nHeight;
197 img->width = nWidth;
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);
203 if (imgname)
204 winpr_image_write(img, imgname);
205 free(imgname);
206 winpr_image_free(img, FALSE);
207 }
208}
209
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)
219{
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));
226
227 if (!bmp || !path)
228 goto fail;
229
230 if (!freerdp_image_copy_from_pointer_data_int(bmp, format, step, 0, 0, nWidth, nHeight, xorMask,
231 xorMaskLength, andMask, andMaskLength, xorBpp,
232 palette))
233 goto fail;
234
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);
238
239fail:
240 free(bmp);
241 free(path);
242}
243#endif
244
245#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
246BYTE* freerdp_glyph_convert(UINT32 width, UINT32 height, const BYTE* WINPR_RESTRICT data)
247{
248 const size_t scanline = (width + 7ull) / 8ull;
249 const size_t required = scanline * height;
250 return freerdp_glyph_convert_ex(width, height, data, required);
251}
252#endif
253
254BYTE* freerdp_glyph_convert_ex(UINT32 width, UINT32 height, const BYTE* WINPR_RESTRICT data,
255 size_t len)
256{
257 /*
258 * converts a 1-bit-per-pixel glyph to a one-byte-per-pixel glyph:
259 * this approach uses a little more memory, but provides faster
260 * means of accessing individual pixels in blitting operations
261 */
262 const size_t scanline = (width + 7ull) / 8ull;
263 const size_t required = scanline * height;
264 if (len < required)
265 return NULL;
266
267 if ((len == 0) || (width == 0) || (height == 0))
268 return NULL;
269
270 WINPR_ASSERT(data);
271
272 BYTE* dstData = (BYTE*)winpr_aligned_malloc(1ull * width * height, 16);
273
274 if (!dstData)
275 return NULL;
276
277 ZeroMemory(dstData, 1ULL * width * height);
278 BYTE* dstp = dstData;
279
280 for (UINT32 y = 0; y < height; y++)
281 {
282 const BYTE* srcp = &data[1ull * y * scanline];
283
284 for (UINT32 x = 0; x < width; x++)
285 {
286 if ((*srcp & (0x80 >> (x % 8))) != 0)
287 *dstp = 0xFF;
288
289 dstp++;
290
291 if (((x + 1) % 8 == 0) && x != 0)
292 srcp++;
293 }
294 }
295
296 return dstData;
297}
298
299BOOL freerdp_image_copy_from_monochrome(BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,
300 UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT32 nWidth,
301 UINT32 nHeight, const BYTE* WINPR_RESTRICT pSrcData,
302 UINT32 backColor, UINT32 foreColor,
303 const gdiPalette* WINPR_RESTRICT palette)
304{
305 const UINT32 dstBytesPerPixel = FreeRDPGetBytesPerPixel(DstFormat);
306
307 if (!pDstData || !pSrcData || !palette)
308 return FALSE;
309
310 if (nDstStep == 0)
311 nDstStep = dstBytesPerPixel * nWidth;
312
313 const UINT32 monoStep = (nWidth + 7) / 8;
314
315 for (size_t y = 0; y < nHeight; y++)
316 {
317 BYTE* pDstLine = &pDstData[((nYDst + y) * nDstStep)];
318 UINT32 monoBit = 0x80;
319 const BYTE* monoBits = &pSrcData[monoStep * y];
320
321 for (size_t x = 0; x < nWidth; x++)
322 {
323 BYTE* pDstPixel = &pDstLine[((nXDst + x) * FreeRDPGetBytesPerPixel(DstFormat))];
324 BOOL monoPixel = (*monoBits & monoBit) ? TRUE : FALSE;
325
326 if (!(monoBit >>= 1))
327 {
328 monoBits++;
329 monoBit = 0x80;
330 }
331
332 if (monoPixel)
333 FreeRDPWriteColor_int(pDstPixel, DstFormat, backColor);
334 else
335 FreeRDPWriteColor_int(pDstPixel, DstFormat, foreColor);
336 }
337 }
338
339 return TRUE;
340}
341
342static inline UINT32 freerdp_image_inverted_pointer_color(UINT32 x, UINT32 y, UINT32 format)
343{
353 BYTE fill = (x + y) & 1 ? 0x00 : 0xFF;
354 return FreeRDPGetColor(format, fill, fill, fill, 0xFF);
355}
356
357/*
358 * DIB color palettes are arrays of RGBQUAD structs with colors in BGRX format.
359 * They are used only by 1, 2, 4, and 8-bit bitmaps.
360 */
361static void fill_gdi_palette_for_icon(const BYTE* colorTable, UINT16 cbColorTable,
362 gdiPalette* palette)
363{
364 WINPR_ASSERT(palette);
365
366 palette->format = PIXEL_FORMAT_BGRX32;
367 ZeroMemory(palette->palette, sizeof(palette->palette));
368
369 if (!cbColorTable)
370 return;
371
372 if ((cbColorTable % 4 != 0) || (cbColorTable / 4 > 256))
373 {
374 WLog_WARN(TAG, "weird palette size: %u", cbColorTable);
375 return;
376 }
377
378 for (UINT16 i = 0; i < cbColorTable / 4; i++)
379 {
380 palette->palette[i] = FreeRDPReadColor_int(&colorTable[4ULL * i], palette->format);
381 }
382}
383
384static inline UINT32 div_ceil(UINT32 a, UINT32 b)
385{
386 return (a + (b - 1)) / b;
387}
388
389static inline UINT32 round_up(UINT32 a, UINT32 b)
390{
391 return b * div_ceil(a, b);
392}
393
394BOOL freerdp_image_copy_from_icon_data(BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,
395 UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT16 nWidth,
396 UINT16 nHeight, const BYTE* WINPR_RESTRICT bitsColor,
397 UINT16 cbBitsColor, const BYTE* WINPR_RESTRICT bitsMask,
398 UINT16 cbBitsMask, const BYTE* WINPR_RESTRICT colorTable,
399 UINT16 cbColorTable, UINT32 bpp)
400{
401 DWORD format = 0;
402 gdiPalette palette;
403
404 if (!pDstData || !bitsColor)
405 return FALSE;
406
407 if ((nWidth == 0) || (nHeight == 0))
408 return TRUE;
409
410 /*
411 * Color formats used by icons are DIB bitmap formats (2-bit format
412 * is not used by MS-RDPERP). Note that 16-bit is RGB555, not RGB565,
413 * and that 32-bit format uses BGRA order.
414 */
415 switch (bpp)
416 {
417 case 1:
418 case 4:
419 /*
420 * These formats are not supported by freerdp_image_copy().
421 * PIXEL_FORMAT_MONO and PIXEL_FORMAT_A4 are *not* correct
422 * color formats for this. Please fix freerdp_image_copy()
423 * if you came here to fix a broken icon of some weird app
424 * that still uses 1 or 4bpp format in the 21st century.
425 */
426 WLog_WARN(TAG, "1bpp and 4bpp icons are not supported");
427 return FALSE;
428
429 case 8:
430 format = PIXEL_FORMAT_RGB8;
431 break;
432
433 case 16:
434 format = PIXEL_FORMAT_RGB15;
435 break;
436
437 case 24:
438 format = PIXEL_FORMAT_RGB24;
439 break;
440
441 case 32:
442 format = PIXEL_FORMAT_BGRA32;
443 break;
444
445 default:
446 WLog_WARN(TAG, "invalid icon bpp: %" PRIu32, bpp);
447 return FALSE;
448 }
449
450 /* Ensure we have enough source data bytes for image copy. */
451 if (cbBitsColor < nWidth * nHeight * FreeRDPGetBytesPerPixel(format))
452 {
453 WLog_ERR(TAG,
454 "cbBitsColor{%" PRIu32 "} < nWidth{%" PRIu32 "} * nHeight{%" PRIu32
455 "} * bpp{%" PRIu32 "}",
456 cbBitsColor, nWidth, nHeight, FreeRDPGetBytesPerPixel(format));
457 return FALSE;
458 }
459
460 fill_gdi_palette_for_icon(colorTable, cbColorTable, &palette);
461 if (!freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,
462 bitsColor, format, 0, 0, 0, &palette, FREERDP_FLIP_VERTICAL))
463 return FALSE;
464
465 /* apply alpha mask */
466 if (FreeRDPColorHasAlpha(DstFormat) && (cbBitsMask > 0))
467 {
468 BYTE* dstBuf = pDstData;
469 UINT32 dstBpp = FreeRDPGetBytesPerPixel(DstFormat);
470
471 /*
472 * Each byte encodes 8 adjacent pixels (with LSB padding as needed).
473 * And due to hysterical raisins, stride of DIB bitmaps must be
474 * a multiple of 4 bytes.
475 */
476 const size_t stride = round_up(div_ceil(nWidth, 8), 4);
477 if (cbBitsMask < stride * (nHeight - 1ULL))
478 {
479 WLog_ERR(TAG,
480 "cbBitsMask{%" PRIu32 "} < stride{%" PRIuz "} * (nHeight{%" PRIu32 "} - 1)",
481 cbBitsMask, stride, nHeight);
482 return FALSE;
483 }
484
485 for (UINT32 y = 0; y < nHeight; y++)
486 {
487 const BYTE* maskByte = &bitsMask[stride * (nHeight - 1ULL - y)];
488 BYTE nextBit = 0x80;
489
490 for (UINT32 x = 0; x < nWidth; x++)
491 {
492 BYTE r = 0;
493 BYTE g = 0;
494 BYTE b = 0;
495 BYTE alpha = (*maskByte & nextBit) ? 0x00 : 0xFF;
496
497 /* read color back, add alpha and write it back */
498 UINT32 color = FreeRDPReadColor_int(dstBuf, DstFormat);
499 FreeRDPSplitColor(color, DstFormat, &r, &g, &b, NULL, &palette);
500 color = FreeRDPGetColor(DstFormat, r, g, b, alpha);
501 FreeRDPWriteColor_int(dstBuf, DstFormat, color);
502
503 nextBit >>= 1;
504 dstBuf += dstBpp;
505 if (!nextBit)
506 {
507 nextBit = 0x80;
508 maskByte++;
509 }
510 }
511 }
512 }
513
514 return TRUE;
515}
516
517static BOOL freerdp_image_copy_from_pointer_data_1bpp(
518 BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
519 UINT32 nWidth, UINT32 nHeight, const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
520 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength, UINT32 xorBpp)
521{
522 BOOL vFlip = 0;
523 UINT32 xorStep = 0;
524 UINT32 andStep = 0;
525 UINT32 xorBit = 0;
526 UINT32 andBit = 0;
527 UINT32 xorPixel = 0;
528 UINT32 andPixel = 0;
529
530 vFlip = (xorBpp == 1) ? FALSE : TRUE;
531 andStep = (nWidth + 7) / 8;
532 andStep += (andStep % 2);
533
534 if (!xorMask || (xorMaskLength == 0))
535 return FALSE;
536 if (!andMask || (andMaskLength == 0))
537 return FALSE;
538
539 xorStep = (nWidth + 7) / 8;
540 xorStep += (xorStep % 2);
541
542 if (xorStep * nHeight > xorMaskLength)
543 return FALSE;
544
545 if (andStep * nHeight > andMaskLength)
546 return FALSE;
547
548 for (UINT32 y = 0; y < nHeight; y++)
549 {
550 const BYTE* andBits = NULL;
551 const BYTE* xorBits = NULL;
552 BYTE* pDstPixel = &pDstData[((1ULL * nYDst + y) * nDstStep) +
553 (1ULL * nXDst * FreeRDPGetBytesPerPixel(DstFormat))];
554 xorBit = andBit = 0x80;
555
556 if (!vFlip)
557 {
558 xorBits = &xorMask[1ULL * xorStep * y];
559 andBits = &andMask[1ULL * andStep * y];
560 }
561 else
562 {
563 xorBits = &xorMask[1ULL * xorStep * (nHeight - y - 1)];
564 andBits = &andMask[1ULL * andStep * (nHeight - y - 1)];
565 }
566
567 for (UINT32 x = 0; x < nWidth; x++)
568 {
569 UINT32 color = 0;
570 xorPixel = (*xorBits & xorBit) ? 1 : 0;
571
572 if (!(xorBit >>= 1))
573 {
574 xorBits++;
575 xorBit = 0x80;
576 }
577
578 andPixel = (*andBits & andBit) ? 1 : 0;
579
580 if (!(andBit >>= 1))
581 {
582 andBits++;
583 andBit = 0x80;
584 }
585
586 if (!andPixel && !xorPixel)
587 color = FreeRDPGetColor(DstFormat, 0, 0, 0, 0xFF); /* black */
588 else if (!andPixel && xorPixel)
589 color = FreeRDPGetColor(DstFormat, 0xFF, 0xFF, 0xFF, 0xFF); /* white */
590 else if (andPixel && !xorPixel)
591 color = FreeRDPGetColor(DstFormat, 0, 0, 0, 0); /* transparent */
592 else if (andPixel && xorPixel)
593 color = freerdp_image_inverted_pointer_color(x, y, DstFormat); /* inverted */
594
595 FreeRDPWriteColor_int(pDstPixel, DstFormat, color);
596 pDstPixel += FreeRDPGetBytesPerPixel(DstFormat);
597 }
598 }
599
600 return TRUE;
601}
602
603static BOOL freerdp_image_copy_from_pointer_data_xbpp(
604 BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
605 UINT32 nWidth, UINT32 nHeight, const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
606 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength, UINT32 xorBpp,
607 const gdiPalette* palette)
608{
609 BOOL vFlip = 0;
610 size_t xorStep = 0;
611 size_t andStep = 0;
612 UINT32 andBit = 0;
613 UINT32 xorPixel = 0;
614 UINT32 andPixel = 0;
615 UINT32 dstBitsPerPixel = 0;
616 UINT32 xorBytesPerPixel = 0;
617 dstBitsPerPixel = FreeRDPGetBitsPerPixel(DstFormat);
618
619 vFlip = (xorBpp == 1) ? FALSE : TRUE;
620 andStep = (nWidth + 7) / 8;
621 andStep += (andStep % 2);
622
623 if (!xorMask || (xorMaskLength == 0))
624 return FALSE;
625
626 xorBytesPerPixel = xorBpp >> 3;
627 xorStep = 1ULL * nWidth * xorBytesPerPixel;
628 xorStep += (xorStep % 2);
629
630 if (xorBpp == 8 && !palette)
631 {
632 WLog_ERR(TAG, "null palette in conversion from %" PRIu32 " bpp to %" PRIu32 " bpp", xorBpp,
633 dstBitsPerPixel);
634 return FALSE;
635 }
636
637 if (xorStep * nHeight > xorMaskLength)
638 return FALSE;
639
640 if (andMask)
641 {
642 if (andStep * nHeight > andMaskLength)
643 return FALSE;
644 }
645
646 for (UINT32 y = 0; y < nHeight; y++)
647 {
648 const BYTE* xorBits = NULL;
649 const BYTE* andBits = NULL;
650 BYTE* pDstPixel = &pDstData[((1ULL * nYDst + y) * nDstStep) +
651 (1ULL * nXDst * FreeRDPGetBytesPerPixel(DstFormat))];
652 andBit = 0x80;
653
654 if (!vFlip)
655 {
656 if (andMask)
657 andBits = &andMask[andStep * y];
658
659 xorBits = &xorMask[xorStep * y];
660 }
661 else
662 {
663 if (andMask)
664 andBits = &andMask[1ULL * andStep * (nHeight - y - 1)];
665
666 xorBits = &xorMask[1ULL * xorStep * (nHeight - y - 1)];
667 }
668
669 for (UINT32 x = 0; x < nWidth; x++)
670 {
671 UINT32 pixelFormat = 0;
672 UINT32 color = 0;
673
674 andPixel = 0;
675
676 if (andMask)
677 {
678 andPixel = (*andBits & andBit) ? 1 : 0;
679
680 if (!(andBit >>= 1))
681 {
682 andBits++;
683 andBit = 0x80;
684 }
685 }
686
687 if (xorBpp == 32)
688 {
689 pixelFormat = PIXEL_FORMAT_BGRA32;
690 xorPixel = FreeRDPReadColor_int(xorBits, pixelFormat);
691 }
692 else if (xorBpp == 16)
693 {
694 pixelFormat = PIXEL_FORMAT_RGB15;
695 xorPixel = FreeRDPReadColor_int(xorBits, pixelFormat);
696 }
697 else if (xorBpp == 8)
698 {
699 pixelFormat = palette->format;
700 xorPixel = palette->palette[xorBits[0]];
701 }
702 else
703 {
704 pixelFormat = PIXEL_FORMAT_BGR24;
705 xorPixel = FreeRDPReadColor_int(xorBits, pixelFormat);
706
707 if (andPixel)
708 {
709 if (xorPixel == 0x00FFFFFFUL)
710 xorPixel |= 0xFF000000UL;
711 else
712 xorPixel = 0;
713 }
714 else
715 xorPixel |= 0xFF000000UL;
716
717 // We need a transparent default alpha value, so use a different format here
718 pixelFormat = PIXEL_FORMAT_ABGR32;
719 }
720
721 xorPixel = FreeRDPConvertColor(xorPixel, pixelFormat, PIXEL_FORMAT_ARGB32, palette);
722 xorBits += xorBytesPerPixel;
723
724 if (andPixel)
725 {
726 if (xorPixel == 0xFF000000UL) /* black -> transparent */
727 xorPixel = 0x00000000;
728 else if (xorPixel == 0xFFFFFFFFUL) /* white -> inverted */
729 xorPixel = freerdp_image_inverted_pointer_color(x, y, PIXEL_FORMAT_ARGB32);
730 }
731
732 color = FreeRDPConvertColor(xorPixel, PIXEL_FORMAT_ARGB32, DstFormat, palette);
733 FreeRDPWriteColor_int(pDstPixel, DstFormat, color);
734 pDstPixel += FreeRDPGetBytesPerPixel(DstFormat);
735 }
736 }
737
738 return TRUE;
739}
740
749BOOL freerdp_image_copy_from_pointer_data_int(
750 BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
751 UINT32 nWidth, UINT32 nHeight, const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
752 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength, UINT32 xorBpp,
753 const gdiPalette* WINPR_RESTRICT palette)
754{
755 UINT32 dstBitsPerPixel = 0;
756 UINT32 dstBytesPerPixel = 0;
757 dstBitsPerPixel = FreeRDPGetBitsPerPixel(DstFormat);
758 dstBytesPerPixel = FreeRDPGetBytesPerPixel(DstFormat);
759
760 if (nDstStep <= 0)
761 nDstStep = dstBytesPerPixel * nWidth;
762
763 for (UINT32 y = nYDst; y < nHeight; y++)
764 {
765 BYTE* WINPR_RESTRICT pDstLine = &pDstData[y * nDstStep + nXDst * dstBytesPerPixel];
766 memset(pDstLine, 0, 1ull * dstBytesPerPixel * (nWidth - nXDst));
767 }
768
769 switch (xorBpp)
770 {
771 case 1:
772 return freerdp_image_copy_from_pointer_data_1bpp(
773 pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, xorMask,
774 xorMaskLength, andMask, andMaskLength, xorBpp);
775
776 case 8:
777 case 16:
778 case 24:
779 case 32:
780 return freerdp_image_copy_from_pointer_data_xbpp(
781 pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, xorMask,
782 xorMaskLength, andMask, andMaskLength, xorBpp, palette);
783
784 default:
785 WLog_ERR(TAG, "failed to convert from %" PRIu32 " bpp to %" PRIu32 " bpp", xorBpp,
786 dstBitsPerPixel);
787 return FALSE;
788 }
789}
790
791BOOL freerdp_image_copy_from_pointer_data(BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat,
792 UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
793 UINT32 nWidth, UINT32 nHeight,
794 const BYTE* WINPR_RESTRICT xorMask, UINT32 xorMaskLength,
795 const BYTE* WINPR_RESTRICT andMask, UINT32 andMaskLength,
796 UINT32 xorBpp, const gdiPalette* WINPR_RESTRICT palette)
797{
798#if defined(WITH_CURSOR_DUMP)
799 dump_pointer_data(nXDst, nYDst, nWidth, nHeight, xorMask, xorMaskLength, andMask, andMaskLength,
800 xorBpp, palette);
801#endif
802 return freerdp_image_copy_from_pointer_data_int(pDstData, DstFormat, nDstStep, nXDst, nYDst,
803 nWidth, nHeight, xorMask, xorMaskLength,
804 andMask, andMaskLength, xorBpp, palette);
805}
806
807static inline BOOL overlapping(const BYTE* pDstData, UINT32 nYDst, UINT32 nDstStep,
808 const BYTE* pSrcData, UINT32 nYSrc, UINT32 nSrcStep, UINT32 nHeight)
809{
810 const uintptr_t src = (uintptr_t)pSrcData;
811 const uintptr_t srcstart = src + 1ULL * nSrcStep * nYSrc;
812 const uintptr_t srcend = srcstart + 1ULL * nSrcStep * nHeight;
813 const uintptr_t dst = (uintptr_t)pDstData;
814 const uintptr_t dststart = dst + 1ULL * nDstStep * nYDst;
815 const uintptr_t dstend = dststart + 1ULL * nDstStep * nHeight;
816
817 if ((dststart >= srcstart) && (dststart <= srcend))
818 return TRUE;
819
820 if ((dstend >= srcstart) && (dstend <= srcend))
821 return TRUE;
822
823 return FALSE;
824}
825
826static inline BOOL freerdp_image_copy_bgr24_bgrx32(BYTE* WINPR_RESTRICT pDstData, UINT32 nDstStep,
827 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth,
828 UINT32 nHeight,
829 const BYTE* WINPR_RESTRICT pSrcData,
830 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
831 int64_t srcVMultiplier, int64_t srcVOffset,
832 int64_t dstVMultiplier, int64_t dstVOffset)
833{
834
835 const int64_t srcByte = 3;
836 const int64_t dstByte = 4;
837
838 for (int64_t y = 0; y < nHeight; y++)
839 {
840 const BYTE* WINPR_RESTRICT srcLine =
841 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
842 BYTE* WINPR_RESTRICT dstLine =
843 &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
844
845 for (int64_t x = 0; x < nWidth; x++)
846 {
847 dstLine[(x + nXDst) * dstByte + 0] = srcLine[(x + nXSrc) * srcByte + 0];
848 dstLine[(x + nXDst) * dstByte + 1] = srcLine[(x + nXSrc) * srcByte + 1];
849 dstLine[(x + nXDst) * dstByte + 2] = srcLine[(x + nXSrc) * srcByte + 2];
850 }
851 }
852
853 return TRUE;
854}
855
856static inline BOOL freerdp_image_copy_bgrx32_bgrx32(BYTE* WINPR_RESTRICT pDstData, UINT32 nDstStep,
857 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth,
858 UINT32 nHeight,
859 const BYTE* WINPR_RESTRICT pSrcData,
860 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
861 int64_t srcVMultiplier, int64_t srcVOffset,
862 int64_t dstVMultiplier, int64_t dstVOffset)
863{
864
865 const int64_t srcByte = 4;
866 const int64_t dstByte = 4;
867
868 for (int64_t y = 0; y < nHeight; y++)
869 {
870 const BYTE* WINPR_RESTRICT srcLine =
871 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
872 BYTE* WINPR_RESTRICT dstLine =
873 &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
874
875 for (int64_t x = 0; x < nWidth; x++)
876 {
877 dstLine[(x + nXDst) * dstByte + 0] = srcLine[(x + nXSrc) * srcByte + 0];
878 dstLine[(x + nXDst) * dstByte + 1] = srcLine[(x + nXSrc) * srcByte + 1];
879 dstLine[(x + nXDst) * dstByte + 2] = srcLine[(x + nXSrc) * srcByte + 2];
880 }
881 }
882
883 return TRUE;
884}
885
886static inline BOOL freerdp_image_copy_generic(
887 BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
888 UINT32 nWidth, UINT32 nHeight, const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcFormat,
889 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* WINPR_RESTRICT palette,
890 int64_t srcVMultiplier, int64_t srcVOffset, int64_t dstVMultiplier, int64_t dstVOffset)
891{
892
893 const int64_t srcByte = 4;
894 const int64_t dstByte = 4;
895
896 for (int64_t y = 0; y < nHeight; y++)
897 {
898 const BYTE* WINPR_RESTRICT srcLine =
899 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
900 BYTE* WINPR_RESTRICT dstLine =
901 &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
902
903 UINT32 color = FreeRDPReadColor_int(&srcLine[nXSrc * srcByte], SrcFormat);
904 UINT32 oldColor = color;
905 UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette);
906 FreeRDPWriteColorIgnoreAlpha_int(&dstLine[nXDst * dstByte], DstFormat, dstColor);
907 for (int64_t x = 1; x < nWidth; x++)
908 {
909 color = FreeRDPReadColor_int(&srcLine[(x + nXSrc) * srcByte], SrcFormat);
910 if (color == oldColor)
911 {
912 FreeRDPWriteColorIgnoreAlpha_int(&dstLine[(x + nXDst) * dstByte], DstFormat,
913 dstColor);
914 }
915 else
916 {
917 oldColor = color;
918 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette);
919 FreeRDPWriteColorIgnoreAlpha_int(&dstLine[(x + nXDst) * dstByte], DstFormat,
920 dstColor);
921 }
922 }
923 }
924
925 return TRUE;
926}
927
928static inline BOOL freerdp_image_copy_no_overlap_dst_alpha(
929 BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
930 UINT32 nWidth, UINT32 nHeight, const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat,
931 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* WINPR_RESTRICT palette,
932 int64_t srcVMultiplier, int64_t srcVOffset, int64_t dstVMultiplier, int64_t dstVOffset)
933{
934 WINPR_ASSERT(pDstData);
935 WINPR_ASSERT(pSrcData);
936
937 switch (SrcFormat)
938 {
939 case PIXEL_FORMAT_BGR24:
940 switch (DstFormat)
941 {
942 case PIXEL_FORMAT_BGRX32:
943 case PIXEL_FORMAT_BGRA32:
944 return freerdp_image_copy_bgr24_bgrx32(
945 pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, pSrcData, nSrcStep,
946 nXSrc, nYSrc, srcVMultiplier, srcVOffset, dstVMultiplier, dstVOffset);
947 default:
948 break;
949 }
950 break;
951 case PIXEL_FORMAT_BGRX32:
952 case PIXEL_FORMAT_BGRA32:
953 switch (DstFormat)
954 {
955 case PIXEL_FORMAT_BGRX32:
956 case PIXEL_FORMAT_BGRA32:
957 return freerdp_image_copy_bgrx32_bgrx32(
958 pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, pSrcData, nSrcStep,
959 nXSrc, nYSrc, srcVMultiplier, srcVOffset, dstVMultiplier, dstVOffset);
960 default:
961 break;
962 }
963 break;
964 default:
965 break;
966 }
967
968 return freerdp_image_copy_generic(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,
969 pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette,
970 srcVMultiplier, srcVOffset, dstVMultiplier, dstVOffset);
971}
972
973BOOL freerdp_image_copy_overlap(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst,
974 UINT32 nYDst, UINT32 nWidth, UINT32 nHeight, const BYTE* pSrcData,
975 DWORD SrcFormat, UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
976 const gdiPalette* WINPR_RESTRICT palette, UINT32 flags)
977{
978 const UINT32 dstByte = FreeRDPGetBytesPerPixel(DstFormat);
979 const UINT32 srcByte = FreeRDPGetBytesPerPixel(SrcFormat);
980 const UINT32 copyDstWidth = nWidth * dstByte;
981 const UINT32 xSrcOffset = nXSrc * srcByte;
982 const UINT32 xDstOffset = nXDst * dstByte;
983 const BOOL vSrcVFlip = (flags & FREERDP_FLIP_VERTICAL) ? TRUE : FALSE;
984 int64_t srcVOffset = 0;
985 int64_t srcVMultiplier = 1;
986 int64_t dstVOffset = 0;
987 int64_t dstVMultiplier = 1;
988
989 WINPR_ASSERT(overlapping(pDstData, nYDst, nDstStep, pSrcData, nYSrc, nSrcStep, nHeight));
990
991 if ((nWidth == 0) || (nHeight == 0))
992 return TRUE;
993
994 if ((nHeight > INT32_MAX) || (nWidth > INT32_MAX))
995 return FALSE;
996
997 if (!pDstData || !pSrcData)
998 return FALSE;
999
1000 if (nDstStep == 0)
1001 nDstStep = nWidth * FreeRDPGetBytesPerPixel(DstFormat);
1002
1003 if (nSrcStep == 0)
1004 nSrcStep = nWidth * FreeRDPGetBytesPerPixel(SrcFormat);
1005
1006 if (vSrcVFlip)
1007 {
1008 srcVOffset = (nHeight - 1ll) * nSrcStep;
1009 srcVMultiplier = -1;
1010 }
1011
1012 if (((flags & FREERDP_KEEP_DST_ALPHA) != 0) && FreeRDPColorHasAlpha(DstFormat))
1013 {
1014 return freerdp_image_copy_no_overlap_dst_alpha(
1015 pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, pSrcData, SrcFormat,
1016 nSrcStep, nXSrc, nYSrc, palette, srcVMultiplier, srcVOffset, dstVMultiplier,
1017 dstVOffset);
1018 }
1019 else if (FreeRDPAreColorFormatsEqualNoAlpha_int(SrcFormat, DstFormat))
1020 {
1021 /* Copy down */
1022 if (nYDst < nYSrc)
1023 {
1024 for (int64_t y = 0; y < nHeight; y++)
1025 {
1026 const BYTE* srcLine =
1027 &pSrcData[(y + nYSrc) * nSrcStep * srcVMultiplier + srcVOffset];
1028 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1029 memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
1030 }
1031 }
1032 /* Copy up */
1033 else if (nYDst > nYSrc)
1034 {
1035 for (int64_t y = nHeight - 1; y >= 0; y--)
1036 {
1037 const BYTE* srcLine =
1038 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
1039 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1040 memcpy(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
1041 }
1042 }
1043 /* Copy left */
1044 else if (nXSrc > nXDst)
1045 {
1046 for (int64_t y = 0; y < nHeight; y++)
1047 {
1048 const BYTE* srcLine =
1049 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
1050 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1051 memmove(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
1052 }
1053 }
1054 /* Copy right */
1055 else if (nXSrc < nXDst)
1056 {
1057 for (int64_t y = nHeight - 1; y >= 0; y--)
1058 {
1059 const BYTE* srcLine =
1060 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
1061 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1062 memmove(&dstLine[xDstOffset], &srcLine[xSrcOffset], copyDstWidth);
1063 }
1064 }
1065 /* Source and destination are equal... */
1066 else
1067 {
1068 }
1069 }
1070 else
1071 {
1072 for (int64_t y = 0; y < nHeight; y++)
1073 {
1074 const BYTE* srcLine = &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
1075 BYTE* dstLine = &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
1076
1077 UINT32 color = FreeRDPReadColor_int(&srcLine[1ULL * nXSrc * srcByte], SrcFormat);
1078 UINT32 oldColor = color;
1079 UINT32 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette);
1080 FreeRDPWriteColor_int(&dstLine[1ULL * nXDst * dstByte], DstFormat, dstColor);
1081 for (int64_t x = 1; x < nWidth; x++)
1082 {
1083 color = FreeRDPReadColor_int(&srcLine[(x + nXSrc) * srcByte], SrcFormat);
1084 if (color == oldColor)
1085 {
1086 FreeRDPWriteColor_int(&dstLine[(x + nXDst) * dstByte], DstFormat, dstColor);
1087 }
1088 else
1089 {
1090 oldColor = color;
1091 dstColor = FreeRDPConvertColor(color, SrcFormat, DstFormat, palette);
1092 FreeRDPWriteColor_int(&dstLine[(x + nXDst) * dstByte], DstFormat, dstColor);
1093 }
1094 }
1095 }
1096 }
1097
1098 return TRUE;
1099}
1100
1101BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst,
1102 UINT32 nYDst, UINT32 nWidth, UINT32 nHeight, const BYTE* pSrcData,
1103 DWORD SrcFormat, UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
1104 const gdiPalette* WINPR_RESTRICT palette, UINT32 flags)
1105{
1106 if ((nHeight > INT32_MAX) || (nWidth > INT32_MAX))
1107 return FALSE;
1108
1109 if (!pDstData || !pSrcData)
1110 return FALSE;
1111
1112 if ((nWidth == 0) || (nHeight == 0))
1113 return TRUE;
1114
1115 if (nDstStep == 0)
1116 nDstStep = nWidth * FreeRDPGetBytesPerPixel(DstFormat);
1117
1118 if (nSrcStep == 0)
1119 nSrcStep = nWidth * FreeRDPGetBytesPerPixel(SrcFormat);
1120
1121 const BOOL ovl = overlapping(pDstData, nYDst, nDstStep, pSrcData, nYSrc, nSrcStep, nHeight);
1122 if (ovl)
1123 return freerdp_image_copy_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth,
1124 nHeight, pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc,
1125 palette, flags);
1126 return freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth,
1127 nHeight, pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc,
1128 palette, flags);
1129}
1130
1131BOOL freerdp_image_fill(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
1132 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight, UINT32 color)
1133{
1134 if ((nWidth == 0) || (nHeight == 0))
1135 return TRUE;
1136 const UINT32 bpp = FreeRDPGetBytesPerPixel(DstFormat);
1137 BYTE* WINPR_RESTRICT pFirstDstLine = NULL;
1138 BYTE* WINPR_RESTRICT pFirstDstLineXOffset = NULL;
1139
1140 if (nDstStep == 0)
1141 nDstStep = (nXDst + nWidth) * FreeRDPGetBytesPerPixel(DstFormat);
1142
1143 pFirstDstLine = &pDstData[1ULL * nYDst * nDstStep];
1144 pFirstDstLineXOffset = &pFirstDstLine[1ULL * nXDst * bpp];
1145
1146 for (size_t x = 0; x < nWidth; x++)
1147 {
1148 BYTE* pDst = &pFirstDstLine[(x + nXDst) * bpp];
1149 FreeRDPWriteColor_int(pDst, DstFormat, color);
1150 }
1151
1152 for (size_t y = 1; y < nHeight; y++)
1153 {
1154 BYTE* pDstLine = &pDstData[(y + nYDst) * nDstStep + 1ULL * nXDst * bpp];
1155 memcpy(pDstLine, pFirstDstLineXOffset, 1ull * nWidth * bpp);
1156 }
1157
1158 return TRUE;
1159}
1160
1161BOOL freerdp_image_fill_ex(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
1162 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight, UINT32 color,
1163 UINT32 flags)
1164{
1165 if (FreeRDPColorHasAlpha(DstFormat) && ((flags & FREERDP_IMAGE_FILL_IGNORE_ALPHA) != 0))
1166 {
1167 const UINT32 bpp = FreeRDPGetBytesPerPixel(DstFormat);
1168 BYTE r = 0;
1169 BYTE g = 0;
1170 BYTE b = 0;
1171 FreeRDPSplitColor(color, DstFormat, &r, &g, &b, NULL, NULL);
1172
1173 for (size_t y = 0; y < nHeight; y++)
1174 {
1175 BYTE* WINPR_RESTRICT line = &pDstData[(y + nYDst) * nDstStep];
1176
1177 for (size_t x = 0; x < nWidth; x++)
1178 {
1179 BYTE* WINPR_RESTRICT dst = &line[x * bpp];
1180 const UINT32 dcolor = FreeRDPReadColor_int(dst, DstFormat);
1181 BYTE a = 0;
1182 FreeRDPSplitColor(dcolor, DstFormat, NULL, NULL, NULL, &a, NULL);
1183 const UINT32 scolor = FreeRDPGetColor(DstFormat, r, g, b, a);
1184 if (!FreeRDPWriteColor_int(dst, DstFormat, scolor))
1185 return FALSE;
1186 }
1187 }
1188 return TRUE;
1189 }
1190 return freerdp_image_fill(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight, color);
1191}
1192
1193#if defined(WITH_SWSCALE)
1194static enum AVPixelFormat av_format_for_buffer(UINT32 format)
1195{
1196 switch (format)
1197 {
1198 case PIXEL_FORMAT_ARGB32:
1199 return AV_PIX_FMT_BGRA;
1200
1201 case PIXEL_FORMAT_XRGB32:
1202 return AV_PIX_FMT_BGR0;
1203
1204 case PIXEL_FORMAT_BGRA32:
1205 return AV_PIX_FMT_RGBA;
1206
1207 case PIXEL_FORMAT_BGRX32:
1208 return AV_PIX_FMT_RGB0;
1209
1210 default:
1211 return AV_PIX_FMT_NONE;
1212 }
1213}
1214#endif
1215
1216BOOL freerdp_image_scale(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
1217 UINT32 nXDst, UINT32 nYDst, UINT32 nDstWidth, UINT32 nDstHeight,
1218 const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat, UINT32 nSrcStep,
1219 UINT32 nXSrc, UINT32 nYSrc, UINT32 nSrcWidth, UINT32 nSrcHeight)
1220{
1221 BOOL rc = FALSE;
1222
1223 if (nDstStep == 0)
1224 nDstStep = nDstWidth * FreeRDPGetBytesPerPixel(DstFormat);
1225
1226 if (nSrcStep == 0)
1227 nSrcStep = nSrcWidth * FreeRDPGetBytesPerPixel(SrcFormat);
1228
1229#if defined(WITH_SWSCALE) || defined(WITH_CAIRO)
1230 const BYTE* src = &pSrcData[nXSrc * FreeRDPGetBytesPerPixel(SrcFormat) + nYSrc * nSrcStep];
1231 BYTE* dst = &pDstData[nXDst * FreeRDPGetBytesPerPixel(DstFormat) + nYDst * nDstStep];
1232#endif
1233
1234 /* direct copy is much faster than scaling, so check if we can simply copy... */
1235 if ((nDstWidth == nSrcWidth) && (nDstHeight == nSrcHeight))
1236 {
1237 return freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nDstWidth,
1238 nDstHeight, pSrcData, SrcFormat, nSrcStep, nXSrc,
1239 nYSrc, NULL, FREERDP_FLIP_NONE);
1240 }
1241 else
1242#if defined(WITH_SWSCALE)
1243 {
1244 int res = 0;
1245 struct SwsContext* resize = NULL;
1246 enum AVPixelFormat srcFormat = av_format_for_buffer(SrcFormat);
1247 enum AVPixelFormat dstFormat = av_format_for_buffer(DstFormat);
1248 const int srcStep[1] = { (int)nSrcStep };
1249 const int dstStep[1] = { (int)nDstStep };
1250
1251 if ((srcFormat == AV_PIX_FMT_NONE) || (dstFormat == AV_PIX_FMT_NONE))
1252 return FALSE;
1253
1254 resize = sws_getContext((int)nSrcWidth, (int)nSrcHeight, srcFormat, (int)nDstWidth,
1255 (int)nDstHeight, dstFormat, SWS_BILINEAR, NULL, NULL, NULL);
1256
1257 if (!resize)
1258 goto fail;
1259
1260 res = sws_scale(resize, &src, srcStep, 0, (int)nSrcHeight, &dst, dstStep);
1261 rc = (res == ((int)nDstHeight));
1262 fail:
1263 sws_freeContext(resize);
1264 }
1265
1266#elif defined(WITH_CAIRO)
1267 {
1268 const double sx = (double)nDstWidth / (double)nSrcWidth;
1269 const double sy = (double)nDstHeight / (double)nSrcHeight;
1270 cairo_t* cairo_context;
1271 cairo_surface_t *csrc, *cdst;
1272
1273 if ((nSrcWidth > INT_MAX) || (nSrcHeight > INT_MAX) || (nSrcStep > INT_MAX))
1274 return FALSE;
1275
1276 if ((nDstWidth > INT_MAX) || (nDstHeight > INT_MAX) || (nDstStep > INT_MAX))
1277 return FALSE;
1278
1279 csrc = cairo_image_surface_create_for_data((void*)src, CAIRO_FORMAT_ARGB32, (int)nSrcWidth,
1280 (int)nSrcHeight, (int)nSrcStep);
1281 cdst = cairo_image_surface_create_for_data(dst, CAIRO_FORMAT_ARGB32, (int)nDstWidth,
1282 (int)nDstHeight, (int)nDstStep);
1283
1284 if (!csrc || !cdst)
1285 goto fail;
1286
1287 cairo_context = cairo_create(cdst);
1288
1289 if (!cairo_context)
1290 goto fail2;
1291
1292 cairo_scale(cairo_context, sx, sy);
1293 cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE);
1294 cairo_set_source_surface(cairo_context, csrc, 0, 0);
1295 cairo_paint(cairo_context);
1296 rc = TRUE;
1297 fail2:
1298 cairo_destroy(cairo_context);
1299 fail:
1300 cairo_surface_destroy(csrc);
1301 cairo_surface_destroy(cdst);
1302 }
1303#else
1304 {
1305 WLog_WARN(TAG, "SmartScaling requested but compiled without libcairo support!");
1306 }
1307#endif
1308 return rc;
1309}
1310
1311DWORD FreeRDPAreColorFormatsEqualNoAlpha(DWORD first, DWORD second)
1312{
1313 return FreeRDPAreColorFormatsEqualNoAlpha_int(first, second);
1314}
1315
1316const char* FreeRDPGetColorFormatName(UINT32 format)
1317{
1318#define ENTRY(x) \
1319 case x: \
1320 return #x;
1321
1322 switch (format)
1323 {
1324 ENTRY(PIXEL_FORMAT_ARGB32)
1325 ENTRY(PIXEL_FORMAT_XRGB32)
1326 ENTRY(PIXEL_FORMAT_ABGR32)
1327 ENTRY(PIXEL_FORMAT_XBGR32)
1328 ENTRY(PIXEL_FORMAT_BGRA32)
1329 ENTRY(PIXEL_FORMAT_BGRX32)
1330 ENTRY(PIXEL_FORMAT_RGBA32)
1331 ENTRY(PIXEL_FORMAT_RGBX32)
1332 ENTRY(PIXEL_FORMAT_BGRX32_DEPTH30)
1333 ENTRY(PIXEL_FORMAT_RGBX32_DEPTH30)
1334 ENTRY(PIXEL_FORMAT_RGB24)
1335 ENTRY(PIXEL_FORMAT_BGR24)
1336 ENTRY(PIXEL_FORMAT_RGB16)
1337 ENTRY(PIXEL_FORMAT_BGR16)
1338 ENTRY(PIXEL_FORMAT_ARGB15)
1339 ENTRY(PIXEL_FORMAT_RGB15)
1340 ENTRY(PIXEL_FORMAT_ABGR15)
1341 ENTRY(PIXEL_FORMAT_BGR15)
1342 ENTRY(PIXEL_FORMAT_RGB8)
1343 ENTRY(PIXEL_FORMAT_A4)
1344 ENTRY(PIXEL_FORMAT_MONO)
1345
1346 default:
1347 return "UNKNOWN";
1348 }
1349#undef ENTRY
1350}
1351
1352uint32_t FreeRDPGetColorFromatFromName(const char* name)
1353{
1354#define ENTRY(x) \
1355 if (strcmp(name, #x) == 0) \
1356 return x;
1357
1358 if (!name)
1359 return 0;
1360
1361 ENTRY(PIXEL_FORMAT_ARGB32)
1362 ENTRY(PIXEL_FORMAT_XRGB32)
1363 ENTRY(PIXEL_FORMAT_ABGR32)
1364 ENTRY(PIXEL_FORMAT_XBGR32)
1365 ENTRY(PIXEL_FORMAT_BGRA32)
1366 ENTRY(PIXEL_FORMAT_BGRX32)
1367 ENTRY(PIXEL_FORMAT_RGBA32)
1368 ENTRY(PIXEL_FORMAT_RGBX32)
1369 ENTRY(PIXEL_FORMAT_BGRX32_DEPTH30)
1370 ENTRY(PIXEL_FORMAT_RGBX32_DEPTH30)
1371 ENTRY(PIXEL_FORMAT_RGB24)
1372 ENTRY(PIXEL_FORMAT_BGR24)
1373 ENTRY(PIXEL_FORMAT_RGB16)
1374 ENTRY(PIXEL_FORMAT_BGR16)
1375 ENTRY(PIXEL_FORMAT_ARGB15)
1376 ENTRY(PIXEL_FORMAT_RGB15)
1377 ENTRY(PIXEL_FORMAT_ABGR15)
1378 ENTRY(PIXEL_FORMAT_BGR15)
1379 ENTRY(PIXEL_FORMAT_RGB8)
1380 ENTRY(PIXEL_FORMAT_A4)
1381 ENTRY(PIXEL_FORMAT_MONO)
1382
1383 return 0;
1384#undef ENTRY
1385}
1386
1387void FreeRDPSplitColor(UINT32 color, UINT32 format, BYTE* _r, BYTE* _g, BYTE* _b, BYTE* _a,
1388 const gdiPalette* palette)
1389{
1390 UINT32 tmp = 0;
1391
1392 switch (format)
1393 {
1394 /* 32bpp formats */
1395 case PIXEL_FORMAT_ARGB32:
1396 if (_a)
1397 *_a = (BYTE)(color >> 24);
1398
1399 if (_r)
1400 *_r = (BYTE)(color >> 16);
1401
1402 if (_g)
1403 *_g = (BYTE)(color >> 8);
1404
1405 if (_b)
1406 *_b = (BYTE)color;
1407
1408 break;
1409
1410 case PIXEL_FORMAT_XRGB32:
1411 if (_r)
1412 *_r = (BYTE)(color >> 16);
1413
1414 if (_g)
1415 *_g = (BYTE)(color >> 8);
1416
1417 if (_b)
1418 *_b = (BYTE)color;
1419
1420 if (_a)
1421 *_a = 0xFF;
1422
1423 break;
1424
1425 case PIXEL_FORMAT_ABGR32:
1426 if (_a)
1427 *_a = (BYTE)(color >> 24);
1428
1429 if (_b)
1430 *_b = (BYTE)(color >> 16);
1431
1432 if (_g)
1433 *_g = (BYTE)(color >> 8);
1434
1435 if (_r)
1436 *_r = (BYTE)color;
1437
1438 break;
1439
1440 case PIXEL_FORMAT_XBGR32:
1441 if (_b)
1442 *_b = (BYTE)(color >> 16);
1443
1444 if (_g)
1445 *_g = (BYTE)(color >> 8);
1446
1447 if (_r)
1448 *_r = (BYTE)color;
1449
1450 if (_a)
1451 *_a = 0xFF;
1452
1453 break;
1454
1455 case PIXEL_FORMAT_RGBA32:
1456 if (_r)
1457 *_r = (BYTE)(color >> 24);
1458
1459 if (_g)
1460 *_g = (BYTE)(color >> 16);
1461
1462 if (_b)
1463 *_b = (BYTE)(color >> 8);
1464
1465 if (_a)
1466 *_a = (BYTE)color;
1467
1468 break;
1469
1470 case PIXEL_FORMAT_RGBX32:
1471 if (_r)
1472 *_r = (BYTE)(color >> 24);
1473
1474 if (_g)
1475 *_g = (BYTE)(color >> 16);
1476
1477 if (_b)
1478 *_b = (BYTE)(color >> 8);
1479
1480 if (_a)
1481 *_a = 0xFF;
1482
1483 break;
1484
1485 case PIXEL_FORMAT_BGRA32:
1486 if (_b)
1487 *_b = (BYTE)(color >> 24);
1488
1489 if (_g)
1490 *_g = (BYTE)(color >> 16);
1491
1492 if (_r)
1493 *_r = (BYTE)(color >> 8);
1494
1495 if (_a)
1496 *_a = (BYTE)color;
1497
1498 break;
1499
1500 case PIXEL_FORMAT_BGRX32:
1501 if (_b)
1502 *_b = (BYTE)(color >> 24);
1503
1504 if (_g)
1505 *_g = (BYTE)(color >> 16);
1506
1507 if (_r)
1508 *_r = (BYTE)(color >> 8);
1509
1510 if (_a)
1511 *_a = 0xFF;
1512
1513 break;
1514
1515 /* 24bpp formats */
1516 case PIXEL_FORMAT_RGB24:
1517 if (_r)
1518 *_r = (BYTE)(color >> 16);
1519
1520 if (_g)
1521 *_g = (BYTE)(color >> 8);
1522
1523 if (_b)
1524 *_b = (BYTE)color;
1525
1526 if (_a)
1527 *_a = 0xFF;
1528
1529 break;
1530
1531 case PIXEL_FORMAT_BGR24:
1532 if (_b)
1533 *_b = (BYTE)(color >> 16);
1534
1535 if (_g)
1536 *_g = (BYTE)(color >> 8);
1537
1538 if (_r)
1539 *_r = (BYTE)color;
1540
1541 if (_a)
1542 *_a = 0xFF;
1543
1544 break;
1545
1546 /* 16bpp formats */
1547 case PIXEL_FORMAT_RGB16:
1548 if (_r)
1549 {
1550 const UINT32 c = (color >> 11) & 0x1F;
1551 const UINT32 val = (c << 3) + c / 4;
1552 *_r = (BYTE)(val > 255 ? 255 : val);
1553 }
1554
1555 if (_g)
1556 {
1557 const UINT32 c = (color >> 5) & 0x3F;
1558 const UINT32 val = (c << 2) + c / 4 / 2;
1559 *_g = (BYTE)(val > 255 ? 255 : val);
1560 }
1561
1562 if (_b)
1563 {
1564 const UINT32 c = (color)&0x1F;
1565 const UINT32 val = (c << 3) + c / 4;
1566 *_b = (BYTE)(val > 255 ? 255 : val);
1567 }
1568
1569 if (_a)
1570 *_a = 0xFF;
1571
1572 break;
1573
1574 case PIXEL_FORMAT_BGR16:
1575 if (_r)
1576 {
1577 const UINT32 c = (color)&0x1F;
1578 const UINT32 val = (c << 3) + c / 4;
1579 *_r = (BYTE)(val > 255 ? 255 : val);
1580 }
1581
1582 if (_g)
1583 {
1584 const UINT32 c = (color >> 5) & 0x3F;
1585 const UINT32 val = (c << 2) + c / 4 / 2;
1586 *_g = (BYTE)(val > 255 ? 255 : val);
1587 }
1588
1589 if (_b)
1590 {
1591 const UINT32 c = (color >> 11) & 0x1F;
1592 const UINT32 val = (c << 3) + c / 4;
1593 *_b = (BYTE)(val > 255 ? 255 : val);
1594 }
1595
1596 if (_a)
1597 *_a = 0xFF;
1598
1599 break;
1600
1601 case PIXEL_FORMAT_ARGB15:
1602 if (_r)
1603 {
1604 const UINT32 c = (color >> 10) & 0x1F;
1605 const UINT32 val = (c << 3) + c / 4;
1606 *_r = (BYTE)(val > 255 ? 255 : val);
1607 }
1608
1609 if (_g)
1610 {
1611 const UINT32 c = (color >> 5) & 0x1F;
1612 const UINT32 val = (c << 3) + c / 4;
1613 *_g = (BYTE)(val > 255 ? 255 : val);
1614 }
1615
1616 if (_b)
1617 {
1618 const UINT32 c = (color)&0x1F;
1619 const UINT32 val = (c << 3) + c / 4;
1620 *_b = (BYTE)(val > 255 ? 255 : val);
1621 }
1622
1623 if (_a)
1624 *_a = color & 0x8000 ? 0xFF : 0x00;
1625
1626 break;
1627
1628 case PIXEL_FORMAT_ABGR15:
1629 if (_r)
1630 {
1631 const UINT32 c = (color)&0x1F;
1632 const UINT32 val = (c << 3) + c / 4;
1633 *_r = (BYTE)(val > 255 ? 255 : val);
1634 }
1635
1636 if (_g)
1637 {
1638 const UINT32 c = (color >> 5) & 0x1F;
1639 const UINT32 val = (c << 3) + c / 4;
1640 *_g = (BYTE)(val > 255 ? 255 : val);
1641 }
1642
1643 if (_b)
1644 {
1645 const UINT32 c = (color >> 10) & 0x1F;
1646 const UINT32 val = (c << 3) + c / 4;
1647 *_b = (BYTE)(val > 255 ? 255 : val);
1648 }
1649
1650 if (_a)
1651 *_a = color & 0x8000 ? 0xFF : 0x00;
1652
1653 break;
1654
1655 /* 15bpp formats */
1656 case PIXEL_FORMAT_RGB15:
1657 if (_r)
1658 {
1659 const UINT32 c = (color >> 10) & 0x1F;
1660 const UINT32 val = (c << 3) + c / 4;
1661 *_r = (BYTE)(val > 255 ? 255 : val);
1662 }
1663
1664 if (_g)
1665 {
1666 const UINT32 c = (color >> 5) & 0x1F;
1667 const UINT32 val = (c << 3) + c / 4;
1668 *_g = (BYTE)(val > 255 ? 255 : val);
1669 }
1670
1671 if (_b)
1672 {
1673 const UINT32 c = (color)&0x1F;
1674 const UINT32 val = (c << 3) + c / 4;
1675 *_b = (BYTE)(val > 255 ? 255 : val);
1676 }
1677
1678 if (_a)
1679 *_a = 0xFF;
1680
1681 break;
1682
1683 case PIXEL_FORMAT_BGR15:
1684 if (_r)
1685 {
1686 const UINT32 c = (color)&0x1F;
1687 const UINT32 val = (c << 3) + c / 4;
1688 *_r = (BYTE)(val > 255 ? 255 : val);
1689 }
1690
1691 if (_g)
1692 {
1693 const UINT32 c = (color >> 5) & 0x1F;
1694 const UINT32 val = (c << 3) + c / 4;
1695 *_g = (BYTE)(val > 255 ? 255 : val);
1696 }
1697
1698 if (_b)
1699 {
1700 const UINT32 c = (color >> 10) & 0x1F;
1701 const UINT32 val = (c << 3) + c / 4;
1702 *_b = (BYTE)(val > 255 ? 255 : val);
1703 }
1704
1705 if (_a)
1706 *_a = 0xFF;
1707
1708 break;
1709
1710 /* 8bpp formats */
1711 case PIXEL_FORMAT_RGB8:
1712 if (color <= 0xFF)
1713 {
1714 tmp = palette->palette[color];
1715 FreeRDPSplitColor(tmp, palette->format, _r, _g, _b, _a, NULL);
1716 }
1717 else
1718 {
1719 if (_r)
1720 *_r = 0x00;
1721
1722 if (_g)
1723 *_g = 0x00;
1724
1725 if (_b)
1726 *_b = 0x00;
1727
1728 if (_a)
1729 *_a = 0x00;
1730 }
1731
1732 break;
1733
1734 /* 1bpp formats */
1735 case PIXEL_FORMAT_MONO:
1736 if (_r)
1737 *_r = (color) ? 0xFF : 0x00;
1738
1739 if (_g)
1740 *_g = (color) ? 0xFF : 0x00;
1741
1742 if (_b)
1743 *_b = (color) ? 0xFF : 0x00;
1744
1745 if (_a)
1746 *_a = (color) ? 0xFF : 0x00;
1747
1748 break;
1749
1750 /* 4 bpp formats */
1751 case PIXEL_FORMAT_A4:
1752 default:
1753 if (_r)
1754 *_r = 0x00;
1755
1756 if (_g)
1757 *_g = 0x00;
1758
1759 if (_b)
1760 *_b = 0x00;
1761
1762 if (_a)
1763 *_a = 0x00;
1764
1765 WLog_ERR(TAG, "Unsupported format %s", FreeRDPGetColorFormatName(format));
1766 break;
1767 }
1768}
1769
1770BOOL FreeRDPWriteColorIgnoreAlpha(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT32 color)
1771{
1772 return FreeRDPWriteColorIgnoreAlpha_int(dst, format, color);
1773}
1774
1775BOOL FreeRDPWriteColor(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT32 color)
1776{
1777 return FreeRDPWriteColor_int(dst, format, color);
1778}
1779
1780UINT32 FreeRDPReadColor(const BYTE* WINPR_RESTRICT src, UINT32 format)
1781{
1782 return FreeRDPReadColor_int(src, format);
1783}
1784
1785UINT32 FreeRDPGetColor(UINT32 format, BYTE r, BYTE g, BYTE b, BYTE a)
1786{
1787 UINT32 _r = r;
1788 UINT32 _g = g;
1789 UINT32 _b = b;
1790 UINT32 _a = a;
1791 UINT32 t = 0;
1792
1793 switch (format)
1794 {
1795 /* 32bpp formats */
1796 case PIXEL_FORMAT_ARGB32:
1797 return (_a << 24) | (_r << 16) | (_g << 8) | _b;
1798
1799 case PIXEL_FORMAT_XRGB32:
1800 return (_r << 16) | (_g << 8) | _b;
1801
1802 case PIXEL_FORMAT_ABGR32:
1803 return (_a << 24) | (_b << 16) | (_g << 8) | _r;
1804
1805 case PIXEL_FORMAT_XBGR32:
1806 return (_b << 16) | (_g << 8) | _r;
1807
1808 case PIXEL_FORMAT_RGBA32:
1809 return (_r << 24) | (_g << 16) | (_b << 8) | _a;
1810
1811 case PIXEL_FORMAT_RGBX32:
1812 return (_r << 24) | (_g << 16) | (_b << 8) | _a;
1813
1814 case PIXEL_FORMAT_BGRA32:
1815 return (_b << 24) | (_g << 16) | (_r << 8) | _a;
1816
1817 case PIXEL_FORMAT_BGRX32:
1818 return (_b << 24) | (_g << 16) | (_r << 8) | _a;
1819
1820 case PIXEL_FORMAT_RGBX32_DEPTH30:
1821 // TODO: Not tested
1822 t = (_r << 22) | (_g << 12) | (_b << 2);
1823 // NOTE: Swapping byte-order because FreeRDPWriteColor written UINT32 in big-endian
1824 return ((t & 0xff) << 24) | (((t >> 8) & 0xff) << 16) | (((t >> 16) & 0xff) << 8) |
1825 (t >> 24);
1826
1827 case PIXEL_FORMAT_BGRX32_DEPTH30:
1828 // NOTE: Swapping b and r channel (unknown reason)
1829 t = (_r << 22) | (_g << 12) | (_b << 2);
1830 // NOTE: Swapping byte-order because FreeRDPWriteColor written UINT32 in big-endian
1831 return ((t & 0xff) << 24) | (((t >> 8) & 0xff) << 16) | (((t >> 16) & 0xff) << 8) |
1832 (t >> 24);
1833
1834 /* 24bpp formats */
1835 case PIXEL_FORMAT_RGB24:
1836 return (_r << 16) | (_g << 8) | _b;
1837
1838 case PIXEL_FORMAT_BGR24:
1839 return (_b << 16) | (_g << 8) | _r;
1840
1841 /* 16bpp formats */
1842 case PIXEL_FORMAT_RGB16:
1843 return (((_r >> 3) & 0x1F) << 11) | (((_g >> 2) & 0x3F) << 5) | ((_b >> 3) & 0x1F);
1844
1845 case PIXEL_FORMAT_BGR16:
1846 return (((_b >> 3) & 0x1F) << 11) | (((_g >> 2) & 0x3F) << 5) | ((_r >> 3) & 0x1F);
1847
1848 case PIXEL_FORMAT_ARGB15:
1849 return (((_r >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_b >> 3) & 0x1F) |
1850 (_a ? 0x8000 : 0x0000);
1851
1852 case PIXEL_FORMAT_ABGR15:
1853 return (((_b >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_r >> 3) & 0x1F) |
1854 (_a ? 0x8000 : 0x0000);
1855
1856 /* 15bpp formats */
1857 case PIXEL_FORMAT_RGB15:
1858 return (((_r >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_b >> 3) & 0x1F);
1859
1860 case PIXEL_FORMAT_BGR15:
1861 return (((_b >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_r >> 3) & 0x1F);
1862
1863 /* 8bpp formats */
1864 case PIXEL_FORMAT_RGB8:
1865
1866 /* 4 bpp formats */
1867 case PIXEL_FORMAT_A4:
1868
1869 /* 1bpp formats */
1870 case PIXEL_FORMAT_MONO:
1871 default:
1872 WLog_ERR(TAG, "Unsupported format %s", FreeRDPGetColorFormatName(format));
1873 return 0;
1874 }
1875}
1876
1877BOOL freerdp_image_copy_no_overlap(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep,
1878 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
1879 const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat,
1880 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
1881 const gdiPalette* WINPR_RESTRICT palette, UINT32 flags)
1882{
1883 static primitives_t* prims = NULL;
1884 if (!prims)
1885 prims = primitives_get();
1886
1887 WINPR_ASSERT(!overlapping(pDstData, nYDst, nDstStep, pSrcData, nYSrc, nSrcStep, nHeight));
1888 WINPR_ASSERT(prims);
1889 WINPR_ASSERT(prims->copy_no_overlap);
1890 return prims->copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,
1891 pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette,
1892 flags) == PRIMITIVES_SUCCESS;
1893}
fn_copy_no_overlap_t copy_no_overlap
Definition primitives.h:304