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