1 /**
2  * FreeRDP: A Remote Desktop Protocol Implementation
3  * Color Conversion Routines
4  *
5  * Copyright 2010 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  * Copyright 2016 Armin Novak <armin.novak@thincast.com>
7  * Copyright 2016 Thincast Technologies GmbH
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *     http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21 
22 #ifndef FREERDP_CODEC_COLOR_H
23 #define FREERDP_CODEC_COLOR_H
24 
25 #include <freerdp/api.h>
26 #include <winpr/wlog.h>
27 #include <freerdp/log.h>
28 #define CTAG FREERDP_TAG("codec.color")
29 
30 #define FREERDP_PIXEL_FORMAT_TYPE_A 0
31 #define FREERDP_PIXEL_FORMAT_TYPE_ARGB 1
32 #define FREERDP_PIXEL_FORMAT_TYPE_ABGR 2
33 #define FREERDP_PIXEL_FORMAT_TYPE_RGBA 3
34 #define FREERDP_PIXEL_FORMAT_TYPE_BGRA 4
35 
36 #define FREERDP_PIXEL_FORMAT_IS_ABGR(_format) \
37 	(FREERDP_PIXEL_FORMAT_TYPE(_format) == FREERDP_PIXEL_FORMAT_TYPE_ABGR)
38 
39 #define FREERDP_FLIP_NONE 0
40 #define FREERDP_FLIP_VERTICAL 1
41 #define FREERDP_FLIP_HORIZONTAL 2
42 
43 #define FREERDP_PIXEL_FORMAT(_bpp, _type, _a, _r, _g, _b) \
44 	((_bpp << 24) | (_type << 16) | (_a << 12) | (_r << 8) | (_g << 4) | (_b))
45 
46 #define FREERDP_PIXEL_FORMAT_TYPE(_format) (((_format) >> 16) & 0x07)
47 
48 /*** Design considerations
49  *
50  * The format naming scheme is based on byte position in memory.
51  * RGBA for example names a byte array with red on positon 0, green on 1 etc.
52  *
53  * To read and write the appropriate format from / to memory use ReadColor and
54  * WriteColor.
55  *
56  * The single pixel manipulation functions use an intermediate integer representation
57  * that must not be interpreted outside the functions as it is platform dependent.
58  *
59  * X for alpha channel denotes unused (but existing) alpha channel data.
60  */
61 
62 /* 32bpp formats */
63 #define PIXEL_FORMAT_ARGB32 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 8, 8, 8, 8)
64 #define PIXEL_FORMAT_XRGB32 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8)
65 #define PIXEL_FORMAT_ABGR32 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 8, 8, 8, 8)
66 #define PIXEL_FORMAT_XBGR32 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 8, 8, 8)
67 #define PIXEL_FORMAT_BGRA32 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_BGRA, 8, 8, 8, 8)
68 #define PIXEL_FORMAT_BGRX32 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_BGRA, 0, 8, 8, 8)
69 #define PIXEL_FORMAT_RGBA32 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 8, 8, 8, 8)
70 #define PIXEL_FORMAT_RGBX32 FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_RGBA, 0, 8, 8, 8)
71 
72 /* 24bpp formats */
73 #define PIXEL_FORMAT_RGB24 FREERDP_PIXEL_FORMAT(24, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 8, 8, 8)
74 #define PIXEL_FORMAT_BGR24 FREERDP_PIXEL_FORMAT(24, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 8, 8, 8)
75 
76 /* 16bpp formats */
77 #define PIXEL_FORMAT_RGB16 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 6, 5)
78 #define PIXEL_FORMAT_BGR16 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 6, 5)
79 #define PIXEL_FORMAT_ARGB15 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 1, 5, 5, 5)
80 #define PIXEL_FORMAT_RGB15 FREERDP_PIXEL_FORMAT(15, FREERDP_PIXEL_FORMAT_TYPE_ARGB, 0, 5, 5, 5)
81 #define PIXEL_FORMAT_ABGR15 FREERDP_PIXEL_FORMAT(16, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 1, 5, 5, 5)
82 #define PIXEL_FORMAT_BGR15 FREERDP_PIXEL_FORMAT(15, FREERDP_PIXEL_FORMAT_TYPE_ABGR, 0, 5, 5, 5)
83 
84 /* 8bpp formats */
85 #define PIXEL_FORMAT_RGB8 FREERDP_PIXEL_FORMAT(8, FREERDP_PIXEL_FORMAT_TYPE_A, 8, 0, 0, 0)
86 
87 /* 4 bpp formats */
88 #define PIXEL_FORMAT_A4 FREERDP_PIXEL_FORMAT(4, FREERDP_PIXEL_FORMAT_TYPE_A, 4, 0, 0, 0)
89 
90 /* 1bpp formats */
91 #define PIXEL_FORMAT_MONO FREERDP_PIXEL_FORMAT(1, FREERDP_PIXEL_FORMAT_TYPE_A, 1, 0, 0, 0)
92 
93 struct gdi_palette
94 {
95 	UINT32 format;
96 	UINT32 palette[256];
97 };
98 typedef struct gdi_palette gdiPalette;
99 
100 #ifdef __cplusplus
101 extern "C"
102 {
103 #endif
104 
105 	/* Compare two color formats but ignore differences in alpha channel.
106 	 */
AreColorFormatsEqualNoAlpha(DWORD first,DWORD second)107 	static INLINE DWORD AreColorFormatsEqualNoAlpha(DWORD first, DWORD second)
108 	{
109 		const DWORD mask = ~(8 << 12);
110 		return (first & mask) == (second & mask);
111 	}
112 
113 	/* Color Space Conversions: http://msdn.microsoft.com/en-us/library/ff566496/ */
114 
115 	/***
116 	 *
117 	 * Get a string representation of a color
118 	 *
119 	 * @param format The pixel color format
120 	 *
121 	 * @return A string representation of format
122 	 */
FreeRDPGetColorFormatName(UINT32 format)123 	static const char* FreeRDPGetColorFormatName(UINT32 format)
124 	{
125 		switch (format)
126 		{
127 			/* 32bpp formats */
128 			case PIXEL_FORMAT_ARGB32:
129 				return "PIXEL_FORMAT_ARGB32";
130 
131 			case PIXEL_FORMAT_XRGB32:
132 				return "PIXEL_FORMAT_XRGB32";
133 
134 			case PIXEL_FORMAT_ABGR32:
135 				return "PIXEL_FORMAT_ABGR32";
136 
137 			case PIXEL_FORMAT_XBGR32:
138 				return "PIXEL_FORMAT_XBGR32";
139 
140 			case PIXEL_FORMAT_BGRA32:
141 				return "PIXEL_FORMAT_BGRA32";
142 
143 			case PIXEL_FORMAT_BGRX32:
144 				return "PIXEL_FORMAT_BGRX32";
145 
146 			case PIXEL_FORMAT_RGBA32:
147 				return "PIXEL_FORMAT_RGBA32";
148 
149 			case PIXEL_FORMAT_RGBX32:
150 				return "PIXEL_FORMAT_RGBX32";
151 
152 			/* 24bpp formats */
153 			case PIXEL_FORMAT_RGB24:
154 				return "PIXEL_FORMAT_RGB24";
155 
156 			case PIXEL_FORMAT_BGR24:
157 				return "PIXEL_FORMAT_BGR24";
158 
159 			/* 16bpp formats */
160 			case PIXEL_FORMAT_RGB16:
161 				return "PIXEL_FORMAT_RGB16";
162 
163 			case PIXEL_FORMAT_BGR16:
164 				return "PIXEL_FORMAT_BGR16";
165 
166 			case PIXEL_FORMAT_ARGB15:
167 				return "PIXEL_FORMAT_ARGB15";
168 
169 			case PIXEL_FORMAT_RGB15:
170 				return "PIXEL_FORMAT_RGB15";
171 
172 			case PIXEL_FORMAT_ABGR15:
173 				return "PIXEL_FORMAT_ABGR15";
174 
175 			case PIXEL_FORMAT_BGR15:
176 				return "PIXEL_FORMAT_BGR15";
177 
178 			/* 8bpp formats */
179 			case PIXEL_FORMAT_RGB8:
180 				return "PIXEL_FORMAT_RGB8";
181 
182 			/* 4 bpp formats */
183 			case PIXEL_FORMAT_A4:
184 				return "PIXEL_FORMAT_A4";
185 
186 			/* 1bpp formats */
187 			case PIXEL_FORMAT_MONO:
188 				return "PIXEL_FORMAT_MONO";
189 
190 			default:
191 				return "UNKNOWN";
192 		}
193 	}
194 
195 	/***
196 	 *
197 	 * Converts a pixel color in internal representation to its red, green, blue
198 	 * and alpha components.
199 	 *
200 	 * @param color  The color in format internal representation
201 	 * @param format one of PIXEL_FORMAT_* color format defines
202 	 * @param _r      red color value
203 	 * @param _g      green color value
204 	 * @param _b      blue color value
205 	 * @param _a      alpha color value
206 	 * @param palette pallete to use (only used for 8 bit color!)
207 	 */
SplitColor(UINT32 color,UINT32 format,BYTE * _r,BYTE * _g,BYTE * _b,BYTE * _a,const gdiPalette * palette)208 	static INLINE void SplitColor(UINT32 color, UINT32 format, BYTE* _r, BYTE* _g, BYTE* _b,
209 	                              BYTE* _a, const gdiPalette* palette)
210 	{
211 		UINT32 tmp;
212 
213 		switch (format)
214 		{
215 			/* 32bpp formats */
216 			case PIXEL_FORMAT_ARGB32:
217 				if (_a)
218 					*_a = (BYTE)(color >> 24);
219 
220 				if (_r)
221 					*_r = (BYTE)(color >> 16);
222 
223 				if (_g)
224 					*_g = (BYTE)(color >> 8);
225 
226 				if (_b)
227 					*_b = (BYTE)color;
228 
229 				break;
230 
231 			case PIXEL_FORMAT_XRGB32:
232 				if (_r)
233 					*_r = (BYTE)(color >> 16);
234 
235 				if (_g)
236 					*_g = (BYTE)(color >> 8);
237 
238 				if (_b)
239 					*_b = (BYTE)color;
240 
241 				if (_a)
242 					*_a = 0xFF;
243 
244 				break;
245 
246 			case PIXEL_FORMAT_ABGR32:
247 				if (_a)
248 					*_a = (BYTE)(color >> 24);
249 
250 				if (_b)
251 					*_b = (BYTE)(color >> 16);
252 
253 				if (_g)
254 					*_g = (BYTE)(color >> 8);
255 
256 				if (_r)
257 					*_r = (BYTE)color;
258 
259 				break;
260 
261 			case PIXEL_FORMAT_XBGR32:
262 				if (_b)
263 					*_b = (BYTE)(color >> 16);
264 
265 				if (_g)
266 					*_g = (BYTE)(color >> 8);
267 
268 				if (_r)
269 					*_r = (BYTE)color;
270 
271 				if (_a)
272 					*_a = 0xFF;
273 
274 				break;
275 
276 			case PIXEL_FORMAT_RGBA32:
277 				if (_r)
278 					*_r = (BYTE)(color >> 24);
279 
280 				if (_g)
281 					*_g = (BYTE)(color >> 16);
282 
283 				if (_b)
284 					*_b = (BYTE)(color >> 8);
285 
286 				if (_a)
287 					*_a = (BYTE)color;
288 
289 				break;
290 
291 			case PIXEL_FORMAT_RGBX32:
292 				if (_r)
293 					*_r = (BYTE)(color >> 24);
294 
295 				if (_g)
296 					*_g = (BYTE)(color >> 16);
297 
298 				if (_b)
299 					*_b = (BYTE)(color >> 8);
300 
301 				if (_a)
302 					*_a = 0xFF;
303 
304 				break;
305 
306 			case PIXEL_FORMAT_BGRA32:
307 				if (_b)
308 					*_b = (BYTE)(color >> 24);
309 
310 				if (_g)
311 					*_g = (BYTE)(color >> 16);
312 
313 				if (_r)
314 					*_r = (BYTE)(color >> 8);
315 
316 				if (_a)
317 					*_a = (BYTE)color;
318 
319 				break;
320 
321 			case PIXEL_FORMAT_BGRX32:
322 				if (_b)
323 					*_b = (BYTE)(color >> 24);
324 
325 				if (_g)
326 					*_g = (BYTE)(color >> 16);
327 
328 				if (_r)
329 					*_r = (BYTE)(color >> 8);
330 
331 				if (_a)
332 					*_a = 0xFF;
333 
334 				break;
335 
336 			/* 24bpp formats */
337 			case PIXEL_FORMAT_RGB24:
338 				if (_r)
339 					*_r = (BYTE)(color >> 16);
340 
341 				if (_g)
342 					*_g = (BYTE)(color >> 8);
343 
344 				if (_b)
345 					*_b = (BYTE)color;
346 
347 				if (_a)
348 					*_a = 0xFF;
349 
350 				break;
351 
352 			case PIXEL_FORMAT_BGR24:
353 				if (_b)
354 					*_b = (BYTE)(color >> 16);
355 
356 				if (_g)
357 					*_g = (BYTE)(color >> 8);
358 
359 				if (_r)
360 					*_r = (BYTE)color;
361 
362 				if (_a)
363 					*_a = 0xFF;
364 
365 				break;
366 
367 			/* 16bpp formats */
368 			case PIXEL_FORMAT_RGB16:
369 				if (_r)
370 				{
371 					const UINT32 c = (color >> 11) & 0x1F;
372 					const UINT32 val = (c << 3) + c / 4;
373 					*_r = (BYTE)(val > 255 ? 255 : val);
374 				}
375 
376 				if (_g)
377 				{
378 					const UINT32 c = (color >> 5) & 0x3F;
379 					const UINT32 val = (c << 2) + c / 4 / 2;
380 					*_g = (BYTE)(val > 255 ? 255 : val);
381 				}
382 
383 				if (_b)
384 				{
385 					const UINT32 c = (color)&0x1F;
386 					const UINT32 val = (c << 3) + c / 4;
387 					*_b = (BYTE)(val > 255 ? 255 : val);
388 				}
389 
390 				if (_a)
391 					*_a = 0xFF;
392 
393 				break;
394 
395 			case PIXEL_FORMAT_BGR16:
396 				if (_r)
397 				{
398 					const UINT32 c = (color)&0x1F;
399 					const UINT32 val = (c << 3) + c / 4;
400 					*_r = (BYTE)(val > 255 ? 255 : val);
401 				}
402 
403 				if (_g)
404 				{
405 					const UINT32 c = (color >> 5) & 0x3F;
406 					const UINT32 val = (c << 2) + c / 4 / 2;
407 					*_g = (BYTE)(val > 255 ? 255 : val);
408 				}
409 
410 				if (_b)
411 				{
412 					const UINT32 c = (color >> 11) & 0x1F;
413 					const UINT32 val = (c << 3) + c / 4;
414 					*_b = (BYTE)(val > 255 ? 255 : val);
415 				}
416 
417 				if (_a)
418 					*_a = 0xFF;
419 
420 				break;
421 
422 			case PIXEL_FORMAT_ARGB15:
423 				if (_r)
424 				{
425 					const UINT32 c = (color >> 10) & 0x1F;
426 					const UINT32 val = (c << 3) + c / 4;
427 					*_r = (BYTE)(val > 255 ? 255 : val);
428 				}
429 
430 				if (_g)
431 				{
432 					const UINT32 c = (color >> 5) & 0x1F;
433 					const UINT32 val = (c << 3) + c / 4;
434 					*_g = (BYTE)(val > 255 ? 255 : val);
435 				}
436 
437 				if (_b)
438 				{
439 					const UINT32 c = (color)&0x1F;
440 					const UINT32 val = (c << 3) + c / 4;
441 					*_b = (BYTE)(val > 255 ? 255 : val);
442 				}
443 
444 				if (_a)
445 					*_a = color & 0x8000 ? 0xFF : 0x00;
446 
447 				break;
448 
449 			case PIXEL_FORMAT_ABGR15:
450 				if (_r)
451 				{
452 					const UINT32 c = (color)&0x1F;
453 					const UINT32 val = (c << 3) + c / 4;
454 					*_r = (BYTE)(val > 255 ? 255 : val);
455 				}
456 
457 				if (_g)
458 				{
459 					const UINT32 c = (color >> 5) & 0x1F;
460 					const UINT32 val = (c << 3) + c / 4;
461 					*_g = (BYTE)(val > 255 ? 255 : val);
462 				}
463 
464 				if (_b)
465 				{
466 					const UINT32 c = (color >> 10) & 0x1F;
467 					const UINT32 val = (c << 3) + c / 4;
468 					*_b = (BYTE)(val > 255 ? 255 : val);
469 				}
470 
471 				if (_a)
472 					*_a = color & 0x8000 ? 0xFF : 0x00;
473 
474 				break;
475 
476 			/* 15bpp formats */
477 			case PIXEL_FORMAT_RGB15:
478 				if (_r)
479 				{
480 					const UINT32 c = (color >> 10) & 0x1F;
481 					const UINT32 val = (c << 3) + c / 4;
482 					*_r = (BYTE)(val > 255 ? 255 : val);
483 				}
484 
485 				if (_g)
486 				{
487 					const UINT32 c = (color >> 5) & 0x1F;
488 					const UINT32 val = (c << 3) + c / 4;
489 					*_g = (BYTE)(val > 255 ? 255 : val);
490 				}
491 
492 				if (_b)
493 				{
494 					const UINT32 c = (color)&0x1F;
495 					const UINT32 val = (c << 3) + c / 4;
496 					*_b = (BYTE)(val > 255 ? 255 : val);
497 				}
498 
499 				if (_a)
500 					*_a = 0xFF;
501 
502 				break;
503 
504 			case PIXEL_FORMAT_BGR15:
505 				if (_r)
506 				{
507 					const UINT32 c = (color)&0x1F;
508 					const UINT32 val = (c << 3) + c / 4;
509 					*_r = (BYTE)(val > 255 ? 255 : val);
510 				}
511 
512 				if (_g)
513 				{
514 					const UINT32 c = (color >> 5) & 0x1F;
515 					const UINT32 val = (c << 3) + c / 4;
516 					*_g = (BYTE)(val > 255 ? 255 : val);
517 				}
518 
519 				if (_b)
520 				{
521 					const UINT32 c = (color >> 10) & 0x1F;
522 					const UINT32 val = (c << 3) + c / 4;
523 					*_b = (BYTE)(val > 255 ? 255 : val);
524 				}
525 
526 				if (_a)
527 					*_a = 0xFF;
528 
529 				break;
530 
531 			/* 8bpp formats */
532 			case PIXEL_FORMAT_RGB8:
533 				if (color <= 0xFF)
534 				{
535 					tmp = palette->palette[color];
536 					SplitColor(tmp, palette->format, _r, _g, _b, _a, NULL);
537 				}
538 				else
539 				{
540 					if (_r)
541 						*_r = 0x00;
542 
543 					if (_g)
544 						*_g = 0x00;
545 
546 					if (_b)
547 						*_b = 0x00;
548 
549 					if (_a)
550 						*_a = 0x00;
551 				}
552 
553 				break;
554 
555 			/* 1bpp formats */
556 			case PIXEL_FORMAT_MONO:
557 				if (_r)
558 					*_r = (color) ? 0xFF : 0x00;
559 
560 				if (_g)
561 					*_g = (color) ? 0xFF : 0x00;
562 
563 				if (_b)
564 					*_b = (color) ? 0xFF : 0x00;
565 
566 				if (_a)
567 					*_a = (color) ? 0xFF : 0x00;
568 
569 				break;
570 
571 			/* 4 bpp formats */
572 			case PIXEL_FORMAT_A4:
573 			default:
574 				if (_r)
575 					*_r = 0x00;
576 
577 				if (_g)
578 					*_g = 0x00;
579 
580 				if (_b)
581 					*_b = 0x00;
582 
583 				if (_a)
584 					*_a = 0x00;
585 
586 				WLog_ERR(CTAG, "Unsupported format %s", FreeRDPGetColorFormatName(format));
587 				break;
588 		}
589 	}
590 
591 	/***
592 	 *
593 	 * Converts red, green, blue and alpha values to internal representation.
594 	 *
595 	 * @param format one of PIXEL_FORMAT_* color format defines
596 	 * @param r      red color value
597 	 * @param g      green color value
598 	 * @param b      blue color value
599 	 * @param a      alpha color value
600 	 *
601 	 * @return       The pixel color in the desired format. Value is in internal
602 	 *               representation.
603 	 */
FreeRDPGetColor(UINT32 format,BYTE r,BYTE g,BYTE b,BYTE a)604 	static INLINE UINT32 FreeRDPGetColor(UINT32 format, BYTE r, BYTE g, BYTE b, BYTE a)
605 	{
606 		UINT32 _r = r;
607 		UINT32 _g = g;
608 		UINT32 _b = b;
609 		UINT32 _a = a;
610 
611 		switch (format)
612 		{
613 			/* 32bpp formats */
614 			case PIXEL_FORMAT_ARGB32:
615 				return (_a << 24) | (_r << 16) | (_g << 8) | _b;
616 
617 			case PIXEL_FORMAT_XRGB32:
618 				return (_r << 16) | (_g << 8) | _b;
619 
620 			case PIXEL_FORMAT_ABGR32:
621 				return (_a << 24) | (_b << 16) | (_g << 8) | _r;
622 
623 			case PIXEL_FORMAT_XBGR32:
624 				return (_b << 16) | (_g << 8) | _r;
625 
626 			case PIXEL_FORMAT_RGBA32:
627 				return (_r << 24) | (_g << 16) | (_b << 8) | _a;
628 
629 			case PIXEL_FORMAT_RGBX32:
630 				return (_r << 24) | (_g << 16) | (_b << 8) | _a;
631 
632 			case PIXEL_FORMAT_BGRA32:
633 				return (_b << 24) | (_g << 16) | (_r << 8) | _a;
634 
635 			case PIXEL_FORMAT_BGRX32:
636 				return (_b << 24) | (_g << 16) | (_r << 8) | _a;
637 
638 			/* 24bpp formats */
639 			case PIXEL_FORMAT_RGB24:
640 				return (_r << 16) | (_g << 8) | _b;
641 
642 			case PIXEL_FORMAT_BGR24:
643 				return (_b << 16) | (_g << 8) | _r;
644 
645 			/* 16bpp formats */
646 			case PIXEL_FORMAT_RGB16:
647 				return (((_r >> 3) & 0x1F) << 11) | (((_g >> 2) & 0x3F) << 5) | ((_b >> 3) & 0x1F);
648 
649 			case PIXEL_FORMAT_BGR16:
650 				return (((_b >> 3) & 0x1F) << 11) | (((_g >> 2) & 0x3F) << 5) | ((_r >> 3) & 0x1F);
651 
652 			case PIXEL_FORMAT_ARGB15:
653 				return (((_r >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_b >> 3) & 0x1F) |
654 				       (_a ? 0x8000 : 0x0000);
655 
656 			case PIXEL_FORMAT_ABGR15:
657 				return (((_b >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_r >> 3) & 0x1F) |
658 				       (_a ? 0x8000 : 0x0000);
659 
660 			/* 15bpp formats */
661 			case PIXEL_FORMAT_RGB15:
662 				return (((_r >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_b >> 3) & 0x1F);
663 
664 			case PIXEL_FORMAT_BGR15:
665 				return (((_b >> 3) & 0x1F) << 10) | (((_g >> 3) & 0x1F) << 5) | ((_r >> 3) & 0x1F);
666 
667 			/* 8bpp formats */
668 			case PIXEL_FORMAT_RGB8:
669 
670 			/* 4 bpp formats */
671 			case PIXEL_FORMAT_A4:
672 
673 			/* 1bpp formats */
674 			case PIXEL_FORMAT_MONO:
675 			default:
676 				WLog_ERR(CTAG, "Unsupported format %s", FreeRDPGetColorFormatName(format));
677 				return 0;
678 		}
679 	}
680 
681 	/***
682 	 *
683 	 * Returns the number of bits the format format uses.
684 	 *
685 	 * @param format One of PIXEL_FORMAT_* defines
686 	 *
687 	 * @return The number of bits the format requires per pixel.
688 	 */
GetBitsPerPixel(UINT32 format)689 	static INLINE UINT32 GetBitsPerPixel(UINT32 format)
690 	{
691 		return (((format) >> 24) & 0x3F);
692 	}
693 
694 	/***
695 	 * @param format one of PIXEL_FORMAT_* color format defines
696 	 *
697 	 * @return TRUE if the format has an alpha channel, FALSE otherwise.
698 	 */
ColorHasAlpha(UINT32 format)699 	static INLINE BOOL ColorHasAlpha(UINT32 format)
700 	{
701 		UINT32 alpha = (((format) >> 12) & 0x0F);
702 
703 		if (alpha == 0)
704 			return FALSE;
705 
706 		return TRUE;
707 	}
708 
709 	/***
710 	 *
711 	 * Read a pixel from memory to internal representation
712 	 *
713 	 * @param src    The source buffer
714 	 * @param format The PIXEL_FORMAT_* define the source buffer uses for encoding
715 	 *
716 	 * @return The pixel color in internal representation
717 	 */
ReadColor(const BYTE * src,UINT32 format)718 	static INLINE UINT32 ReadColor(const BYTE* src, UINT32 format)
719 	{
720 		UINT32 color;
721 
722 		switch (GetBitsPerPixel(format))
723 		{
724 			case 32:
725 				color = ((UINT32)src[0] << 24) | ((UINT32)src[1] << 16) | ((UINT32)src[2] << 8) |
726 				        src[3];
727 				break;
728 
729 			case 24:
730 				color = ((UINT32)src[0] << 16) | ((UINT32)src[1] << 8) | src[2];
731 				break;
732 
733 			case 16:
734 				color = ((UINT32)src[1] << 8) | src[0];
735 				break;
736 
737 			case 15:
738 				color = ((UINT32)src[1] << 8) | src[0];
739 
740 				if (!ColorHasAlpha(format))
741 					color = color & 0x7FFF;
742 
743 				break;
744 
745 			case 8:
746 			case 4:
747 			case 1:
748 				color = *src;
749 				break;
750 
751 			default:
752 				WLog_ERR(CTAG, "Unsupported format %s", FreeRDPGetColorFormatName(format));
753 				color = 0;
754 				break;
755 		}
756 
757 		return color;
758 	}
759 
760 	/***
761 	 *
762 	 * Write a pixel from internal representation to memory
763 	 *
764 	 * @param dst    The destination buffer
765 	 * @param format The PIXEL_FORMAT_* define for encoding
766 	 * @param color  The pixel color in internal representation
767 	 *
768 	 * @return TRUE if successful, FALSE otherwise
769 	 */
WriteColor(BYTE * dst,UINT32 format,UINT32 color)770 	static INLINE BOOL WriteColor(BYTE* dst, UINT32 format, UINT32 color)
771 	{
772 		switch (GetBitsPerPixel(format))
773 		{
774 			case 32:
775 				dst[0] = (BYTE)(color >> 24);
776 				dst[1] = (BYTE)(color >> 16);
777 				dst[2] = (BYTE)(color >> 8);
778 				dst[3] = (BYTE)color;
779 				break;
780 
781 			case 24:
782 				dst[0] = (BYTE)(color >> 16);
783 				dst[1] = (BYTE)(color >> 8);
784 				dst[2] = (BYTE)color;
785 				break;
786 
787 			case 16:
788 				dst[1] = (BYTE)(color >> 8);
789 				dst[0] = (BYTE)color;
790 				break;
791 
792 			case 15:
793 				if (!ColorHasAlpha(format))
794 					color = color & 0x7FFF;
795 
796 				dst[1] = (BYTE)(color >> 8);
797 				dst[0] = (BYTE)color;
798 				break;
799 
800 			case 8:
801 				dst[0] = (BYTE)color;
802 				break;
803 
804 			default:
805 				WLog_ERR(CTAG, "Unsupported format %s", FreeRDPGetColorFormatName(format));
806 				return FALSE;
807 		}
808 
809 		return TRUE;
810 	}
811 
WriteColorIgnoreAlpha(BYTE * dst,UINT32 format,UINT32 color)812 	static INLINE BOOL WriteColorIgnoreAlpha(BYTE* dst, UINT32 format, UINT32 color)
813 	{
814 		switch (format)
815 		{
816 			case PIXEL_FORMAT_ABGR32:
817 			case PIXEL_FORMAT_ARGB32:
818 			{
819 				const UINT32 tmp = (dst[0] << 24) | (color & 0x00FFFFFF);
820 				return WriteColor(dst, format, tmp);
821 			}
822 			case PIXEL_FORMAT_BGRA32:
823 			case PIXEL_FORMAT_RGBA32:
824 			{
825 				const UINT32 tmp = (dst[3]) | (color & 0xFFFFFF00);
826 				return WriteColor(dst, format, tmp);
827 			}
828 			default:
829 				return WriteColor(dst, format, color);
830 		}
831 	}
832 
833 	/***
834 	 *
835 	 * Converts a pixel in internal representation format srcFormat to internal
836 	 * representation format dstFormat
837 	 *
838 	 * @param color      The pixel color in srcFormat representation
839 	 * @param srcFormat  The PIXEL_FORMAT_* of color
840 	 * @param dstFormat  The PIXEL_FORMAT_* of the return.
841 	 * @param palette    pallete to use (only used for 8 bit color!)
842 	 *
843 	 * @return           The converted pixel color in dstFormat representation
844 	 */
FreeRDPConvertColor(UINT32 color,UINT32 srcFormat,UINT32 dstFormat,const gdiPalette * palette)845 	static INLINE UINT32 FreeRDPConvertColor(UINT32 color, UINT32 srcFormat, UINT32 dstFormat,
846 	                                         const gdiPalette* palette)
847 	{
848 		BYTE r = 0;
849 		BYTE g = 0;
850 		BYTE b = 0;
851 		BYTE a = 0;
852 		SplitColor(color, srcFormat, &r, &g, &b, &a, palette);
853 		return FreeRDPGetColor(dstFormat, r, g, b, a);
854 	}
855 
856 	/***
857 	 *
858 	 * Returns the number of bytes the format format uses.
859 	 *
860 	 * @param format One of PIXEL_FORMAT_* defines
861 	 *
862 	 * @return The number of bytes the format requires per pixel.
863 	 */
GetBytesPerPixel(UINT32 format)864 	static INLINE UINT32 GetBytesPerPixel(UINT32 format)
865 	{
866 		return (GetBitsPerPixel(format) + 7) / 8;
867 	}
868 
869 	/***
870 	 *
871 	 * @param nWidth    width to copy in pixels
872 	 * @param nHeight   height to copy in pixels
873 	 * @param data      source buffer, must be (nWidth + 7) / 8 bytes long
874 	 *
875 	 * @return          A buffer allocated with _aligned_malloc(width * height, 16)
876 	 *                  if successufl, NULL otherwise.
877 	 */
878 	FREERDP_API BYTE* freerdp_glyph_convert(UINT32 width, UINT32 height, const BYTE* data);
879 
880 	/***
881 	 *
882 	 * @param pDstData  destination buffer
883 	 * @param DstFormat destination buffer format
884 	 * @param nDstStep  destination buffer stride (line in bytes) 0 for default
885 	 * @param nXDst     destination buffer offset x
886 	 * @param nYDst     destination buffer offset y
887 	 * @param nWidth    width to copy in pixels
888 	 * @param nHeight   height to copy in pixels
889 	 * @param pSrcData  source buffer, must be (nWidth + 7) / 8 bytes long
890 	 * @param backColor The background color in internal representation format
891 	 * @param foreColor The foreground color in internal representation format
892 	 * @param palette   palette to use (only used for 8 bit color!)
893 	 *
894 	 * @return          TRUE if success, FALSE otherwise
895 	 */
896 	FREERDP_API BOOL freerdp_image_copy_from_monochrome(BYTE* pDstData, UINT32 DstFormat,
897 	                                                    UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
898 	                                                    UINT32 nWidth, UINT32 nHeight,
899 	                                                    const BYTE* pSrcData, UINT32 backColor,
900 	                                                    UINT32 foreColor,
901 	                                                    const gdiPalette* palette);
902 
903 	/***
904 	 *
905 	 * @param pDstData      destination buffer
906 	 * @param DstFormat     destination buffer format
907 	 * @param nDstStep      destination buffer stride (line in bytes) 0 for default
908 	 * @param nXDst         destination buffer offset x
909 	 * @param nYDst         destination buffer offset y
910 	 * @param nWidth        width to copy in pixels
911 	 * @param nHeight       height to copy in pixels
912 	 * @param bitsColor     icon's image data buffer
913 	 * @param cbBitsColor   length of the image data buffer in bytes
914 	 * @param bitsMask      icon's 1bpp image mask buffer
915 	 * @param cbBitsMask    length of the image mask buffer in bytes
916 	 * @param colorTable    icon's image color table
917 	 * @param cbBitsColor   length of the image color table buffer in bytes
918 	 * @param bpp           color image data bits per pixel
919 	 *
920 	 * @return              TRUE if success, FALSE otherwise
921 	 */
922 	FREERDP_API BOOL freerdp_image_copy_from_icon_data(BYTE* pDstData, UINT32 DstFormat,
923 	                                                   UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
924 	                                                   UINT16 nWidth, UINT16 nHeight,
925 	                                                   const BYTE* bitsColor, UINT16 cbBitsColor,
926 	                                                   const BYTE* bitsMask, UINT16 cbBitsMask,
927 	                                                   const BYTE* colorTable, UINT16 cbColorTable,
928 	                                                   UINT32 bpp);
929 
930 	/***
931 	 *
932 	 * @param pDstData      destination buffer
933 	 * @param DstFormat     destination buffer format
934 	 * @param nDstStep      destination buffer stride (line in bytes) 0 for default
935 	 * @param nXDst         destination buffer offset x
936 	 * @param nYDst         destination buffer offset y
937 	 * @param nWidth        width to copy in pixels
938 	 * @param nHeight       height to copy in pixels
939 	 * @param xorMask       XOR mask buffer
940 	 * @param xorMaskLength XOR mask length in bytes
941 	 * @param andMask       AND mask buffer
942 	 * @param andMaskLength AND mask length in bytes
943 	 * @param xorBpp        XOR bits per pixel
944 	 * @param palette       palette to use (only used for 8 bit color!)
945 	 *
946 	 * @return              TRUE if success, FALSE otherwise
947 	 */
948 	FREERDP_API BOOL freerdp_image_copy_from_pointer_data(
949 	    BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
950 	    UINT32 nWidth, UINT32 nHeight, const BYTE* xorMask, UINT32 xorMaskLength,
951 	    const BYTE* andMask, UINT32 andMaskLength, UINT32 xorBpp, const gdiPalette* palette);
952 
953 	/***
954 	 *
955 	 * @param pDstData  destination buffer
956 	 * @param DstFormat destination buffer format
957 	 * @param nDstStep  destination buffer stride (line in bytes) 0 for default
958 	 * @param nXDst     destination buffer offset x
959 	 * @param nYDst     destination buffer offset y
960 	 * @param nWidth    width to copy in pixels
961 	 * @param nHeight   height to copy in pixels
962 	 * @param pSrcData  source buffer
963 	 * @param SrcFormat source buffer format
964 	 * @param nSrcStep  source buffer stride (line in bytes) 0 for default
965 	 * @param nXSrc     source buffer x offset in pixels
966 	 * @param nYSrc     source buffer y offset in pixels
967 	 * @param palette   palette to use (only used for 8 bit color!)
968 	 * @param flags     Image flipping flags FREERDP_FLIP_NONE et al
969 	 *
970 	 * @return          TRUE if success, FALSE otherwise
971 	 */
972 	FREERDP_API BOOL freerdp_image_copy(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep,
973 	                                    UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
974 	                                    const BYTE* pSrcData, DWORD SrcFormat, UINT32 nSrcStep,
975 	                                    UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette,
976 	                                    UINT32 flags);
977 
978 	/***
979 	 *
980 	 * @param pDstData   destination buffer
981 	 * @param DstFormat  destination buffer format
982 	 * @param nDstStep   destination buffer stride (line in bytes) 0 for default
983 	 * @param nXDst      destination buffer offset x
984 	 * @param nYDst      destination buffer offset y
985 	 * @param nDstWidth  width of destination in pixels
986 	 * @param nDstHeight height of destination in pixels
987 	 * @param pSrcData   source buffer
988 	 * @param SrcFormat  source buffer format
989 	 * @param nSrcStep   source buffer stride (line in bytes) 0 for default
990 	 * @param nXSrc      source buffer x offset in pixels
991 	 * @param nYSrc      source buffer y offset in pixels
992 	 * @param nSrcWidth  width of source in pixels
993 	 * @param nSrcHeight height of source in pixels
994 	 *
995 	 * @return          TRUE if success, FALSE otherwise
996 	 */
997 	FREERDP_API BOOL freerdp_image_scale(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep,
998 	                                     UINT32 nXDst, UINT32 nYDst, UINT32 nDstWidth,
999 	                                     UINT32 nDstHeight, const BYTE* pSrcData, DWORD SrcFormat,
1000 	                                     UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
1001 	                                     UINT32 nSrcWidth, UINT32 nSrcHeight);
1002 
1003 	/***
1004 	 *
1005 	 * @param pDstData  destionation buffer
1006 	 * @param DstFormat destionation buffer format
1007 	 * @param nDstStep  destionation buffer stride (line in bytes) 0 for default
1008 	 * @param nXDst     destination buffer offset x
1009 	 * @param nYDst     destination buffer offset y
1010 	 * @param nWidth    width to copy in pixels
1011 	 * @param nHeight   height to copy in pixels
1012 	 * @param color     Pixel color in DstFormat (internal representation format,
1013 	 *                  use FreeRDPGetColor to create)
1014 	 *
1015 	 * @return          TRUE if success, FALSE otherwise
1016 	 */
1017 	FREERDP_API BOOL freerdp_image_fill(BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep,
1018 	                                    UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
1019 	                                    UINT32 color);
1020 
1021 #if !defined(__APPLE__)
1022 #define GetColorFormatName FreeRDPGetColorFormatName
1023 #define GetColor FreeRDPGetColor
1024 #define ConvertColor FreeRDPConvertColor
1025 #endif
1026 
1027 #ifdef __cplusplus
1028 }
1029 #endif
1030 
1031 #endif /* FREERDP_CODEC_COLOR_H */
1032