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 */