1 // Copyright (C) 2006 Davis E. King (davis@dlib.net) 2 // License: Boost Software License See LICENSE.txt for the full license. 3 #ifndef DLIB_PIXEl_ 4 #define DLIB_PIXEl_ 5 6 #include <iostream> 7 #include "serialize.h" 8 #include <cmath> 9 #include "algs.h" 10 #include "uintn.h" 11 #include <limits> 12 #include <complex> 13 #include "enable_if.h" 14 15 namespace dlib 16 { 17 18 // ---------------------------------------------------------------------------------------- 19 20 /*! 21 This file contains definitions of pixel objects and related classes and 22 functionality. 23 !*/ 24 25 // ---------------------------------------------------------------------------------------- 26 27 template <typename T> 28 struct pixel_traits; 29 /*! 30 WHAT THIS OBJECT REPRESENTS 31 As the name implies, this is a traits class for pixel types. 32 It defines the properties of a pixel. 33 34 This traits class will define the following public static members: 35 - bool grayscale 36 - bool rgb 37 - bool rgb_alpha 38 - bool hsi 39 - bool lab 40 41 - bool has_alpha 42 43 - long num 44 45 - basic_pixel_type 46 - basic_pixel_type min() 47 - basic_pixel_type max() 48 - is_unsigned 49 50 The above public constants are subject to the following constraints: 51 - only one of grayscale, rgb, rgb_alpha, hsi or lab is true 52 - if (rgb == true) then 53 - The type T will be a struct with 3 public members of type 54 unsigned char named "red" "green" and "blue". 55 - This type of pixel represents the RGB color space. 56 - num == 3 57 - has_alpha == false 58 - basic_pixel_type == unsigned char 59 - min() == 0 60 - max() == 255 61 - is_unsigned == true 62 - if (rgb_alpha == true) then 63 - The type T will be a struct with 4 public members of type 64 unsigned char named "red" "green" "blue" and "alpha". 65 - This type of pixel represents the RGB color space with 66 an alpha channel where an alpha of 0 represents a pixel 67 that is totally transparent and 255 represents a pixel 68 with maximum opacity. 69 - num == 4 70 - has_alpha == true 71 - basic_pixel_type == unsigned char 72 - min() == 0 73 - max() == 255 74 - is_unsigned == true 75 - else if (hsi == true) then 76 - The type T will be a struct with 3 public members of type 77 unsigned char named "h" "s" and "i". 78 - This type of pixel represents the HSI color space. 79 - num == 3 80 - has_alpha == false 81 - basic_pixel_type == unsigned char 82 - min() == 0 83 - max() == 255 84 - is_unsigned == true 85 - else if (lab == true) then 86 - The type T will be a struct with 3 public members of type 87 unsigned char named "l" "a" and "b". 88 - This type of pixel represents the Lab color space. 89 - num == 3 90 - has_alpha == false 91 - basic_pixel_type == unsigned char 92 - min() == 0 93 - max() == 255 94 - is_unsigned == true 95 - else 96 - grayscale == true 97 - This type of pixel represents a grayscale color space. T 98 will be some kind of basic scalar type such as unsigned int. 99 - num == 1 100 - has_alpha == false 101 - basic_pixel_type == T 102 - min() == the minimum obtainable value of objects of type T 103 - max() == the maximum obtainable value of objects of type T 104 - is_unsigned is true if min() == 0 and false otherwise 105 !*/ 106 107 // ---------------------------------------------------------------------------------------- 108 109 struct rgb_pixel 110 { 111 /*! 112 WHAT THIS OBJECT REPRESENTS 113 This is a simple struct that represents an RGB colored graphical pixel. 114 !*/ 115 rgb_pixelrgb_pixel116 rgb_pixel ( 117 ) {} 118 rgb_pixelrgb_pixel119 rgb_pixel ( 120 unsigned char red_, 121 unsigned char green_, 122 unsigned char blue_ 123 ) : red(red_), green(green_), blue(blue_) {} 124 125 unsigned char red; 126 unsigned char green; 127 unsigned char blue; 128 129 bool operator == (const rgb_pixel& that) const 130 { 131 return this->red == that.red 132 && this->green == that.green 133 && this->blue == that.blue; 134 } 135 136 bool operator != (const rgb_pixel& that) const 137 { 138 return !(*this == that); 139 } 140 141 }; 142 143 // ---------------------------------------------------------------------------------------- 144 145 struct bgr_pixel 146 { 147 /*! 148 WHAT THIS OBJECT REPRESENTS 149 This is a simple struct that represents an BGR colored graphical pixel. 150 (the reason it exists in addition to the rgb_pixel is so you can lay 151 it down on top of a memory region that organizes its color data in the 152 BGR format and still be able to read it) 153 !*/ 154 bgr_pixelbgr_pixel155 bgr_pixel ( 156 ) {} 157 bgr_pixelbgr_pixel158 bgr_pixel ( 159 unsigned char blue_, 160 unsigned char green_, 161 unsigned char red_ 162 ) : blue(blue_), green(green_), red(red_) {} 163 164 unsigned char blue; 165 unsigned char green; 166 unsigned char red; 167 168 bool operator == (const bgr_pixel& that) const 169 { 170 return this->blue == that.blue 171 && this->green == that.green 172 && this->red == that.red; 173 } 174 175 bool operator != (const bgr_pixel& that) const 176 { 177 return !(*this == that); 178 } 179 180 }; 181 182 // ---------------------------------------------------------------------------------------- 183 184 struct rgb_alpha_pixel 185 { 186 /*! 187 WHAT THIS OBJECT REPRESENTS 188 This is a simple struct that represents an RGB colored graphical pixel 189 with an alpha channel. 190 !*/ 191 rgb_alpha_pixelrgb_alpha_pixel192 rgb_alpha_pixel ( 193 ) {} 194 rgb_alpha_pixelrgb_alpha_pixel195 rgb_alpha_pixel ( 196 unsigned char red_, 197 unsigned char green_, 198 unsigned char blue_, 199 unsigned char alpha_ 200 ) : red(red_), green(green_), blue(blue_), alpha(alpha_) {} 201 202 unsigned char red; 203 unsigned char green; 204 unsigned char blue; 205 unsigned char alpha; 206 207 bool operator == (const rgb_alpha_pixel& that) const 208 { 209 return this->red == that.red 210 && this->green == that.green 211 && this->blue == that.blue 212 && this->alpha == that.alpha; 213 } 214 215 bool operator != (const rgb_alpha_pixel& that) const 216 { 217 return !(*this == that); 218 } 219 220 }; 221 222 // ---------------------------------------------------------------------------------------- 223 224 struct hsi_pixel 225 { 226 /*! 227 WHAT THIS OBJECT REPRESENTS 228 This is a simple struct that represents an HSI colored graphical pixel. 229 !*/ 230 hsi_pixelhsi_pixel231 hsi_pixel ( 232 ) {} 233 hsi_pixelhsi_pixel234 hsi_pixel ( 235 unsigned char h_, 236 unsigned char s_, 237 unsigned char i_ 238 ) : h(h_), s(s_), i(i_) {} 239 240 unsigned char h; 241 unsigned char s; 242 unsigned char i; 243 244 bool operator == (const hsi_pixel& that) const 245 { 246 return this->h == that.h 247 && this->s == that.s 248 && this->i == that.i; 249 } 250 251 bool operator != (const hsi_pixel& that) const 252 { 253 return !(*this == that); 254 } 255 256 }; 257 258 // ---------------------------------------------------------------------------------------- 259 260 struct lab_pixel 261 { 262 /*! 263 WHAT THIS OBJECT REPRESENTS 264 This is a simple struct that represents an Lab colored graphical pixel. 265 !*/ 266 lab_pixellab_pixel267 lab_pixel ( 268 ) {} 269 lab_pixellab_pixel270 lab_pixel ( 271 unsigned char l_, 272 unsigned char a_, 273 unsigned char b_ 274 ) : l(l_), a(a_), b(b_) {} 275 276 unsigned char l; 277 unsigned char a; 278 unsigned char b; 279 280 bool operator == (const lab_pixel& that) const 281 { 282 return this->l == that.l 283 && this->a == that.a 284 && this->b == that.b; 285 } 286 287 bool operator != (const lab_pixel& that) const 288 { 289 return !(*this == that); 290 } 291 292 }; 293 294 // ---------------------------------------------------------------------------------------- 295 296 template < 297 typename P1, 298 typename P2 299 > 300 inline void assign_pixel ( 301 P1& dest, 302 const P2& src 303 ); 304 /*! 305 requires 306 - pixel_traits<P1> must be defined 307 - pixel_traits<P2> must be defined 308 ensures 309 - if (P1 and P2 are the same type of pixel) then 310 - simply copies the value of src into dest. In other words, 311 dest will be identical to src after this function returns. 312 - else if (P1 and P2 are not the same type of pixel) then 313 - assigns pixel src to pixel dest and does any necessary color space 314 conversions. 315 - When converting from a grayscale color space with more than 255 values the 316 pixel intensity is saturated at pixel_traits<P1>::max() or pixel_traits<P1>::min() 317 as appropriate. 318 - if (the dest pixel has an alpha channel and the src pixel doesn't) then 319 - #dest.alpha == 255 320 - else if (the src pixel has an alpha channel but the dest pixel doesn't) then 321 - #dest == the original dest value blended with the src value according 322 to the alpha channel in src. 323 (i.e. #dest == src*(alpha/255) + dest*(1-alpha/255)) 324 !*/ 325 326 // ---------------------------------------------------------------------------------------- 327 328 template < 329 typename P 330 > 331 inline typename pixel_traits<P>::basic_pixel_type get_pixel_intensity ( 332 const P& src 333 ); 334 /*! 335 requires 336 - pixel_traits<P> must be defined 337 ensures 338 - if (pixel_traits<P>::grayscale == true) then 339 - returns src 340 - else 341 - converts src to grayscale and returns the resulting value. 342 !*/ 343 344 // ---------------------------------------------------------------------------------------- 345 346 template < 347 typename P, 348 typename T 349 > 350 inline void assign_pixel_intensity ( 351 P& dest, 352 const T& new_intensity 353 ); 354 /*! 355 requires 356 - pixel_traits<P> must be defined 357 - pixel_traits<T> must be defined 358 ensures 359 - This function changes the intensity of the dest pixel. So if the pixel in 360 question is a grayscale pixel then it simply assigns that pixel with the 361 value of get_pixel_intensity(new_intensity). However, if the pixel is not 362 a grayscale pixel then it converts the pixel to the HSI color space and sets 363 the I channel to the given intensity and then converts this HSI value back to 364 the original pixel's color space. 365 - Note that we don't necessarily have #get_pixel_intensity(dest) == get_pixel_intensity(new_intensity) 366 due to vagaries of how converting to and from HSI works out. 367 - if (the dest pixel has an alpha channel) then 368 - #dest.alpha == dest.alpha 369 !*/ 370 371 // ---------------------------------------------------------------------------------------- 372 373 inline void serialize ( 374 const rgb_pixel& item, 375 std::ostream& out 376 ); 377 /*! 378 provides serialization support for the rgb_pixel struct 379 !*/ 380 381 // ---------------------------------------------------------------------------------------- 382 383 inline void deserialize ( 384 rgb_pixel& item, 385 std::istream& in 386 ); 387 /*! 388 provides deserialization support for the rgb_pixel struct 389 !*/ 390 391 // ---------------------------------------------------------------------------------------- 392 393 inline void serialize ( 394 const bgr_pixel& item, 395 std::ostream& out 396 ); 397 /*! 398 provides serialization support for the bgr_pixel struct 399 !*/ 400 401 // ---------------------------------------------------------------------------------------- 402 403 inline void deserialize ( 404 bgr_pixel& item, 405 std::istream& in 406 ); 407 /*! 408 provides deserialization support for the bgr_pixel struct 409 !*/ 410 411 // ---------------------------------------------------------------------------------------- 412 413 inline void serialize ( 414 const rgb_alpha_pixel& item, 415 std::ostream& out 416 ); 417 /*! 418 provides serialization support for the rgb_alpha_pixel struct 419 !*/ 420 421 // ---------------------------------------------------------------------------------------- 422 423 inline void deserialize ( 424 rgb_alpha_pixel& item, 425 std::istream& in 426 ); 427 /*! 428 provides deserialization support for the rgb_alpha_pixel struct 429 !*/ 430 431 // ---------------------------------------------------------------------------------------- 432 433 inline void serialize ( 434 const hsi_pixel& item, 435 std::ostream& out 436 ); 437 /*! 438 provides serialization support for the hsi_pixel struct 439 !*/ 440 441 // ---------------------------------------------------------------------------------------- 442 443 inline void serialize ( 444 const lab_pixel& item, 445 std::ostream& out 446 ); 447 /*! 448 provides serialization support for the lab_pixel struct 449 !*/ 450 451 452 // ---------------------------------------------------------------------------------------- 453 454 inline void deserialize ( 455 hsi_pixel& item, 456 std::istream& in 457 ); 458 /*! 459 provides deserialization support for the hsi_pixel struct 460 !*/ 461 // ---------------------------------------------------------------------------------------- 462 463 inline void deserialize ( 464 lab_pixel& item, 465 std::istream& in 466 ); 467 /*! 468 provides deserialization support for the lab_pixel struct 469 !*/ 470 471 // ---------------------------------------------------------------------------------------- 472 473 template <> 474 struct pixel_traits<rgb_pixel> 475 { 476 constexpr static bool rgb = true; 477 constexpr static bool rgb_alpha = false; 478 constexpr static bool grayscale = false; 479 constexpr static bool hsi = false; 480 constexpr static bool lab = false; 481 enum { num = 3}; 482 typedef unsigned char basic_pixel_type; 483 static basic_pixel_type min() { return 0;} 484 static basic_pixel_type max() { return 255;} 485 constexpr static bool is_unsigned = true; 486 constexpr static bool has_alpha = false; 487 }; 488 489 // ---------------------------------------------------------------------------------------- 490 491 template <> 492 struct pixel_traits<bgr_pixel> 493 { 494 constexpr static bool rgb = true; 495 constexpr static bool rgb_alpha = false; 496 constexpr static bool grayscale = false; 497 constexpr static bool hsi = false; 498 constexpr static bool lab = false; 499 constexpr static long num = 3; 500 typedef unsigned char basic_pixel_type; 501 static basic_pixel_type min() { return 0;} 502 static basic_pixel_type max() { return 255;} 503 constexpr static bool is_unsigned = true; 504 constexpr static bool has_alpha = false; 505 }; 506 507 // ---------------------------------------------------------------------------------------- 508 509 template <> 510 struct pixel_traits<rgb_alpha_pixel> 511 { 512 constexpr static bool rgb = false; 513 constexpr static bool rgb_alpha = true; 514 constexpr static bool grayscale = false; 515 constexpr static bool hsi = false; 516 constexpr static bool lab = false; 517 constexpr static long num = 4; 518 typedef unsigned char basic_pixel_type; 519 static basic_pixel_type min() { return 0;} 520 static basic_pixel_type max() { return 255;} 521 constexpr static bool is_unsigned = true; 522 constexpr static bool has_alpha = true; 523 }; 524 525 // ---------------------------------------------------------------------------------------- 526 527 528 template <> 529 struct pixel_traits<hsi_pixel> 530 { 531 constexpr static bool rgb = false; 532 constexpr static bool rgb_alpha = false; 533 constexpr static bool grayscale = false; 534 constexpr static bool hsi = true; 535 constexpr static bool lab = false; 536 constexpr static long num = 3; 537 typedef unsigned char basic_pixel_type; 538 static basic_pixel_type min() { return 0;} 539 static basic_pixel_type max() { return 255;} 540 constexpr static bool is_unsigned = true; 541 constexpr static bool has_alpha = false; 542 }; 543 544 // ---------------------------------------------------------------------------------------- 545 546 547 template <> 548 struct pixel_traits<lab_pixel> 549 { 550 constexpr static bool rgb = false; 551 constexpr static bool rgb_alpha = false; 552 constexpr static bool grayscale = false; 553 constexpr static bool hsi = false; 554 constexpr static bool lab = true; 555 constexpr static long num = 3; 556 typedef unsigned char basic_pixel_type; 557 static basic_pixel_type min() { return 0;} 558 static basic_pixel_type max() { return 255;} 559 constexpr static bool is_unsigned = true; 560 constexpr static bool has_alpha = false; 561 }; 562 563 // ---------------------------------------------------------------------------------------- 564 565 template <typename T> 566 struct grayscale_pixel_traits 567 { 568 constexpr static bool rgb = false; 569 constexpr static bool rgb_alpha = false; 570 constexpr static bool grayscale = true; 571 constexpr static bool hsi = false; 572 constexpr static bool lab = false; 573 constexpr static long num = 1; 574 constexpr static bool has_alpha = false; 575 typedef T basic_pixel_type; 576 static basic_pixel_type min() { return std::numeric_limits<T>::min();} 577 static basic_pixel_type max() { return std::numeric_limits<T>::max();} 578 constexpr static bool is_unsigned = is_unsigned_type<T>::value; 579 }; 580 581 template <> struct pixel_traits<unsigned char> : public grayscale_pixel_traits<unsigned char> {}; 582 template <> struct pixel_traits<unsigned short> : public grayscale_pixel_traits<unsigned short> {}; 583 template <> struct pixel_traits<unsigned int> : public grayscale_pixel_traits<unsigned int> {}; 584 template <> struct pixel_traits<unsigned long> : public grayscale_pixel_traits<unsigned long> {}; 585 586 template <> struct pixel_traits<char> : public grayscale_pixel_traits<char> {}; 587 template <> struct pixel_traits<signed char> : public grayscale_pixel_traits<signed char> {}; 588 template <> struct pixel_traits<short> : public grayscale_pixel_traits<short> {}; 589 template <> struct pixel_traits<int> : public grayscale_pixel_traits<int> {}; 590 template <> struct pixel_traits<long> : public grayscale_pixel_traits<long> {}; 591 592 template <> struct pixel_traits<int64> : public grayscale_pixel_traits<int64> {}; 593 template <> struct pixel_traits<uint64> : public grayscale_pixel_traits<uint64> {}; 594 595 // ---------------------------------------------------------------------------------------- 596 597 template <typename T> 598 struct float_grayscale_pixel_traits 599 { 600 constexpr static bool rgb = false; 601 constexpr static bool rgb_alpha = false; 602 constexpr static bool grayscale = true; 603 constexpr static bool hsi = false; 604 constexpr static bool lab = false; 605 constexpr static long num = 1; 606 constexpr static bool has_alpha = false; 607 typedef T basic_pixel_type; 608 static basic_pixel_type min() { return -std::numeric_limits<T>::max();} 609 static basic_pixel_type max() { return std::numeric_limits<T>::max();} 610 constexpr static bool is_unsigned = false; 611 }; 612 613 template <> struct pixel_traits<float> : public float_grayscale_pixel_traits<float> {}; 614 template <> struct pixel_traits<double> : public float_grayscale_pixel_traits<double> {}; 615 template <> struct pixel_traits<long double> : public float_grayscale_pixel_traits<long double> {}; 616 617 // These are here mainly so you can easily copy images into complex arrays. This is 618 // useful when you want to do a FFT on an image or some similar operation. 619 template <> struct pixel_traits<std::complex<float> > : public float_grayscale_pixel_traits<float> {}; 620 template <> struct pixel_traits<std::complex<double> > : public float_grayscale_pixel_traits<double> {}; 621 template <> struct pixel_traits<std::complex<long double> > : public float_grayscale_pixel_traits<long double> {}; 622 623 // ---------------------------------------------------------------------------------------- 624 625 // The following is a bunch of conversion stuff for the assign_pixel function. 626 627 namespace assign_pixel_helpers 628 { 629 630 // ----------------------------- 631 // all the same kind 632 633 template < typename P > 634 typename enable_if_c<pixel_traits<P>::grayscale>::type 635 assign(P& dest, const P& src) 636 { 637 dest = src; 638 } 639 640 // ----------------------------- 641 642 template <typename T> 643 typename unsigned_type<T>::type make_unsigned ( 644 const T& val 645 ) { return static_cast<typename unsigned_type<T>::type>(val); } 646 647 inline float make_unsigned(const float& val) { return val; } 648 inline double make_unsigned(const double& val) { return val; } 649 inline long double make_unsigned(const long double& val) { return val; } 650 651 652 template <typename T, typename P> 653 typename enable_if_c<pixel_traits<T>::is_unsigned == pixel_traits<P>::is_unsigned, bool>::type less_or_equal_to_max ( 654 const P& p 655 ) 656 /*! 657 ensures 658 - returns true if p is <= max value of T 659 !*/ 660 { 661 return p <= pixel_traits<T>::max(); 662 } 663 664 template <typename T, typename P> 665 typename enable_if_c<pixel_traits<T>::is_unsigned && !pixel_traits<P>::is_unsigned, bool>::type less_or_equal_to_max ( 666 const P& p 667 ) 668 { 669 if (p <= 0) 670 return true; 671 else if (make_unsigned(p) <= pixel_traits<T>::max()) 672 return true; 673 else 674 return false; 675 } 676 677 template <typename T, typename P> 678 typename enable_if_c<!pixel_traits<T>::is_unsigned && pixel_traits<P>::is_unsigned, bool>::type less_or_equal_to_max ( 679 const P& p 680 ) 681 { 682 return p <= make_unsigned(pixel_traits<T>::max()); 683 } 684 685 // ----------------------------- 686 687 template <typename T, typename P> 688 typename enable_if_c<pixel_traits<P>::is_unsigned, bool >::type greater_or_equal_to_min ( 689 const P& 690 ) { return true; } 691 /*! 692 ensures 693 - returns true if p is >= min value of T 694 !*/ 695 696 template <typename T, typename P> 697 typename enable_if_c<!pixel_traits<P>::is_unsigned && pixel_traits<T>::is_unsigned, bool >::type greater_or_equal_to_min ( 698 const P& p 699 ) 700 { 701 return p >= 0; 702 } 703 704 template <typename T, typename P> 705 typename enable_if_c<!pixel_traits<P>::is_unsigned && !pixel_traits<T>::is_unsigned, bool >::type greater_or_equal_to_min ( 706 const P& p 707 ) 708 { 709 return p >= pixel_traits<T>::min(); 710 } 711 // ----------------------------- 712 713 template < typename P1, typename P2 > 714 typename enable_if_c<pixel_traits<P1>::grayscale && pixel_traits<P2>::grayscale>::type 715 assign(P1& dest, const P2& src) 716 { 717 /* 718 The reason for these weird comparison functions is to avoid getting compiler 719 warnings about comparing signed types to unsigned and stuff like that. 720 */ 721 722 if (less_or_equal_to_max<P1>(src)) 723 if (greater_or_equal_to_min<P1>(src)) 724 dest = static_cast<P1>(src); 725 else 726 dest = pixel_traits<P1>::min(); 727 else 728 dest = pixel_traits<P1>::max(); 729 } 730 731 // ----------------------------- 732 // ----------------------------- 733 // ----------------------------- 734 735 template < typename P1, typename P2 > 736 typename enable_if_c<pixel_traits<P1>::rgb && pixel_traits<P2>::rgb>::type 737 assign(P1& dest, const P2& src) 738 { 739 dest.red = src.red; 740 dest.green = src.green; 741 dest.blue = src.blue; 742 } 743 744 template < typename P1, typename P2 > 745 typename enable_if_c<pixel_traits<P1>::rgb_alpha && pixel_traits<P2>::rgb_alpha>::type 746 assign(P1& dest, const P2& src) 747 { 748 dest.red = src.red; 749 dest.green = src.green; 750 dest.blue = src.blue; 751 dest.alpha = src.alpha; 752 } 753 754 template < typename P1, typename P2 > 755 typename enable_if_c<pixel_traits<P1>::hsi && pixel_traits<P2>::hsi>::type 756 assign(P1& dest, const P2& src) 757 { 758 dest.h = src.h; 759 dest.s = src.s; 760 dest.i = src.i; 761 } 762 763 template < typename P1, typename P2 > 764 typename enable_if_c<pixel_traits<P1>::lab && pixel_traits<P2>::lab>::type 765 assign(P1& dest, const P2& src) 766 { 767 dest.l = src.l; 768 dest.a = src.a; 769 dest.b = src.b; 770 } 771 772 // ----------------------------- 773 // dest is a grayscale 774 775 template < typename P1, typename P2 > 776 typename enable_if_c<pixel_traits<P1>::grayscale && pixel_traits<P2>::rgb>::type 777 assign(P1& dest, const P2& src) 778 { 779 const unsigned int temp = ((static_cast<unsigned int>(src.red) + 780 static_cast<unsigned int>(src.green) + 781 static_cast<unsigned int>(src.blue))/3); 782 assign_pixel(dest, temp); 783 } 784 785 template < typename P1, typename P2 > 786 typename enable_if_c<pixel_traits<P1>::grayscale && pixel_traits<P2>::rgb_alpha>::type 787 assign(P1& dest, const P2& src) 788 { 789 790 const unsigned char avg = static_cast<unsigned char>((static_cast<unsigned int>(src.red) + 791 static_cast<unsigned int>(src.green) + 792 static_cast<unsigned int>(src.blue))/3); 793 794 if (src.alpha == 255) 795 { 796 assign_pixel(dest, avg); 797 } 798 else 799 { 800 // perform this assignment using fixed point arithmetic: 801 // dest = src*(alpha/255) + dest*(1 - alpha/255); 802 // dest = src*(alpha/255) + dest*1 - dest*(alpha/255); 803 // dest = dest*1 + src*(alpha/255) - dest*(alpha/255); 804 // dest = dest*1 + (src - dest)*(alpha/255); 805 // dest += (src - dest)*(alpha/255); 806 807 int temp = avg; 808 // copy dest into dest_copy using assign_pixel to avoid potential 809 // warnings about implicit float to int warnings. 810 int dest_copy; 811 assign_pixel(dest_copy, dest); 812 813 temp -= dest_copy; 814 815 temp *= src.alpha; 816 817 temp /= 255; 818 819 assign_pixel(dest, temp+dest_copy); 820 } 821 } 822 823 template < typename P1, typename P2 > 824 typename enable_if_c<pixel_traits<P1>::grayscale && pixel_traits<P2>::hsi>::type 825 assign(P1& dest, const P2& src) 826 { 827 assign_pixel(dest, src.i); 828 } 829 830 template < typename P1, typename P2 > 831 typename enable_if_c<pixel_traits<P1>::grayscale && pixel_traits<P2>::lab>::type 832 assign(P1& dest, const P2& src) 833 { 834 assign_pixel(dest, src.l); 835 } 836 837 838 // ----------------------------- 839 840 struct HSL 841 { 842 double h; 843 double s; 844 double l; 845 }; 846 847 struct COLOUR 848 { 849 double r; 850 double g; 851 double b; 852 }; 853 854 /* 855 I found this excellent bit of code for dealing with HSL spaces at 856 http://local.wasp.uwa.edu.au/~pbourke/colour/hsl/ 857 */ 858 /* 859 Calculate HSL from RGB 860 Hue is in degrees 861 Lightness is between 0 and 1 862 Saturation is between 0 and 1 863 */ 864 inline HSL RGB2HSL(COLOUR c1) 865 { 866 double themin,themax,delta; 867 HSL c2; 868 using namespace std; 869 870 themin = std::min(c1.r,std::min(c1.g,c1.b)); 871 themax = std::max(c1.r,std::max(c1.g,c1.b)); 872 delta = themax - themin; 873 c2.l = (themin + themax) / 2; 874 c2.s = 0; 875 if (c2.l > 0 && c2.l < 1) 876 c2.s = delta / (c2.l < 0.5 ? (2*c2.l) : (2-2*c2.l)); 877 c2.h = 0; 878 if (delta > 0) { 879 if (themax == c1.r && themax != c1.g) 880 c2.h += (c1.g - c1.b) / delta; 881 if (themax == c1.g && themax != c1.b) 882 c2.h += (2 + (c1.b - c1.r) / delta); 883 if (themax == c1.b && themax != c1.r) 884 c2.h += (4 + (c1.r - c1.g) / delta); 885 c2.h *= 60; 886 } 887 return(c2); 888 } 889 890 /* 891 Calculate RGB from HSL, reverse of RGB2HSL() 892 Hue is in degrees 893 Lightness is between 0 and 1 894 Saturation is between 0 and 1 895 */ 896 inline COLOUR HSL2RGB(HSL c1) 897 { 898 COLOUR c2,sat,ctmp; 899 using namespace std; 900 901 if (c1.h < 120) { 902 sat.r = (120 - c1.h) / 60.0; 903 sat.g = c1.h / 60.0; 904 sat.b = 0; 905 } else if (c1.h < 240) { 906 sat.r = 0; 907 sat.g = (240 - c1.h) / 60.0; 908 sat.b = (c1.h - 120) / 60.0; 909 } else { 910 sat.r = (c1.h - 240) / 60.0; 911 sat.g = 0; 912 sat.b = (360 - c1.h) / 60.0; 913 } 914 sat.r = std::min(sat.r,1.0); 915 sat.g = std::min(sat.g,1.0); 916 sat.b = std::min(sat.b,1.0); 917 918 ctmp.r = 2 * c1.s * sat.r + (1 - c1.s); 919 ctmp.g = 2 * c1.s * sat.g + (1 - c1.s); 920 ctmp.b = 2 * c1.s * sat.b + (1 - c1.s); 921 922 if (c1.l < 0.5) { 923 c2.r = c1.l * ctmp.r; 924 c2.g = c1.l * ctmp.g; 925 c2.b = c1.l * ctmp.b; 926 } else { 927 c2.r = (1 - c1.l) * ctmp.r + 2 * c1.l - 1; 928 c2.g = (1 - c1.l) * ctmp.g + 2 * c1.l - 1; 929 c2.b = (1 - c1.l) * ctmp.b + 2 * c1.l - 1; 930 } 931 932 return(c2); 933 } 934 935 // ----------------------------- 936 937 struct Lab 938 { 939 double l; 940 double a; 941 double b; 942 }; 943 /* 944 Calculate Lab from RGB 945 L is between 0 and 100 946 a is between -128 and 127 947 b is between -128 and 127 948 RGB is between 0.0 and 1.0 949 */ 950 inline Lab RGB2Lab(COLOUR c1) 951 { 952 Lab c2; 953 using namespace std; 954 955 double var_R = c1.r; 956 double var_G = c1.g; 957 double var_B = c1.b; 958 959 if (var_R > 0.04045) { 960 var_R = pow(((var_R + 0.055) / 1.055), 2.4); 961 } else { 962 var_R = var_R / 12.92; 963 } 964 965 if (var_G > 0.04045) { 966 var_G = pow(((var_G + 0.055) / 1.055), 2.4); 967 } else { 968 var_G = var_G / 12.92; 969 } 970 971 if (var_B > 0.04045) { 972 var_B = pow(((var_B + 0.055) / 1.055), 2.4); 973 } else { 974 var_B = var_B / 12.92; 975 } 976 977 var_R = var_R * 100; 978 var_G = var_G * 100; 979 var_B = var_B * 100; 980 981 //Observer. = 2°, Illuminant = D65 982 double X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805; 983 double Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722; 984 double Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505; 985 986 double var_X = X / 95.047; 987 double var_Y = Y / 100.000; 988 double var_Z = Z / 108.883; 989 990 if (var_X > 0.008856) { 991 var_X = pow(var_X, (1.0 / 3)); 992 } 993 else { 994 var_X = (7.787 * var_X) + (16.0 / 116); 995 } 996 997 if (var_Y > 0.008856) { 998 var_Y = pow(var_Y, (1.0 / 3)); 999 } 1000 else { 1001 var_Y = (7.787 * var_Y) + (16.0 / 116); 1002 } 1003 1004 if (var_Z > 0.008856) { 1005 var_Z = pow(var_Z, (1.0 / 3)); 1006 } 1007 else { 1008 var_Z = (7.787 * var_Z) + (16.0 / 116); 1009 } 1010 1011 //clamping 1012 c2.l = std::max(0.0, (116.0 * var_Y) - 16); 1013 c2.a = std::max(-128.0, std::min(127.0, 500.0 * (var_X - var_Y))); 1014 c2.b = std::max(-128.0, std::min(127.0, 200.0 * (var_Y - var_Z))); 1015 1016 return c2; 1017 } 1018 1019 /* 1020 Calculate RGB from Lab, reverse of RGB2LAb() 1021 L is between 0 and 100 1022 a is between -128 and 127 1023 b is between -128 and 127 1024 RGB is between 0.0 and 1.0 1025 */ 1026 inline COLOUR Lab2RGB(Lab c1) { 1027 COLOUR c2; 1028 using namespace std; 1029 1030 double var_Y = (c1.l + 16) / 116.0; 1031 double var_X = (c1.a / 500.0) + var_Y; 1032 double var_Z = var_Y - (c1.b / 200); 1033 1034 if (pow(var_Y, 3) > 0.008856) { 1035 var_Y = pow(var_Y, 3); 1036 } else { 1037 var_Y = (var_Y - 16.0 / 116) / 7.787; 1038 } 1039 1040 if (pow(var_X, 3) > 0.008856) { 1041 var_X = pow(var_X, 3); 1042 } else { 1043 var_X = (var_X - 16.0 / 116) / 7.787; 1044 } 1045 1046 if (pow(var_Z, 3) > 0.008856) { 1047 var_Z = pow(var_Z, 3); 1048 } else { 1049 var_Z = (var_Z - 16.0 / 116) / 7.787; 1050 } 1051 1052 double X = var_X * 95.047; 1053 double Y = var_Y * 100.000; 1054 double Z = var_Z * 108.883; 1055 1056 var_X = X / 100.0; 1057 var_Y = Y / 100.0; 1058 var_Z = Z / 100.0; 1059 1060 double var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986; 1061 double var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415; 1062 double var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570; 1063 1064 if (var_R > 0.0031308) { 1065 var_R = 1.055 * pow(var_R, (1 / 2.4)) - 0.055; 1066 } else { 1067 var_R = 12.92 * var_R; 1068 } 1069 1070 if (var_G > 0.0031308) { 1071 var_G = 1.055 * pow(var_G, (1 / 2.4)) - 0.055; 1072 } else { 1073 var_G = 12.92 * var_G; 1074 } 1075 1076 if (var_B > 0.0031308) { 1077 var_B = 1.055 * pow(var_B, (1 / 2.4)) - 0.055; 1078 } else { 1079 var_B = 12.92 * var_B; 1080 } 1081 1082 // clamping 1083 c2.r = std::max(0.0, std::min(1.0, var_R)); 1084 c2.g = std::max(0.0, std::min(1.0, var_G)); 1085 c2.b = std::max(0.0, std::min(1.0, var_B)); 1086 1087 return (c2); 1088 } 1089 1090 1091 // ----------------------------- 1092 // dest is a color rgb_pixel 1093 1094 template < typename P1 > 1095 typename enable_if_c<pixel_traits<P1>::rgb>::type 1096 assign(P1& dest, const unsigned char& src) 1097 { 1098 dest.red = src; 1099 dest.green = src; 1100 dest.blue = src; 1101 } 1102 1103 template < typename P1, typename P2 > 1104 typename enable_if_c<pixel_traits<P1>::rgb && pixel_traits<P2>::grayscale>::type 1105 assign(P1& dest, const P2& src) 1106 { 1107 unsigned char p; 1108 assign_pixel(p, src); 1109 dest.red = p; 1110 dest.green = p; 1111 dest.blue = p; 1112 } 1113 1114 template < typename P1, typename P2 > 1115 typename enable_if_c<pixel_traits<P1>::rgb && pixel_traits<P2>::rgb_alpha>::type 1116 assign(P1& dest, const P2& src) 1117 { 1118 if (src.alpha == 255) 1119 { 1120 dest.red = src.red; 1121 dest.green = src.green; 1122 dest.blue = src.blue; 1123 } 1124 else 1125 { 1126 // perform this assignment using fixed point arithmetic: 1127 // dest = src*(alpha/255) + dest*(1 - alpha/255); 1128 // dest = src*(alpha/255) + dest*1 - dest*(alpha/255); 1129 // dest = dest*1 + src*(alpha/255) - dest*(alpha/255); 1130 // dest = dest*1 + (src - dest)*(alpha/255); 1131 // dest += (src - dest)*(alpha/255); 1132 1133 unsigned int temp_r = src.red; 1134 unsigned int temp_g = src.green; 1135 unsigned int temp_b = src.blue; 1136 1137 temp_r -= dest.red; 1138 temp_g -= dest.green; 1139 temp_b -= dest.blue; 1140 1141 temp_r *= src.alpha; 1142 temp_g *= src.alpha; 1143 temp_b *= src.alpha; 1144 1145 temp_r >>= 8; 1146 temp_g >>= 8; 1147 temp_b >>= 8; 1148 1149 dest.red += static_cast<unsigned char>(temp_r&0xFF); 1150 dest.green += static_cast<unsigned char>(temp_g&0xFF); 1151 dest.blue += static_cast<unsigned char>(temp_b&0xFF); 1152 } 1153 } 1154 1155 template < typename P1, typename P2 > 1156 typename enable_if_c<pixel_traits<P1>::rgb && pixel_traits<P2>::hsi>::type 1157 assign(P1& dest, const P2& src) 1158 { 1159 COLOUR c; 1160 HSL h; 1161 h.h = src.h; 1162 h.h = h.h/255.0*360; 1163 h.s = src.s/255.0; 1164 h.l = src.i/255.0; 1165 c = HSL2RGB(h); 1166 1167 dest.red = static_cast<unsigned char>(c.r*255.0 + 0.5); 1168 dest.green = static_cast<unsigned char>(c.g*255.0 + 0.5); 1169 dest.blue = static_cast<unsigned char>(c.b*255.0 + 0.5); 1170 } 1171 1172 template < typename P1, typename P2 > 1173 typename enable_if_c<pixel_traits<P1>::rgb && pixel_traits<P2>::lab>::type 1174 assign(P1& dest, const P2& src) 1175 { 1176 COLOUR c; 1177 Lab l; 1178 l.l = (src.l/255.0)*100; 1179 l.a = (src.a-128.0); 1180 l.b = (src.b-128.0); 1181 c = Lab2RGB(l); 1182 1183 dest.red = static_cast<unsigned char>(c.r*255.0 + 0.5); 1184 dest.green = static_cast<unsigned char>(c.g*255.0 + 0.5); 1185 dest.blue = static_cast<unsigned char>(c.b*255.0 + 0.5); 1186 } 1187 1188 1189 // ----------------------------- 1190 // dest is a color rgb_alpha_pixel 1191 1192 template < typename P1 > 1193 typename enable_if_c<pixel_traits<P1>::rgb_alpha>::type 1194 assign(P1& dest, const unsigned char& src) 1195 { 1196 dest.red = src; 1197 dest.green = src; 1198 dest.blue = src; 1199 dest.alpha = 255; 1200 } 1201 1202 1203 template < typename P1, typename P2 > 1204 typename enable_if_c<pixel_traits<P1>::rgb_alpha && pixel_traits<P2>::grayscale>::type 1205 assign(P1& dest, const P2& src) 1206 { 1207 unsigned char p; 1208 assign_pixel(p, src); 1209 1210 dest.red = p; 1211 dest.green = p; 1212 dest.blue = p; 1213 dest.alpha = 255; 1214 } 1215 1216 template < typename P1, typename P2 > 1217 typename enable_if_c<pixel_traits<P1>::rgb_alpha && pixel_traits<P2>::rgb>::type 1218 assign(P1& dest, const P2& src) 1219 { 1220 dest.red = src.red; 1221 dest.green = src.green; 1222 dest.blue = src.blue; 1223 dest.alpha = 255; 1224 } 1225 1226 template < typename P1, typename P2 > 1227 typename enable_if_c<pixel_traits<P1>::rgb_alpha && pixel_traits<P2>::hsi>::type 1228 assign(P1& dest, const P2& src) 1229 { 1230 COLOUR c; 1231 HSL h; 1232 h.h = src.h; 1233 h.h = h.h/255.0*360; 1234 h.s = src.s/255.0; 1235 h.l = src.i/255.0; 1236 c = HSL2RGB(h); 1237 1238 dest.red = static_cast<unsigned char>(c.r*255.0 + 0.5); 1239 dest.green = static_cast<unsigned char>(c.g*255.0 + 0.5); 1240 dest.blue = static_cast<unsigned char>(c.b*255.0 + 0.5); 1241 dest.alpha = 255; 1242 } 1243 1244 template < typename P1, typename P2 > 1245 typename enable_if_c<pixel_traits<P1>::rgb_alpha && pixel_traits<P2>::lab>::type 1246 assign(P1& dest, const P2& src) 1247 { 1248 COLOUR c; 1249 Lab l; 1250 l.l = (src.l/255.0)*100; 1251 l.a = (src.a-128.0); 1252 l.b = (src.b-128.0); 1253 c = Lab2RGB(l); 1254 1255 dest.red = static_cast<unsigned char>(c.r * 255 + 0.5); 1256 dest.green = static_cast<unsigned char>(c.g * 255 + 0.5); 1257 dest.blue = static_cast<unsigned char>(c.b * 255 + 0.5); 1258 dest.alpha = 255; 1259 } 1260 // ----------------------------- 1261 // dest is an hsi pixel 1262 1263 template < typename P1> 1264 typename enable_if_c<pixel_traits<P1>::hsi>::type 1265 assign(P1& dest, const unsigned char& src) 1266 { 1267 dest.h = 0; 1268 dest.s = 0; 1269 dest.i = src; 1270 } 1271 1272 1273 template < typename P1, typename P2 > 1274 typename enable_if_c<pixel_traits<P1>::hsi && pixel_traits<P2>::grayscale>::type 1275 assign(P1& dest, const P2& src) 1276 { 1277 dest.h = 0; 1278 dest.s = 0; 1279 assign_pixel(dest.i, src); 1280 } 1281 1282 template < typename P1, typename P2 > 1283 typename enable_if_c<pixel_traits<P1>::hsi && pixel_traits<P2>::rgb>::type 1284 assign(P1& dest, const P2& src) 1285 { 1286 COLOUR c1; 1287 HSL c2; 1288 c1.r = src.red/255.0; 1289 c1.g = src.green/255.0; 1290 c1.b = src.blue/255.0; 1291 c2 = RGB2HSL(c1); 1292 1293 dest.h = static_cast<unsigned char>(c2.h/360.0*255.0 + 0.5); 1294 dest.s = static_cast<unsigned char>(c2.s*255.0 + 0.5); 1295 dest.i = static_cast<unsigned char>(c2.l*255.0 + 0.5); 1296 } 1297 1298 template < typename P1, typename P2 > 1299 typename enable_if_c<pixel_traits<P1>::hsi && pixel_traits<P2>::rgb_alpha>::type 1300 assign(P1& dest, const P2& src) 1301 { 1302 rgb_pixel temp; 1303 // convert target hsi pixel to rgb 1304 assign_pixel_helpers::assign(temp,dest); 1305 1306 // now assign the rgb_alpha value to our temp rgb pixel 1307 assign_pixel_helpers::assign(temp,src); 1308 1309 // now we can just go assign the new rgb value to the 1310 // hsi pixel 1311 assign_pixel_helpers::assign(dest,temp); 1312 } 1313 1314 template < typename P1, typename P2 > 1315 typename enable_if_c<pixel_traits<P1>::hsi && pixel_traits<P2>::lab>::type 1316 assign(P1& dest, const P2& src) 1317 { 1318 rgb_pixel temp; 1319 // convert lab value to our temp rgb pixel 1320 assign_pixel_helpers::assign(temp,src); 1321 // now we can just go assign the new rgb value to the 1322 // hsi pixel 1323 assign_pixel_helpers::assign(dest,temp); 1324 } 1325 1326 // ----------------------------- 1327 // dest is an lab pixel 1328 template < typename P1> 1329 typename enable_if_c<pixel_traits<P1>::lab>::type 1330 assign(P1& dest, const unsigned char& src) 1331 { 1332 dest.a = 128; 1333 dest.b = 128; 1334 dest.l = src; 1335 } 1336 1337 1338 template < typename P1, typename P2 > 1339 typename enable_if_c<pixel_traits<P1>::lab && pixel_traits<P2>::grayscale>::type 1340 assign(P1& dest, const P2& src) 1341 { 1342 dest.a = 128; 1343 dest.b = 128; 1344 assign_pixel(dest.l, src); 1345 } 1346 1347 template < typename P1, typename P2 > 1348 typename enable_if_c<pixel_traits<P1>::lab && pixel_traits<P2>::rgb>::type 1349 assign(P1& dest, const P2& src) 1350 { 1351 COLOUR c1; 1352 Lab c2; 1353 c1.r = src.red / 255.0; 1354 c1.g = src.green / 255.0; 1355 c1.b = src.blue / 255.0; 1356 c2 = RGB2Lab(c1); 1357 1358 dest.l = static_cast<unsigned char>((c2.l / 100) * 255 + 0.5); 1359 dest.a = static_cast<unsigned char>(c2.a + 128 + 0.5); 1360 dest.b = static_cast<unsigned char>(c2.b + 128 + 0.5); 1361 } 1362 1363 template < typename P1, typename P2 > 1364 typename enable_if_c<pixel_traits<P1>::lab && pixel_traits<P2>::rgb_alpha>::type 1365 assign(P1& dest, const P2& src) 1366 { 1367 rgb_pixel temp; 1368 // convert target lab pixel to rgb 1369 assign_pixel_helpers::assign(temp,dest); 1370 1371 // now assign the rgb_alpha value to our temp rgb pixel 1372 assign_pixel_helpers::assign(temp,src); 1373 1374 // now we can just go assign the new rgb value to the 1375 // lab pixel 1376 assign_pixel_helpers::assign(dest,temp); 1377 } 1378 1379 template < typename P1, typename P2 > 1380 typename enable_if_c<pixel_traits<P1>::lab && pixel_traits<P2>::hsi>::type 1381 assign(P1& dest, const P2& src) 1382 { 1383 rgb_pixel temp; 1384 1385 // convert hsi value to our temp rgb pixel 1386 assign_pixel_helpers::assign(temp,src); 1387 1388 // now we can just go assign the new rgb value to the 1389 // lab pixel 1390 assign_pixel_helpers::assign(dest,temp); 1391 } 1392 } 1393 1394 // ----------------------------- 1395 1396 template < typename P1, typename P2 > 1397 inline void assign_pixel ( 1398 P1& dest, 1399 const P2& src 1400 ) { assign_pixel_helpers::assign(dest,src); } 1401 1402 // ---------------------------------------------------------------------------------------- 1403 1404 template < 1405 typename P, 1406 typename T 1407 > 1408 inline typename enable_if_c<pixel_traits<P>::grayscale>::type assign_pixel_intensity_helper ( 1409 P& dest, 1410 const T& new_intensity 1411 ) 1412 { 1413 assign_pixel(dest, new_intensity); 1414 } 1415 1416 template < 1417 typename P, 1418 typename T 1419 > 1420 inline typename enable_if_c<pixel_traits<P>::grayscale == false && 1421 pixel_traits<P>::has_alpha>::type assign_pixel_intensity_helper ( 1422 P& dest, 1423 const T& new_intensity 1424 ) 1425 { 1426 hsi_pixel p; 1427 const unsigned long old_alpha = dest.alpha; 1428 dest.alpha = 255; 1429 rgb_pixel temp; 1430 assign_pixel(temp, dest); // put dest into an rgb_pixel to avoid the somewhat complicated assign_pixel(hsi,rgb_alpha). 1431 assign_pixel(p,temp); 1432 assign_pixel(p.i, new_intensity); 1433 assign_pixel(dest,p); 1434 dest.alpha = old_alpha; 1435 } 1436 1437 template < 1438 typename P, 1439 typename T 1440 > 1441 inline typename enable_if_c<pixel_traits<P>::grayscale == false && 1442 pixel_traits<P>::has_alpha == false>::type assign_pixel_intensity_helper ( 1443 P& dest, 1444 const T& new_intensity 1445 ) 1446 { 1447 hsi_pixel p; 1448 assign_pixel(p,dest); 1449 assign_pixel(p.i, new_intensity); 1450 assign_pixel(dest,p); 1451 } 1452 1453 template < 1454 typename P, 1455 typename T 1456 > 1457 inline void assign_pixel_intensity ( 1458 P& dest, 1459 const T& new_intensity 1460 ) 1461 { 1462 assign_pixel_intensity_helper(dest, new_intensity); 1463 } 1464 1465 // ---------------------------------------------------------------------------------------- 1466 1467 template < 1468 typename P 1469 > 1470 inline typename enable_if_c<pixel_traits<P>::grayscale, P>::type get_pixel_intensity_helper ( 1471 const P& src 1472 ) 1473 { 1474 return src; 1475 } 1476 1477 template < 1478 typename P 1479 > 1480 inline typename enable_if_c<pixel_traits<P>::grayscale == false&& 1481 pixel_traits<P>::has_alpha, 1482 typename pixel_traits<P>::basic_pixel_type>::type get_pixel_intensity_helper ( 1483 const P& src 1484 ) 1485 { 1486 P temp = src; 1487 temp.alpha = 255; 1488 typename pixel_traits<P>::basic_pixel_type p; 1489 assign_pixel(p,temp); 1490 return p; 1491 } 1492 1493 template < 1494 typename P 1495 > 1496 inline typename enable_if_c<pixel_traits<P>::grayscale == false&& 1497 pixel_traits<P>::has_alpha == false, 1498 typename pixel_traits<P>::basic_pixel_type>::type get_pixel_intensity_helper ( 1499 const P& src 1500 ) 1501 { 1502 typename pixel_traits<P>::basic_pixel_type p; 1503 assign_pixel(p,src); 1504 return p; 1505 } 1506 1507 template < 1508 typename P 1509 > 1510 inline typename pixel_traits<P>::basic_pixel_type get_pixel_intensity ( 1511 const P& src 1512 ) 1513 { 1514 return get_pixel_intensity_helper(src); 1515 } 1516 1517 // ---------------------------------------------------------------------------------------- 1518 // ---------------------------------------------------------------------------------------- 1519 // ---------------------------------------------------------------------------------------- 1520 1521 inline void serialize ( 1522 const rgb_alpha_pixel& item, 1523 std::ostream& out 1524 ) 1525 { 1526 try 1527 { 1528 serialize(item.red,out); 1529 serialize(item.green,out); 1530 serialize(item.blue,out); 1531 serialize(item.alpha,out); 1532 } 1533 catch (serialization_error& e) 1534 { 1535 throw serialization_error(e.info + "\n while serializing object of type rgb_alpha_pixel"); 1536 } 1537 } 1538 1539 // ---------------------------------------------------------------------------------------- 1540 1541 inline void deserialize ( 1542 rgb_alpha_pixel& item, 1543 std::istream& in 1544 ) 1545 { 1546 try 1547 { 1548 deserialize(item.red,in); 1549 deserialize(item.green,in); 1550 deserialize(item.blue,in); 1551 deserialize(item.alpha,in); 1552 } 1553 catch (serialization_error& e) 1554 { 1555 throw serialization_error(e.info + "\n while deserializing object of type rgb_alpha_pixel"); 1556 } 1557 } 1558 1559 // ---------------------------------------------------------------------------------------- 1560 1561 inline void serialize ( 1562 const rgb_pixel& item, 1563 std::ostream& out 1564 ) 1565 { 1566 try 1567 { 1568 serialize(item.red,out); 1569 serialize(item.green,out); 1570 serialize(item.blue,out); 1571 } 1572 catch (serialization_error& e) 1573 { 1574 throw serialization_error(e.info + "\n while serializing object of type rgb_pixel"); 1575 } 1576 } 1577 1578 // ---------------------------------------------------------------------------------------- 1579 1580 inline void deserialize ( 1581 rgb_pixel& item, 1582 std::istream& in 1583 ) 1584 { 1585 try 1586 { 1587 deserialize(item.red,in); 1588 deserialize(item.green,in); 1589 deserialize(item.blue,in); 1590 } 1591 catch (serialization_error& e) 1592 { 1593 throw serialization_error(e.info + "\n while deserializing object of type rgb_pixel"); 1594 } 1595 } 1596 1597 // ---------------------------------------------------------------------------------------- 1598 1599 inline void serialize ( 1600 const bgr_pixel& item, 1601 std::ostream& out 1602 ) 1603 { 1604 try 1605 { 1606 serialize(item.blue,out); 1607 serialize(item.green,out); 1608 serialize(item.red,out); 1609 } 1610 catch (serialization_error& e) 1611 { 1612 throw serialization_error(e.info + "\n while serializing object of type bgr_pixel"); 1613 } 1614 } 1615 1616 // ---------------------------------------------------------------------------------------- 1617 1618 inline void deserialize ( 1619 bgr_pixel& item, 1620 std::istream& in 1621 ) 1622 { 1623 try 1624 { 1625 deserialize(item.blue,in); 1626 deserialize(item.green,in); 1627 deserialize(item.red,in); 1628 } 1629 catch (serialization_error& e) 1630 { 1631 throw serialization_error(e.info + "\n while deserializing object of type bgr_pixel"); 1632 } 1633 } 1634 1635 // ---------------------------------------------------------------------------------------- 1636 1637 inline void serialize ( 1638 const hsi_pixel& item, 1639 std::ostream& out 1640 ) 1641 { 1642 try 1643 { 1644 serialize(item.h,out); 1645 serialize(item.s,out); 1646 serialize(item.i,out); 1647 } 1648 catch (serialization_error& e) 1649 { 1650 throw serialization_error(e.info + "\n while serializing object of type hsi_pixel"); 1651 } 1652 } 1653 1654 // ---------------------------------------------------------------------------------------- 1655 1656 inline void deserialize ( 1657 hsi_pixel& item, 1658 std::istream& in 1659 ) 1660 { 1661 try 1662 { 1663 deserialize(item.h,in); 1664 deserialize(item.s,in); 1665 deserialize(item.i,in); 1666 } 1667 catch (serialization_error& e) 1668 { 1669 throw serialization_error(e.info + "\n while deserializing object of type hsi_pixel"); 1670 } 1671 } 1672 1673 // ---------------------------------------------------------------------------------------- 1674 1675 inline void serialize ( 1676 const lab_pixel& item, 1677 std::ostream& out 1678 ) 1679 { 1680 try 1681 { 1682 serialize(item.l,out); 1683 serialize(item.a,out); 1684 serialize(item.b,out); 1685 } 1686 catch (serialization_error& e) 1687 { 1688 throw serialization_error(e.info + "\n while serializing object of type lab_pixel"); 1689 } 1690 } 1691 1692 // ---------------------------------------------------------------------------------------- 1693 1694 inline void deserialize ( 1695 lab_pixel& item, 1696 std::istream& in 1697 ) 1698 { 1699 try 1700 { 1701 deserialize(item.l,in); 1702 deserialize(item.a,in); 1703 deserialize(item.b,in); 1704 } 1705 catch (serialization_error& e) 1706 { 1707 throw serialization_error(e.info + "\n while deserializing object of type lab_pixel"); 1708 } 1709 } 1710 1711 // ---------------------------------------------------------------------------------------- 1712 1713 } 1714 1715 #endif // DLIB_PIXEl_ 1716 1717