cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

color.h (28400B)


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