1 //---------------------------------------------------------------------------- 2 // Anti-Grain Geometry - Version 2.4 3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) 4 // 5 // Permission to copy, use, modify, sell and distribute this software 6 // is granted provided this copyright notice appears in all copies. 7 // This software is provided "as is" without express or implied 8 // warranty, and with no claim as to its suitability for any purpose. 9 // 10 //---------------------------------------------------------------------------- 11 // Contact: mcseem@antigrain.com 12 // mcseemagg@yahoo.com 13 // http://www.antigrain.com 14 //---------------------------------------------------------------------------- 15 // 16 // Adaptation for high precision colors has been sponsored by 17 // Liberty Technology Systems, Inc., visit http://lib-sys.com 18 // 19 // Liberty Technology Systems, Inc. is the provider of 20 // PostScript and PDF technology for software developers. 21 // 22 //---------------------------------------------------------------------------- 23 // 24 // color types gray8, gray16 25 // 26 //---------------------------------------------------------------------------- 27 28 #ifndef AGG_COLOR_GRAY_INCLUDED 29 #define AGG_COLOR_GRAY_INCLUDED 30 31 #include "agg_basics.h" 32 #include "agg_color_rgba.h" 33 34 namespace agg 35 { 36 37 //===================================================================gray8 38 template<class Colorspace> 39 struct gray8T 40 { 41 typedef int8u value_type; 42 typedef int32u calc_type; 43 typedef int32 long_type; 44 enum base_scale_e 45 { 46 base_shift = 8, 47 base_scale = 1 << base_shift, 48 base_mask = base_scale - 1, 49 base_MSB = 1 << (base_shift - 1) 50 }; 51 typedef gray8T self_type; 52 53 value_type v; 54 value_type a; 55 luminancegray8T56 static value_type luminance(const rgba& c) 57 { 58 // Calculate grayscale value as per ITU-R BT.709. 59 return value_type(uround((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * base_mask)); 60 } 61 luminancegray8T62 static value_type luminance(const rgba8& c) 63 { 64 // Calculate grayscale value as per ITU-R BT.709. 65 return value_type((55u * c.r + 184u * c.g + 18u * c.b) >> 8); 66 } 67 convertgray8T68 static void convert(gray8T<linear>& dst, const gray8T<sRGB>& src) 69 { 70 dst.v = sRGB_conv<value_type>::rgb_from_sRGB(src.v); 71 dst.a = src.a; 72 } 73 convertgray8T74 static void convert(gray8T<sRGB>& dst, const gray8T<linear>& src) 75 { 76 dst.v = sRGB_conv<value_type>::rgb_to_sRGB(src.v); 77 dst.a = src.a; 78 } 79 convertgray8T80 static void convert(gray8T<linear>& dst, const rgba8& src) 81 { 82 dst.v = luminance(src); 83 dst.a = src.a; 84 } 85 convertgray8T86 static void convert(gray8T<linear>& dst, const srgba8& src) 87 { 88 // The RGB weights are only valid for linear values. 89 convert(dst, rgba8(src)); 90 } 91 convertgray8T92 static void convert(gray8T<sRGB>& dst, const rgba8& src) 93 { 94 dst.v = sRGB_conv<value_type>::rgb_to_sRGB(luminance(src)); 95 dst.a = src.a; 96 } 97 convertgray8T98 static void convert(gray8T<sRGB>& dst, const srgba8& src) 99 { 100 // The RGB weights are only valid for linear values. 101 convert(dst, rgba8(src)); 102 } 103 104 //-------------------------------------------------------------------- gray8Tgray8T105 gray8T() {} 106 107 //-------------------------------------------------------------------- 108 explicit gray8T(unsigned v_, unsigned a_ = base_mask) : vgray8T109 v(int8u(v_)), a(int8u(a_)) {} 110 111 //-------------------------------------------------------------------- gray8Tgray8T112 gray8T(const self_type& c, unsigned a_) : 113 v(c.v), a(value_type(a_)) {} 114 115 //-------------------------------------------------------------------- gray8Tgray8T116 gray8T(const rgba& c) : 117 v(luminance(c)), 118 a(value_type(uround(c.a * base_mask))) {} 119 120 //-------------------------------------------------------------------- 121 template<class T> gray8Tgray8T122 gray8T(const gray8T<T>& c) 123 { 124 convert(*this, c); 125 } 126 127 //-------------------------------------------------------------------- 128 template<class T> gray8Tgray8T129 gray8T(const rgba8T<T>& c) 130 { 131 convert(*this, c); 132 } 133 134 //-------------------------------------------------------------------- 135 template<class T> convert_from_sRGBgray8T136 T convert_from_sRGB() const 137 { 138 typename T::value_type y = sRGB_conv<typename T::value_type>::rgb_from_sRGB(v); 139 return T(y, y, y, sRGB_conv<typename T::value_type>::alpha_from_sRGB(a)); 140 } 141 142 template<class T> convert_to_sRGBgray8T143 T convert_to_sRGB() const 144 { 145 typename T::value_type y = sRGB_conv<typename T::value_type>::rgb_to_sRGB(v); 146 return T(y, y, y, sRGB_conv<typename T::value_type>::alpha_to_sRGB(a)); 147 } 148 149 //-------------------------------------------------------------------- make_rgba8gray8T150 rgba8 make_rgba8(const linear&) const 151 { 152 return rgba8(v, v, v, a); 153 } 154 make_rgba8gray8T155 rgba8 make_rgba8(const sRGB&) const 156 { 157 return convert_from_sRGB<srgba8>(); 158 } 159 rgba8gray8T160 operator rgba8() const 161 { 162 return make_rgba8(Colorspace()); 163 } 164 165 //-------------------------------------------------------------------- make_srgba8gray8T166 srgba8 make_srgba8(const linear&) const 167 { 168 return convert_to_sRGB<rgba8>(); 169 } 170 make_srgba8gray8T171 srgba8 make_srgba8(const sRGB&) const 172 { 173 return srgba8(v, v, v, a); 174 } 175 srgba8gray8T176 operator srgba8() const 177 { 178 return make_rgba8(Colorspace()); 179 } 180 181 //-------------------------------------------------------------------- make_rgba16gray8T182 rgba16 make_rgba16(const linear&) const 183 { 184 rgba16::value_type rgb = (v << 8) | v; 185 return rgba16(rgb, rgb, rgb, (a << 8) | a); 186 } 187 make_rgba16gray8T188 rgba16 make_rgba16(const sRGB&) const 189 { 190 return convert_from_sRGB<rgba16>(); 191 } 192 rgba16gray8T193 operator rgba16() const 194 { 195 return make_rgba16(Colorspace()); 196 } 197 198 //-------------------------------------------------------------------- make_rgba32gray8T199 rgba32 make_rgba32(const linear&) const 200 { 201 rgba32::value_type v32 = v / 255.0f; 202 return rgba32(v32, v32, v32, a / 255.0f); 203 } 204 make_rgba32gray8T205 rgba32 make_rgba32(const sRGB&) const 206 { 207 return convert_from_sRGB<rgba32>(); 208 } 209 rgba32gray8T210 operator rgba32() const 211 { 212 return make_rgba32(Colorspace()); 213 } 214 215 //-------------------------------------------------------------------- to_doublegray8T216 static AGG_INLINE double to_double(value_type a) 217 { 218 return double(a) / base_mask; 219 } 220 221 //-------------------------------------------------------------------- from_doublegray8T222 static AGG_INLINE value_type from_double(double a) 223 { 224 return value_type(uround(a * base_mask)); 225 } 226 227 //-------------------------------------------------------------------- empty_valuegray8T228 static AGG_INLINE value_type empty_value() 229 { 230 return 0; 231 } 232 233 //-------------------------------------------------------------------- full_valuegray8T234 static AGG_INLINE value_type full_value() 235 { 236 return base_mask; 237 } 238 239 //-------------------------------------------------------------------- is_transparentgray8T240 AGG_INLINE bool is_transparent() const 241 { 242 return a == 0; 243 } 244 245 //-------------------------------------------------------------------- is_opaquegray8T246 AGG_INLINE bool is_opaque() const 247 { 248 return a == base_mask; 249 } 250 251 //-------------------------------------------------------------------- 252 // Fixed-point multiply, exact over int8u. multiplygray8T253 static AGG_INLINE value_type multiply(value_type a, value_type b) 254 { 255 calc_type t = a * b + base_MSB; 256 return value_type(((t >> base_shift) + t) >> base_shift); 257 } 258 259 //-------------------------------------------------------------------- demultiplygray8T260 static AGG_INLINE value_type demultiply(value_type a, value_type b) 261 { 262 if (a * b == 0) 263 { 264 return 0; 265 } 266 else if (a >= b) 267 { 268 return base_mask; 269 } 270 else return value_type((a * base_mask + (b >> 1)) / b); 271 } 272 273 //-------------------------------------------------------------------- 274 template<typename T> downscalegray8T275 static AGG_INLINE T downscale(T a) 276 { 277 return a >> base_shift; 278 } 279 280 //-------------------------------------------------------------------- 281 template<typename T> downshiftgray8T282 static AGG_INLINE T downshift(T a, unsigned n) 283 { 284 return a >> n; 285 } 286 287 //-------------------------------------------------------------------- 288 // Fixed-point multiply, exact over int8u. 289 // Specifically for multiplying a color component by a cover. mult_covergray8T290 static AGG_INLINE value_type mult_cover(value_type a, value_type b) 291 { 292 return multiply(a, b); 293 } 294 295 //-------------------------------------------------------------------- scale_covergray8T296 static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) 297 { 298 return multiply(b, a); 299 } 300 301 //-------------------------------------------------------------------- 302 // Interpolate p to q by a, assuming q is premultiplied by a. prelerpgray8T303 static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) 304 { 305 return p + q - multiply(p, a); 306 } 307 308 //-------------------------------------------------------------------- 309 // Interpolate p to q by a. lerpgray8T310 static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a) 311 { 312 int t = (q - p) * a + base_MSB - (p > q); 313 return value_type(p + (((t >> base_shift) + t) >> base_shift)); 314 } 315 316 //-------------------------------------------------------------------- cleargray8T317 self_type& clear() 318 { 319 v = a = 0; 320 return *this; 321 } 322 323 //-------------------------------------------------------------------- transparentgray8T324 self_type& transparent() 325 { 326 a = 0; 327 return *this; 328 } 329 330 //-------------------------------------------------------------------- opacitygray8T331 self_type& opacity(double a_) 332 { 333 if (a_ < 0) a = 0; 334 else if (a_ > 1) a = 1; 335 else a = (value_type)uround(a_ * double(base_mask)); 336 return *this; 337 } 338 339 //-------------------------------------------------------------------- opacitygray8T340 double opacity() const 341 { 342 return double(a) / double(base_mask); 343 } 344 345 //-------------------------------------------------------------------- premultiplygray8T346 self_type& premultiply() 347 { 348 if (a < base_mask) 349 { 350 if (a == 0) v = 0; 351 else v = multiply(v, a); 352 } 353 return *this; 354 } 355 356 //-------------------------------------------------------------------- demultiplygray8T357 self_type& demultiply() 358 { 359 if (a < base_mask) 360 { 361 if (a == 0) 362 { 363 v = 0; 364 } 365 else 366 { 367 calc_type v_ = (calc_type(v) * base_mask) / a; 368 v = value_type((v_ > base_mask) ? (value_type)base_mask : v_); 369 } 370 } 371 return *this; 372 } 373 374 //-------------------------------------------------------------------- gradientgray8T375 self_type gradient(self_type c, double k) const 376 { 377 self_type ret; 378 calc_type ik = uround(k * base_scale); 379 ret.v = lerp(v, c.v, ik); 380 ret.a = lerp(a, c.a, ik); 381 return ret; 382 } 383 384 //-------------------------------------------------------------------- addgray8T385 AGG_INLINE void add(const self_type& c, unsigned cover) 386 { 387 calc_type cv, ca; 388 if (cover == cover_mask) 389 { 390 if (c.a == base_mask) 391 { 392 *this = c; 393 return; 394 } 395 else 396 { 397 cv = v + c.v; 398 ca = a + c.a; 399 } 400 } 401 else 402 { 403 cv = v + mult_cover(c.v, cover); 404 ca = a + mult_cover(c.a, cover); 405 } 406 v = (value_type)((cv > calc_type(base_mask)) ? calc_type(base_mask) : cv); 407 a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca); 408 } 409 410 //-------------------------------------------------------------------- no_colorgray8T411 static self_type no_color() { return self_type(0,0); } 412 }; 413 414 typedef gray8T<linear> gray8; 415 typedef gray8T<sRGB> sgray8; 416 417 418 //==================================================================gray16 419 struct gray16 420 { 421 typedef int16u value_type; 422 typedef int32u calc_type; 423 typedef int64 long_type; 424 enum base_scale_e 425 { 426 base_shift = 16, 427 base_scale = 1 << base_shift, 428 base_mask = base_scale - 1, 429 base_MSB = 1 << (base_shift - 1) 430 }; 431 typedef gray16 self_type; 432 433 value_type v; 434 value_type a; 435 luminancegray16436 static value_type luminance(const rgba& c) 437 { 438 // Calculate grayscale value as per ITU-R BT.709. 439 return value_type(uround((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * base_mask)); 440 } 441 luminancegray16442 static value_type luminance(const rgba16& c) 443 { 444 // Calculate grayscale value as per ITU-R BT.709. 445 return value_type((13933u * c.r + 46872u * c.g + 4732u * c.b) >> 16); 446 } 447 luminancegray16448 static value_type luminance(const rgba8& c) 449 { 450 return luminance(rgba16(c)); 451 } 452 luminancegray16453 static value_type luminance(const srgba8& c) 454 { 455 return luminance(rgba16(c)); 456 } 457 luminancegray16458 static value_type luminance(const rgba32& c) 459 { 460 return luminance(rgba(c)); 461 } 462 463 //-------------------------------------------------------------------- gray16gray16464 gray16() {} 465 466 //-------------------------------------------------------------------- 467 explicit gray16(unsigned v_, unsigned a_ = base_mask) : vgray16468 v(int16u(v_)), a(int16u(a_)) {} 469 470 //-------------------------------------------------------------------- gray16gray16471 gray16(const self_type& c, unsigned a_) : 472 v(c.v), a(value_type(a_)) {} 473 474 //-------------------------------------------------------------------- gray16gray16475 gray16(const rgba& c) : 476 v(luminance(c)), 477 a((value_type)uround(c.a * double(base_mask))) {} 478 479 //-------------------------------------------------------------------- gray16gray16480 gray16(const rgba8& c) : 481 v(luminance(c)), 482 a((value_type(c.a) << 8) | c.a) {} 483 484 //-------------------------------------------------------------------- gray16gray16485 gray16(const srgba8& c) : 486 v(luminance(c)), 487 a((value_type(c.a) << 8) | c.a) {} 488 489 //-------------------------------------------------------------------- gray16gray16490 gray16(const rgba16& c) : 491 v(luminance(c)), 492 a(c.a) {} 493 494 //-------------------------------------------------------------------- gray16gray16495 gray16(const gray8& c) : 496 v((value_type(c.v) << 8) | c.v), 497 a((value_type(c.a) << 8) | c.a) {} 498 499 //-------------------------------------------------------------------- gray16gray16500 gray16(const sgray8& c) : 501 v(sRGB_conv<value_type>::rgb_from_sRGB(c.v)), 502 a(sRGB_conv<value_type>::alpha_from_sRGB(c.a)) {} 503 504 //-------------------------------------------------------------------- rgba8gray16505 operator rgba8() const 506 { 507 return rgba8(v >> 8, v >> 8, v >> 8, a >> 8); 508 } 509 510 //-------------------------------------------------------------------- srgba8gray16511 operator srgba8() const 512 { 513 value_type y = sRGB_conv<value_type>::rgb_to_sRGB(v); 514 return srgba8(y, y, y, sRGB_conv<value_type>::alpha_to_sRGB(a)); 515 } 516 517 //-------------------------------------------------------------------- rgba16gray16518 operator rgba16() const 519 { 520 return rgba16(v, v, v, a); 521 } 522 523 //-------------------------------------------------------------------- rgba32gray16524 operator rgba32() const 525 { 526 rgba32::value_type v32 = v / 65535.0f; 527 return rgba32(v32, v32, v32, a / 65535.0f); 528 } 529 530 //-------------------------------------------------------------------- gray8gray16531 operator gray8() const 532 { 533 return gray8(v >> 8, a >> 8); 534 } 535 536 //-------------------------------------------------------------------- sgray8gray16537 operator sgray8() const 538 { 539 return sgray8( 540 sRGB_conv<value_type>::rgb_to_sRGB(v), 541 sRGB_conv<value_type>::alpha_to_sRGB(a)); 542 } 543 544 //-------------------------------------------------------------------- to_doublegray16545 static AGG_INLINE double to_double(value_type a) 546 { 547 return double(a) / base_mask; 548 } 549 550 //-------------------------------------------------------------------- from_doublegray16551 static AGG_INLINE value_type from_double(double a) 552 { 553 return value_type(uround(a * base_mask)); 554 } 555 556 //-------------------------------------------------------------------- empty_valuegray16557 static AGG_INLINE value_type empty_value() 558 { 559 return 0; 560 } 561 562 //-------------------------------------------------------------------- full_valuegray16563 static AGG_INLINE value_type full_value() 564 { 565 return base_mask; 566 } 567 568 //-------------------------------------------------------------------- is_transparentgray16569 AGG_INLINE bool is_transparent() const 570 { 571 return a == 0; 572 } 573 574 //-------------------------------------------------------------------- is_opaquegray16575 AGG_INLINE bool is_opaque() const 576 { 577 return a == base_mask; 578 } 579 580 //-------------------------------------------------------------------- 581 // Fixed-point multiply, exact over int16u. multiplygray16582 static AGG_INLINE value_type multiply(value_type a, value_type b) 583 { 584 calc_type t = a * b + base_MSB; 585 return value_type(((t >> base_shift) + t) >> base_shift); 586 } 587 588 //-------------------------------------------------------------------- demultiplygray16589 static AGG_INLINE value_type demultiply(value_type a, value_type b) 590 { 591 if (a * b == 0) 592 { 593 return 0; 594 } 595 else if (a >= b) 596 { 597 return base_mask; 598 } 599 else return value_type((a * base_mask + (b >> 1)) / b); 600 } 601 602 //-------------------------------------------------------------------- 603 template<typename T> downscalegray16604 static AGG_INLINE T downscale(T a) 605 { 606 return a >> base_shift; 607 } 608 609 //-------------------------------------------------------------------- 610 template<typename T> downshiftgray16611 static AGG_INLINE T downshift(T a, unsigned n) 612 { 613 return a >> n; 614 } 615 616 //-------------------------------------------------------------------- 617 // Fixed-point multiply, almost exact over int16u. 618 // Specifically for multiplying a color component by a cover. mult_covergray16619 static AGG_INLINE value_type mult_cover(value_type a, cover_type b) 620 { 621 return multiply(a, b << 8 | b); 622 } 623 624 //-------------------------------------------------------------------- scale_covergray16625 static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) 626 { 627 return mult_cover(b, a) >> 8; 628 } 629 630 //-------------------------------------------------------------------- 631 // Interpolate p to q by a, assuming q is premultiplied by a. prelerpgray16632 static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) 633 { 634 return p + q - multiply(p, a); 635 } 636 637 //-------------------------------------------------------------------- 638 // Interpolate p to q by a. lerpgray16639 static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a) 640 { 641 int t = (q - p) * a + base_MSB - (p > q); 642 return value_type(p + (((t >> base_shift) + t) >> base_shift)); 643 } 644 645 //-------------------------------------------------------------------- cleargray16646 self_type& clear() 647 { 648 v = a = 0; 649 return *this; 650 } 651 652 //-------------------------------------------------------------------- transparentgray16653 self_type& transparent() 654 { 655 a = 0; 656 return *this; 657 } 658 659 //-------------------------------------------------------------------- opacitygray16660 self_type& opacity(double a_) 661 { 662 if (a_ < 0) a = 0; 663 else if(a_ > 1) a = 1; 664 else a = (value_type)uround(a_ * double(base_mask)); 665 return *this; 666 } 667 668 //-------------------------------------------------------------------- opacitygray16669 double opacity() const 670 { 671 return double(a) / double(base_mask); 672 } 673 674 675 //-------------------------------------------------------------------- premultiplygray16676 self_type& premultiply() 677 { 678 if (a < base_mask) 679 { 680 if(a == 0) v = 0; 681 else v = multiply(v, a); 682 } 683 return *this; 684 } 685 686 //-------------------------------------------------------------------- demultiplygray16687 self_type& demultiply() 688 { 689 if (a < base_mask) 690 { 691 if (a == 0) 692 { 693 v = 0; 694 } 695 else 696 { 697 calc_type v_ = (calc_type(v) * base_mask) / a; 698 v = (v_ > base_mask) ? value_type(base_mask) : value_type(v_); 699 } 700 } 701 return *this; 702 } 703 704 //-------------------------------------------------------------------- gradientgray16705 self_type gradient(self_type c, double k) const 706 { 707 self_type ret; 708 calc_type ik = uround(k * base_scale); 709 ret.v = lerp(v, c.v, ik); 710 ret.a = lerp(a, c.a, ik); 711 return ret; 712 } 713 714 //-------------------------------------------------------------------- addgray16715 AGG_INLINE void add(const self_type& c, unsigned cover) 716 { 717 calc_type cv, ca; 718 if (cover == cover_mask) 719 { 720 if (c.a == base_mask) 721 { 722 *this = c; 723 return; 724 } 725 else 726 { 727 cv = v + c.v; 728 ca = a + c.a; 729 } 730 } 731 else 732 { 733 cv = v + mult_cover(c.v, cover); 734 ca = a + mult_cover(c.a, cover); 735 } 736 v = (value_type)((cv > calc_type(base_mask)) ? calc_type(base_mask) : cv); 737 a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca); 738 } 739 740 //-------------------------------------------------------------------- no_colorgray16741 static self_type no_color() { return self_type(0,0); } 742 }; 743 744 745 //===================================================================gray32 746 struct gray32 747 { 748 typedef float value_type; 749 typedef double calc_type; 750 typedef double long_type; 751 typedef gray32 self_type; 752 753 value_type v; 754 value_type a; 755 756 // Calculate grayscale value as per ITU-R BT.709. luminancegray32757 static value_type luminance(double r, double g, double b) 758 { 759 return value_type(0.2126 * r + 0.7152 * g + 0.0722 * b); 760 } 761 luminancegray32762 static value_type luminance(const rgba& c) 763 { 764 return luminance(c.r, c.g, c.b); 765 } 766 luminancegray32767 static value_type luminance(const rgba32& c) 768 { 769 return luminance(c.r, c.g, c.b); 770 } 771 luminancegray32772 static value_type luminance(const rgba8& c) 773 { 774 return luminance(c.r / 255.0, c.g / 255.0, c.g / 255.0); 775 } 776 luminancegray32777 static value_type luminance(const rgba16& c) 778 { 779 return luminance(c.r / 65535.0, c.g / 65535.0, c.g / 65535.0); 780 } 781 782 //-------------------------------------------------------------------- gray32gray32783 gray32() {} 784 785 //-------------------------------------------------------------------- 786 explicit gray32(value_type v_, value_type a_ = 1) : vgray32787 v(v_), a(a_) {} 788 789 //-------------------------------------------------------------------- gray32gray32790 gray32(const self_type& c, value_type a_) : 791 v(c.v), a(a_) {} 792 793 //-------------------------------------------------------------------- gray32gray32794 gray32(const rgba& c) : 795 v(luminance(c)), 796 a(value_type(c.a)) {} 797 798 //-------------------------------------------------------------------- gray32gray32799 gray32(const rgba8& c) : 800 v(luminance(c)), 801 a(value_type(c.a / 255.0)) {} 802 803 //-------------------------------------------------------------------- gray32gray32804 gray32(const srgba8& c) : 805 v(luminance(rgba32(c))), 806 a(value_type(c.a / 255.0)) {} 807 808 //-------------------------------------------------------------------- gray32gray32809 gray32(const rgba16& c) : 810 v(luminance(c)), 811 a(value_type(c.a / 65535.0)) {} 812 813 //-------------------------------------------------------------------- gray32gray32814 gray32(const rgba32& c) : 815 v(luminance(c)), 816 a(value_type(c.a)) {} 817 818 //-------------------------------------------------------------------- gray32gray32819 gray32(const gray8& c) : 820 v(value_type(c.v / 255.0)), 821 a(value_type(c.a / 255.0)) {} 822 823 //-------------------------------------------------------------------- gray32gray32824 gray32(const sgray8& c) : 825 v(sRGB_conv<value_type>::rgb_from_sRGB(c.v)), 826 a(sRGB_conv<value_type>::alpha_from_sRGB(c.a)) {} 827 828 //-------------------------------------------------------------------- gray32gray32829 gray32(const gray16& c) : 830 v(value_type(c.v / 65535.0)), 831 a(value_type(c.a / 65535.0)) {} 832 833 //-------------------------------------------------------------------- rgbagray32834 operator rgba() const 835 { 836 return rgba(v, v, v, a); 837 } 838 839 //-------------------------------------------------------------------- gray8gray32840 operator gray8() const 841 { 842 return gray8(uround(v * 255.0), uround(a * 255.0)); 843 } 844 845 //-------------------------------------------------------------------- sgray8gray32846 operator sgray8() const 847 { 848 // Return (non-premultiplied) sRGB values. 849 return sgray8( 850 sRGB_conv<value_type>::rgb_to_sRGB(v), 851 sRGB_conv<value_type>::alpha_to_sRGB(a)); 852 } 853 854 //-------------------------------------------------------------------- gray16gray32855 operator gray16() const 856 { 857 return gray16(uround(v * 65535.0), uround(a * 65535.0)); 858 } 859 860 //-------------------------------------------------------------------- rgba8gray32861 operator rgba8() const 862 { 863 rgba8::value_type y = uround(v * 255.0); 864 return rgba8(y, y, y, uround(a * 255.0)); 865 } 866 867 //-------------------------------------------------------------------- srgba8gray32868 operator srgba8() const 869 { 870 srgba8::value_type y = sRGB_conv<value_type>::rgb_to_sRGB(v); 871 return srgba8(y, y, y, sRGB_conv<value_type>::alpha_to_sRGB(a)); 872 } 873 874 //-------------------------------------------------------------------- rgba16gray32875 operator rgba16() const 876 { 877 rgba16::value_type y = uround(v * 65535.0); 878 return rgba16(y, y, y, uround(a * 65535.0)); 879 } 880 881 //-------------------------------------------------------------------- rgba32gray32882 operator rgba32() const 883 { 884 return rgba32(v, v, v, a); 885 } 886 887 //-------------------------------------------------------------------- to_doublegray32888 static AGG_INLINE double to_double(value_type a) 889 { 890 return a; 891 } 892 893 //-------------------------------------------------------------------- from_doublegray32894 static AGG_INLINE value_type from_double(double a) 895 { 896 return value_type(a); 897 } 898 899 //-------------------------------------------------------------------- empty_valuegray32900 static AGG_INLINE value_type empty_value() 901 { 902 return 0; 903 } 904 905 //-------------------------------------------------------------------- full_valuegray32906 static AGG_INLINE value_type full_value() 907 { 908 return 1; 909 } 910 911 //-------------------------------------------------------------------- is_transparentgray32912 AGG_INLINE bool is_transparent() const 913 { 914 return a <= 0; 915 } 916 917 //-------------------------------------------------------------------- is_opaquegray32918 AGG_INLINE bool is_opaque() const 919 { 920 return a >= 1; 921 } 922 923 //-------------------------------------------------------------------- invertgray32924 static AGG_INLINE value_type invert(value_type x) 925 { 926 return 1 - x; 927 } 928 929 //-------------------------------------------------------------------- multiplygray32930 static AGG_INLINE value_type multiply(value_type a, value_type b) 931 { 932 return value_type(a * b); 933 } 934 935 //-------------------------------------------------------------------- demultiplygray32936 static AGG_INLINE value_type demultiply(value_type a, value_type b) 937 { 938 return (b == 0) ? 0 : value_type(a / b); 939 } 940 941 //-------------------------------------------------------------------- 942 template<typename T> downscalegray32943 static AGG_INLINE T downscale(T a) 944 { 945 return a; 946 } 947 948 //-------------------------------------------------------------------- 949 template<typename T> downshiftgray32950 static AGG_INLINE T downshift(T a, unsigned n) 951 { 952 return n > 0 ? a / (1 << n) : a; 953 } 954 955 //-------------------------------------------------------------------- mult_covergray32956 static AGG_INLINE value_type mult_cover(value_type a, cover_type b) 957 { 958 return value_type(a * b / cover_mask); 959 } 960 961 //-------------------------------------------------------------------- scale_covergray32962 static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) 963 { 964 return cover_type(uround(a * b)); 965 } 966 967 //-------------------------------------------------------------------- 968 // Interpolate p to q by a, assuming q is premultiplied by a. prelerpgray32969 static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) 970 { 971 return (1 - a) * p + q; // more accurate than "p + q - p * a" 972 } 973 974 //-------------------------------------------------------------------- 975 // Interpolate p to q by a. lerpgray32976 static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a) 977 { 978 // The form "p + a * (q - p)" avoids a multiplication, but may produce an 979 // inaccurate result. For example, "p + (q - p)" may not be exactly equal 980 // to q. Therefore, stick to the basic expression, which at least produces 981 // the correct result at either extreme. 982 return (1 - a) * p + a * q; 983 } 984 985 //-------------------------------------------------------------------- cleargray32986 self_type& clear() 987 { 988 v = a = 0; 989 return *this; 990 } 991 992 //-------------------------------------------------------------------- transparentgray32993 self_type& transparent() 994 { 995 a = 0; 996 return *this; 997 } 998 999 //-------------------------------------------------------------------- opacitygray321000 self_type& opacity(double a_) 1001 { 1002 if (a_ < 0) a = 0; 1003 else if (a_ > 1) a = 1; 1004 else a = value_type(a_); 1005 return *this; 1006 } 1007 1008 //-------------------------------------------------------------------- opacitygray321009 double opacity() const 1010 { 1011 return a; 1012 } 1013 1014 1015 //-------------------------------------------------------------------- premultiplygray321016 self_type& premultiply() 1017 { 1018 if (a < 0) v = 0; 1019 else if(a < 1) v *= a; 1020 return *this; 1021 } 1022 1023 //-------------------------------------------------------------------- demultiplygray321024 self_type& demultiply() 1025 { 1026 if (a < 0) v = 0; 1027 else if (a < 1) v /= a; 1028 return *this; 1029 } 1030 1031 //-------------------------------------------------------------------- gradientgray321032 self_type gradient(self_type c, double k) const 1033 { 1034 return self_type( 1035 value_type(v + (c.v - v) * k), 1036 value_type(a + (c.a - a) * k)); 1037 } 1038 1039 //-------------------------------------------------------------------- no_colorgray321040 static self_type no_color() { return self_type(0,0); } 1041 }; 1042 } 1043 1044 1045 1046 1047 #endif 1048