summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/pixel.h
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/pixel.h')
-rw-r--r--ml/dlib/dlib/pixel.h1649
1 files changed, 1649 insertions, 0 deletions
diff --git a/ml/dlib/dlib/pixel.h b/ml/dlib/dlib/pixel.h
new file mode 100644
index 00000000..50ead2c3
--- /dev/null
+++ b/ml/dlib/dlib/pixel.h
@@ -0,0 +1,1649 @@
+// Copyright (C) 2006 Davis E. King (davis@dlib.net)
+// License: Boost Software License See LICENSE.txt for the full license.
+#ifndef DLIB_PIXEl_
+#define DLIB_PIXEl_
+
+#include <iostream>
+#include "serialize.h"
+#include <cmath>
+#include "algs.h"
+#include "uintn.h"
+#include <limits>
+#include <complex>
+#include "enable_if.h"
+
+namespace dlib
+{
+
+// ----------------------------------------------------------------------------------------
+
+ /*!
+ This file contains definitions of pixel objects and related classes and
+ functionality.
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ template <typename T>
+ struct pixel_traits;
+ /*!
+ WHAT THIS OBJECT REPRESENTS
+ As the name implies, this is a traits class for pixel types.
+ It defines the properties of a pixel.
+
+ This traits class will define the following public static members:
+ - bool grayscale
+ - bool rgb
+ - bool rgb_alpha
+ - bool hsi
+ - bool lab
+
+ - bool has_alpha
+
+ - long num
+
+ - basic_pixel_type
+ - basic_pixel_type min()
+ - basic_pixel_type max()
+ - is_unsigned
+
+ The above public constants are subject to the following constraints:
+ - only one of grayscale, rgb, rgb_alpha, hsi or lab is true
+ - if (rgb == true) then
+ - The type T will be a struct with 3 public members of type
+ unsigned char named "red" "green" and "blue".
+ - This type of pixel represents the RGB color space.
+ - num == 3
+ - has_alpha == false
+ - basic_pixel_type == unsigned char
+ - min() == 0
+ - max() == 255
+ - is_unsigned == true
+ - if (rgb_alpha == true) then
+ - The type T will be a struct with 4 public members of type
+ unsigned char named "red" "green" "blue" and "alpha".
+ - This type of pixel represents the RGB color space with
+ an alpha channel where an alpha of 0 represents a pixel
+ that is totally transparent and 255 represents a pixel
+ with maximum opacity.
+ - num == 4
+ - has_alpha == true
+ - basic_pixel_type == unsigned char
+ - min() == 0
+ - max() == 255
+ - is_unsigned == true
+ - else if (hsi == true) then
+ - The type T will be a struct with 3 public members of type
+ unsigned char named "h" "s" and "i".
+ - This type of pixel represents the HSI color space.
+ - num == 3
+ - has_alpha == false
+ - basic_pixel_type == unsigned char
+ - min() == 0
+ - max() == 255
+ - is_unsigned == true
+ - else if (lab == true) then
+ - The type T will be a struct with 3 public members of type
+ unsigned char named "l" "a" and "b".
+ - This type of pixel represents the Lab color space.
+ - num == 3
+ - has_alpha == false
+ - basic_pixel_type == unsigned char
+ - min() == 0
+ - max() == 255
+ - is_unsigned == true
+ - else
+ - grayscale == true
+ - This type of pixel represents a grayscale color space. T
+ will be some kind of basic scalar type such as unsigned int.
+ - num == 1
+ - has_alpha == false
+ - basic_pixel_type == T
+ - min() == the minimum obtainable value of objects of type T
+ - max() == the maximum obtainable value of objects of type T
+ - is_unsigned is true if min() == 0 and false otherwise
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ struct rgb_pixel
+ {
+ /*!
+ WHAT THIS OBJECT REPRESENTS
+ This is a simple struct that represents an RGB colored graphical pixel.
+ !*/
+
+ rgb_pixel (
+ ) {}
+
+ rgb_pixel (
+ unsigned char red_,
+ unsigned char green_,
+ unsigned char blue_
+ ) : red(red_), green(green_), blue(blue_) {}
+
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+ };
+
+// ----------------------------------------------------------------------------------------
+
+ struct bgr_pixel
+ {
+ /*!
+ WHAT THIS OBJECT REPRESENTS
+ This is a simple struct that represents an BGR colored graphical pixel.
+ (the reason it exists in addition to the rgb_pixel is so you can lay
+ it down on top of a memory region that organizes its color data in the
+ BGR format and still be able to read it)
+ !*/
+
+ bgr_pixel (
+ ) {}
+
+ bgr_pixel (
+ unsigned char blue_,
+ unsigned char green_,
+ unsigned char red_
+ ) : blue(blue_), green(green_), red(red_) {}
+
+ unsigned char blue;
+ unsigned char green;
+ unsigned char red;
+ };
+
+// ----------------------------------------------------------------------------------------
+
+ struct rgb_alpha_pixel
+ {
+ /*!
+ WHAT THIS OBJECT REPRESENTS
+ This is a simple struct that represents an RGB colored graphical pixel
+ with an alpha channel.
+ !*/
+
+ rgb_alpha_pixel (
+ ) {}
+
+ rgb_alpha_pixel (
+ unsigned char red_,
+ unsigned char green_,
+ unsigned char blue_,
+ unsigned char alpha_
+ ) : red(red_), green(green_), blue(blue_), alpha(alpha_) {}
+
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+ unsigned char alpha;
+ };
+
+// ----------------------------------------------------------------------------------------
+
+ struct hsi_pixel
+ {
+ /*!
+ WHAT THIS OBJECT REPRESENTS
+ This is a simple struct that represents an HSI colored graphical pixel.
+ !*/
+
+ hsi_pixel (
+ ) {}
+
+ hsi_pixel (
+ unsigned char h_,
+ unsigned char s_,
+ unsigned char i_
+ ) : h(h_), s(s_), i(i_) {}
+
+ unsigned char h;
+ unsigned char s;
+ unsigned char i;
+ };
+ // ----------------------------------------------------------------------------------------
+
+ struct lab_pixel
+ {
+ /*!
+ WHAT THIS OBJECT REPRESENTS
+ This is a simple struct that represents an Lab colored graphical pixel.
+ !*/
+
+ lab_pixel (
+ ) {}
+
+ lab_pixel (
+ unsigned char l_,
+ unsigned char a_,
+ unsigned char b_
+ ) : l(l_), a(a_), b(b_) {}
+
+ unsigned char l;
+ unsigned char a;
+ unsigned char b;
+ };
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename P1,
+ typename P2
+ >
+ inline void assign_pixel (
+ P1& dest,
+ const P2& src
+ );
+ /*!
+ requires
+ - pixel_traits<P1> must be defined
+ - pixel_traits<P2> must be defined
+ ensures
+ - if (P1 and P2 are the same type of pixel) then
+ - simply copies the value of src into dest. In other words,
+ dest will be identical to src after this function returns.
+ - else if (P1 and P2 are not the same type of pixel) then
+ - assigns pixel src to pixel dest and does any necessary color space
+ conversions.
+ - When converting from a grayscale color space with more than 255 values the
+ pixel intensity is saturated at pixel_traits<P1>::max() or pixel_traits<P1>::min()
+ as appropriate.
+ - if (the dest pixel has an alpha channel and the src pixel doesn't) then
+ - #dest.alpha == 255
+ - else if (the src pixel has an alpha channel but the dest pixel doesn't) then
+ - #dest == the original dest value blended with the src value according
+ to the alpha channel in src.
+ (i.e. #dest == src*(alpha/255) + dest*(1-alpha/255))
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename P
+ >
+ inline typename pixel_traits<P>::basic_pixel_type get_pixel_intensity (
+ const P& src
+ );
+ /*!
+ requires
+ - pixel_traits<P> must be defined
+ ensures
+ - if (pixel_traits<P>::grayscale == true) then
+ - returns src
+ - else
+ - converts src to grayscale and returns the resulting value.
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename P,
+ typename T
+ >
+ inline void assign_pixel_intensity (
+ P& dest,
+ const T& new_intensity
+ );
+ /*!
+ requires
+ - pixel_traits<P> must be defined
+ - pixel_traits<T> must be defined
+ ensures
+ - This function changes the intensity of the dest pixel. So if the pixel in
+ question is a grayscale pixel then it simply assigns that pixel with the
+ value of get_pixel_intensity(new_intensity). However, if the pixel is not
+ a grayscale pixel then it converts the pixel to the HSI color space and sets
+ the I channel to the given intensity and then converts this HSI value back to
+ the original pixel's color space.
+ - Note that we don't necessarily have #get_pixel_intensity(dest) == get_pixel_intensity(new_intensity)
+ due to vagaries of how converting to and from HSI works out.
+ - if (the dest pixel has an alpha channel) then
+ - #dest.alpha == dest.alpha
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ inline void serialize (
+ const rgb_pixel& item,
+ std::ostream& out
+ );
+ /*!
+ provides serialization support for the rgb_pixel struct
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ inline void deserialize (
+ rgb_pixel& item,
+ std::istream& in
+ );
+ /*!
+ provides deserialization support for the rgb_pixel struct
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ inline void serialize (
+ const bgr_pixel& item,
+ std::ostream& out
+ );
+ /*!
+ provides serialization support for the bgr_pixel struct
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ inline void deserialize (
+ bgr_pixel& item,
+ std::istream& in
+ );
+ /*!
+ provides deserialization support for the bgr_pixel struct
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ inline void serialize (
+ const rgb_alpha_pixel& item,
+ std::ostream& out
+ );
+ /*!
+ provides serialization support for the rgb_alpha_pixel struct
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ inline void deserialize (
+ rgb_alpha_pixel& item,
+ std::istream& in
+ );
+ /*!
+ provides deserialization support for the rgb_alpha_pixel struct
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ inline void serialize (
+ const hsi_pixel& item,
+ std::ostream& out
+ );
+ /*!
+ provides serialization support for the hsi_pixel struct
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ inline void serialize (
+ const lab_pixel& item,
+ std::ostream& out
+ );
+ /*!
+ provides serialization support for the lab_pixel struct
+ !*/
+
+
+// ----------------------------------------------------------------------------------------
+
+ inline void deserialize (
+ hsi_pixel& item,
+ std::istream& in
+ );
+ /*!
+ provides deserialization support for the hsi_pixel struct
+ !*/
+// ----------------------------------------------------------------------------------------
+
+ inline void deserialize (
+ lab_pixel& item,
+ std::istream& in
+ );
+ /*!
+ provides deserialization support for the lab_pixel struct
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ template <>
+ struct pixel_traits<rgb_pixel>
+ {
+ constexpr static bool rgb = true;
+ constexpr static bool rgb_alpha = false;
+ constexpr static bool grayscale = false;
+ constexpr static bool hsi = false;
+ constexpr static bool lab = false;
+ enum { num = 3};
+ typedef unsigned char basic_pixel_type;
+ static basic_pixel_type min() { return 0;}
+ static basic_pixel_type max() { return 255;}
+ constexpr static bool is_unsigned = true;
+ constexpr static bool has_alpha = false;
+ };
+
+// ----------------------------------------------------------------------------------------
+
+ template <>
+ struct pixel_traits<bgr_pixel>
+ {
+ constexpr static bool rgb = true;
+ constexpr static bool rgb_alpha = false;
+ constexpr static bool grayscale = false;
+ constexpr static bool hsi = false;
+ constexpr static bool lab = false;
+ constexpr static long num = 3;
+ typedef unsigned char basic_pixel_type;
+ static basic_pixel_type min() { return 0;}
+ static basic_pixel_type max() { return 255;}
+ constexpr static bool is_unsigned = true;
+ constexpr static bool has_alpha = false;
+ };
+
+// ----------------------------------------------------------------------------------------
+
+ template <>
+ struct pixel_traits<rgb_alpha_pixel>
+ {
+ constexpr static bool rgb = false;
+ constexpr static bool rgb_alpha = true;
+ constexpr static bool grayscale = false;
+ constexpr static bool hsi = false;
+ constexpr static bool lab = false;
+ constexpr static long num = 4;
+ typedef unsigned char basic_pixel_type;
+ static basic_pixel_type min() { return 0;}
+ static basic_pixel_type max() { return 255;}
+ constexpr static bool is_unsigned = true;
+ constexpr static bool has_alpha = true;
+ };
+
+// ----------------------------------------------------------------------------------------
+
+
+ template <>
+ struct pixel_traits<hsi_pixel>
+ {
+ constexpr static bool rgb = false;
+ constexpr static bool rgb_alpha = false;
+ constexpr static bool grayscale = false;
+ constexpr static bool hsi = true;
+ constexpr static bool lab = false;
+ constexpr static long num = 3;
+ typedef unsigned char basic_pixel_type;
+ static basic_pixel_type min() { return 0;}
+ static basic_pixel_type max() { return 255;}
+ constexpr static bool is_unsigned = true;
+ constexpr static bool has_alpha = false;
+ };
+
+// ----------------------------------------------------------------------------------------
+
+
+ template <>
+ struct pixel_traits<lab_pixel>
+ {
+ constexpr static bool rgb = false;
+ constexpr static bool rgb_alpha = false;
+ constexpr static bool grayscale = false;
+ constexpr static bool hsi = false;
+ constexpr static bool lab = true;
+ constexpr static long num = 3;
+ typedef unsigned char basic_pixel_type;
+ static basic_pixel_type min() { return 0;}
+ static basic_pixel_type max() { return 255;}
+ constexpr static bool is_unsigned = true;
+ constexpr static bool has_alpha = false;
+ };
+
+// ----------------------------------------------------------------------------------------
+
+ template <typename T>
+ struct grayscale_pixel_traits
+ {
+ constexpr static bool rgb = false;
+ constexpr static bool rgb_alpha = false;
+ constexpr static bool grayscale = true;
+ constexpr static bool hsi = false;
+ constexpr static bool lab = false;
+ constexpr static long num = 1;
+ constexpr static bool has_alpha = false;
+ typedef T basic_pixel_type;
+ static basic_pixel_type min() { return std::numeric_limits<T>::min();}
+ static basic_pixel_type max() { return std::numeric_limits<T>::max();}
+ constexpr static bool is_unsigned = is_unsigned_type<T>::value;
+ };
+
+ template <> struct pixel_traits<unsigned char> : public grayscale_pixel_traits<unsigned char> {};
+ template <> struct pixel_traits<unsigned short> : public grayscale_pixel_traits<unsigned short> {};
+ template <> struct pixel_traits<unsigned int> : public grayscale_pixel_traits<unsigned int> {};
+ template <> struct pixel_traits<unsigned long> : public grayscale_pixel_traits<unsigned long> {};
+
+ template <> struct pixel_traits<char> : public grayscale_pixel_traits<char> {};
+ template <> struct pixel_traits<signed char> : public grayscale_pixel_traits<signed char> {};
+ template <> struct pixel_traits<short> : public grayscale_pixel_traits<short> {};
+ template <> struct pixel_traits<int> : public grayscale_pixel_traits<int> {};
+ template <> struct pixel_traits<long> : public grayscale_pixel_traits<long> {};
+
+ template <> struct pixel_traits<int64> : public grayscale_pixel_traits<int64> {};
+ template <> struct pixel_traits<uint64> : public grayscale_pixel_traits<uint64> {};
+
+// ----------------------------------------------------------------------------------------
+
+ template <typename T>
+ struct float_grayscale_pixel_traits
+ {
+ constexpr static bool rgb = false;
+ constexpr static bool rgb_alpha = false;
+ constexpr static bool grayscale = true;
+ constexpr static bool hsi = false;
+ constexpr static bool lab = false;
+ constexpr static long num = 1;
+ constexpr static bool has_alpha = false;
+ typedef T basic_pixel_type;
+ static basic_pixel_type min() { return -std::numeric_limits<T>::max();}
+ static basic_pixel_type max() { return std::numeric_limits<T>::max();}
+ constexpr static bool is_unsigned = false;
+ };
+
+ template <> struct pixel_traits<float> : public float_grayscale_pixel_traits<float> {};
+ template <> struct pixel_traits<double> : public float_grayscale_pixel_traits<double> {};
+ template <> struct pixel_traits<long double> : public float_grayscale_pixel_traits<long double> {};
+
+ // These are here mainly so you can easily copy images into complex arrays. This is
+ // useful when you want to do a FFT on an image or some similar operation.
+ template <> struct pixel_traits<std::complex<float> > : public float_grayscale_pixel_traits<float> {};
+ template <> struct pixel_traits<std::complex<double> > : public float_grayscale_pixel_traits<double> {};
+ template <> struct pixel_traits<std::complex<long double> > : public float_grayscale_pixel_traits<long double> {};
+
+// ----------------------------------------------------------------------------------------
+
+ // The following is a bunch of conversion stuff for the assign_pixel function.
+
+ namespace assign_pixel_helpers
+ {
+
+ // -----------------------------
+ // all the same kind
+
+ template < typename P >
+ typename enable_if_c<pixel_traits<P>::grayscale>::type
+ assign(P& dest, const P& src)
+ {
+ dest = src;
+ }
+
+ // -----------------------------
+
+ template <typename T>
+ typename unsigned_type<T>::type make_unsigned (
+ const T& val
+ ) { return static_cast<typename unsigned_type<T>::type>(val); }
+
+ inline float make_unsigned(const float& val) { return val; }
+ inline double make_unsigned(const double& val) { return val; }
+ inline long double make_unsigned(const long double& val) { return val; }
+
+
+ template <typename T, typename P>
+ typename enable_if_c<pixel_traits<T>::is_unsigned == pixel_traits<P>::is_unsigned, bool>::type less_or_equal_to_max (
+ const P& p
+ )
+ /*!
+ ensures
+ - returns true if p is <= max value of T
+ !*/
+ {
+ return p <= pixel_traits<T>::max();
+ }
+
+ template <typename T, typename P>
+ typename enable_if_c<pixel_traits<T>::is_unsigned && !pixel_traits<P>::is_unsigned, bool>::type less_or_equal_to_max (
+ const P& p
+ )
+ {
+ if (p <= 0)
+ return true;
+ else if (make_unsigned(p) <= pixel_traits<T>::max())
+ return true;
+ else
+ return false;
+ }
+
+ template <typename T, typename P>
+ typename enable_if_c<!pixel_traits<T>::is_unsigned && pixel_traits<P>::is_unsigned, bool>::type less_or_equal_to_max (
+ const P& p
+ )
+ {
+ return p <= make_unsigned(pixel_traits<T>::max());
+ }
+
+ // -----------------------------
+
+ template <typename T, typename P>
+ typename enable_if_c<pixel_traits<P>::is_unsigned, bool >::type greater_or_equal_to_min (
+ const P&
+ ) { return true; }
+ /*!
+ ensures
+ - returns true if p is >= min value of T
+ !*/
+
+ template <typename T, typename P>
+ typename enable_if_c<!pixel_traits<P>::is_unsigned && pixel_traits<T>::is_unsigned, bool >::type greater_or_equal_to_min (
+ const P& p
+ )
+ {
+ return p >= 0;
+ }
+
+ template <typename T, typename P>
+ typename enable_if_c<!pixel_traits<P>::is_unsigned && !pixel_traits<T>::is_unsigned, bool >::type greater_or_equal_to_min (
+ const P& p
+ )
+ {
+ return p >= pixel_traits<T>::min();
+ }
+ // -----------------------------
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::grayscale && pixel_traits<P2>::grayscale>::type
+ assign(P1& dest, const P2& src)
+ {
+ /*
+ The reason for these weird comparison functions is to avoid getting compiler
+ warnings about comparing signed types to unsigned and stuff like that.
+ */
+
+ if (less_or_equal_to_max<P1>(src))
+ if (greater_or_equal_to_min<P1>(src))
+ dest = static_cast<P1>(src);
+ else
+ dest = pixel_traits<P1>::min();
+ else
+ dest = pixel_traits<P1>::max();
+ }
+
+ // -----------------------------
+ // -----------------------------
+ // -----------------------------
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::rgb && pixel_traits<P2>::rgb>::type
+ assign(P1& dest, const P2& src)
+ {
+ dest.red = src.red;
+ dest.green = src.green;
+ dest.blue = src.blue;
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::rgb_alpha && pixel_traits<P2>::rgb_alpha>::type
+ assign(P1& dest, const P2& src)
+ {
+ dest.red = src.red;
+ dest.green = src.green;
+ dest.blue = src.blue;
+ dest.alpha = src.alpha;
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::hsi && pixel_traits<P2>::hsi>::type
+ assign(P1& dest, const P2& src)
+ {
+ dest.h = src.h;
+ dest.s = src.s;
+ dest.i = src.i;
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::lab && pixel_traits<P2>::lab>::type
+ assign(P1& dest, const P2& src)
+ {
+ dest.l = src.l;
+ dest.a = src.a;
+ dest.b = src.b;
+ }
+
+ // -----------------------------
+ // dest is a grayscale
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::grayscale && pixel_traits<P2>::rgb>::type
+ assign(P1& dest, const P2& src)
+ {
+ const unsigned int temp = ((static_cast<unsigned int>(src.red) +
+ static_cast<unsigned int>(src.green) +
+ static_cast<unsigned int>(src.blue))/3);
+ assign_pixel(dest, temp);
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::grayscale && pixel_traits<P2>::rgb_alpha>::type
+ assign(P1& dest, const P2& src)
+ {
+
+ const unsigned char avg = static_cast<unsigned char>((static_cast<unsigned int>(src.red) +
+ static_cast<unsigned int>(src.green) +
+ static_cast<unsigned int>(src.blue))/3);
+
+ if (src.alpha == 255)
+ {
+ assign_pixel(dest, avg);
+ }
+ else
+ {
+ // perform this assignment using fixed point arithmetic:
+ // dest = src*(alpha/255) + dest*(1 - alpha/255);
+ // dest = src*(alpha/255) + dest*1 - dest*(alpha/255);
+ // dest = dest*1 + src*(alpha/255) - dest*(alpha/255);
+ // dest = dest*1 + (src - dest)*(alpha/255);
+ // dest += (src - dest)*(alpha/255);
+
+ int temp = avg;
+ // copy dest into dest_copy using assign_pixel to avoid potential
+ // warnings about implicit float to int warnings.
+ int dest_copy;
+ assign_pixel(dest_copy, dest);
+
+ temp -= dest_copy;
+
+ temp *= src.alpha;
+
+ temp /= 255;
+
+ assign_pixel(dest, temp+dest_copy);
+ }
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::grayscale && pixel_traits<P2>::hsi>::type
+ assign(P1& dest, const P2& src)
+ {
+ assign_pixel(dest, src.i);
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::grayscale && pixel_traits<P2>::lab>::type
+ assign(P1& dest, const P2& src)
+ {
+ assign_pixel(dest, src.l);
+ }
+
+
+ // -----------------------------
+
+ struct HSL
+ {
+ double h;
+ double s;
+ double l;
+ };
+
+ struct COLOUR
+ {
+ double r;
+ double g;
+ double b;
+ };
+
+ /*
+ I found this excellent bit of code for dealing with HSL spaces at
+ http://local.wasp.uwa.edu.au/~pbourke/colour/hsl/
+ */
+ /*
+ Calculate HSL from RGB
+ Hue is in degrees
+ Lightness is between 0 and 1
+ Saturation is between 0 and 1
+ */
+ inline HSL RGB2HSL(COLOUR c1)
+ {
+ double themin,themax,delta;
+ HSL c2;
+ using namespace std;
+
+ themin = std::min(c1.r,std::min(c1.g,c1.b));
+ themax = std::max(c1.r,std::max(c1.g,c1.b));
+ delta = themax - themin;
+ c2.l = (themin + themax) / 2;
+ c2.s = 0;
+ if (c2.l > 0 && c2.l < 1)
+ c2.s = delta / (c2.l < 0.5 ? (2*c2.l) : (2-2*c2.l));
+ c2.h = 0;
+ if (delta > 0) {
+ if (themax == c1.r && themax != c1.g)
+ c2.h += (c1.g - c1.b) / delta;
+ if (themax == c1.g && themax != c1.b)
+ c2.h += (2 + (c1.b - c1.r) / delta);
+ if (themax == c1.b && themax != c1.r)
+ c2.h += (4 + (c1.r - c1.g) / delta);
+ c2.h *= 60;
+ }
+ return(c2);
+ }
+
+ /*
+ Calculate RGB from HSL, reverse of RGB2HSL()
+ Hue is in degrees
+ Lightness is between 0 and 1
+ Saturation is between 0 and 1
+ */
+ inline COLOUR HSL2RGB(HSL c1)
+ {
+ COLOUR c2,sat,ctmp;
+ using namespace std;
+
+ if (c1.h < 120) {
+ sat.r = (120 - c1.h) / 60.0;
+ sat.g = c1.h / 60.0;
+ sat.b = 0;
+ } else if (c1.h < 240) {
+ sat.r = 0;
+ sat.g = (240 - c1.h) / 60.0;
+ sat.b = (c1.h - 120) / 60.0;
+ } else {
+ sat.r = (c1.h - 240) / 60.0;
+ sat.g = 0;
+ sat.b = (360 - c1.h) / 60.0;
+ }
+ sat.r = std::min(sat.r,1.0);
+ sat.g = std::min(sat.g,1.0);
+ sat.b = std::min(sat.b,1.0);
+
+ ctmp.r = 2 * c1.s * sat.r + (1 - c1.s);
+ ctmp.g = 2 * c1.s * sat.g + (1 - c1.s);
+ ctmp.b = 2 * c1.s * sat.b + (1 - c1.s);
+
+ if (c1.l < 0.5) {
+ c2.r = c1.l * ctmp.r;
+ c2.g = c1.l * ctmp.g;
+ c2.b = c1.l * ctmp.b;
+ } else {
+ c2.r = (1 - c1.l) * ctmp.r + 2 * c1.l - 1;
+ c2.g = (1 - c1.l) * ctmp.g + 2 * c1.l - 1;
+ c2.b = (1 - c1.l) * ctmp.b + 2 * c1.l - 1;
+ }
+
+ return(c2);
+ }
+
+ // -----------------------------
+
+ struct Lab
+ {
+ double l;
+ double a;
+ double b;
+ };
+ /*
+ Calculate Lab from RGB
+ L is between 0 and 100
+ a is between -128 and 127
+ b is between -128 and 127
+ RGB is between 0.0 and 1.0
+ */
+ inline Lab RGB2Lab(COLOUR c1)
+ {
+ Lab c2;
+ using namespace std;
+
+ double var_R = c1.r;
+ double var_G = c1.g;
+ double var_B = c1.b;
+
+ if (var_R > 0.04045) {
+ var_R = pow(((var_R + 0.055) / 1.055), 2.4);
+ } else {
+ var_R = var_R / 12.92;
+ }
+
+ if (var_G > 0.04045) {
+ var_G = pow(((var_G + 0.055) / 1.055), 2.4);
+ } else {
+ var_G = var_G / 12.92;
+ }
+
+ if (var_B > 0.04045) {
+ var_B = pow(((var_B + 0.055) / 1.055), 2.4);
+ } else {
+ var_B = var_B / 12.92;
+ }
+
+ var_R = var_R * 100;
+ var_G = var_G * 100;
+ var_B = var_B * 100;
+
+//Observer. = 2°, Illuminant = D65
+ double X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805;
+ double Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722;
+ double Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505;
+
+ double var_X = X / 95.047;
+ double var_Y = Y / 100.000;
+ double var_Z = Z / 108.883;
+
+ if (var_X > 0.008856) {
+ var_X = pow(var_X, (1.0 / 3));
+ }
+ else {
+ var_X = (7.787 * var_X) + (16.0 / 116);
+ }
+
+ if (var_Y > 0.008856) {
+ var_Y = pow(var_Y, (1.0 / 3));
+ }
+ else {
+ var_Y = (7.787 * var_Y) + (16.0 / 116);
+ }
+
+ if (var_Z > 0.008856) {
+ var_Z = pow(var_Z, (1.0 / 3));
+ }
+ else {
+ var_Z = (7.787 * var_Z) + (16.0 / 116);
+ }
+
+ //clamping
+ c2.l = max(0.0, (116.0 * var_Y) - 16);
+ c2.a = max(-128.0, min(127.0, 500.0 * (var_X - var_Y)));
+ c2.b = max(-128.0, min(127.0, 200.0 * (var_Y - var_Z)));
+
+ return c2;
+ }
+
+ /*
+ Calculate RGB from Lab, reverse of RGB2LAb()
+ L is between 0 and 100
+ a is between -128 and 127
+ b is between -128 and 127
+ RGB is between 0.0 and 1.0
+ */
+ inline COLOUR Lab2RGB(Lab c1) {
+ COLOUR c2;
+ using namespace std;
+
+ double var_Y = (c1.l + 16) / 116.0;
+ double var_X = (c1.a / 500.0) + var_Y;
+ double var_Z = var_Y - (c1.b / 200);
+
+ if (pow(var_Y, 3) > 0.008856) {
+ var_Y = pow(var_Y, 3);
+ } else {
+ var_Y = (var_Y - 16.0 / 116) / 7.787;
+ }
+
+ if (pow(var_X, 3) > 0.008856) {
+ var_X = pow(var_X, 3);
+ } else {
+ var_X = (var_X - 16.0 / 116) / 7.787;
+ }
+
+ if (pow(var_Z, 3) > 0.008856) {
+ var_Z = pow(var_Z, 3);
+ } else {
+ var_Z = (var_Z - 16.0 / 116) / 7.787;
+ }
+
+ double X = var_X * 95.047;
+ double Y = var_Y * 100.000;
+ double Z = var_Z * 108.883;
+
+ var_X = X / 100.0;
+ var_Y = Y / 100.0;
+ var_Z = Z / 100.0;
+
+ double var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986;
+ double var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415;
+ double var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570;
+
+ if (var_R > 0.0031308) {
+ var_R = 1.055 * pow(var_R, (1 / 2.4)) - 0.055;
+ } else {
+ var_R = 12.92 * var_R;
+ }
+
+ if (var_G > 0.0031308) {
+ var_G = 1.055 * pow(var_G, (1 / 2.4)) - 0.055;
+ } else {
+ var_G = 12.92 * var_G;
+ }
+
+ if (var_B > 0.0031308) {
+ var_B = 1.055 * pow(var_B, (1 / 2.4)) - 0.055;
+ } else {
+ var_B = 12.92 * var_B;
+ }
+
+ // clamping
+ c2.r = max(0.0, min(1.0, var_R));
+ c2.g = max(0.0, min(1.0, var_G));
+ c2.b = max(0.0, min(1.0, var_B));
+
+ return (c2);
+ }
+
+
+ // -----------------------------
+ // dest is a color rgb_pixel
+
+ template < typename P1 >
+ typename enable_if_c<pixel_traits<P1>::rgb>::type
+ assign(P1& dest, const unsigned char& src)
+ {
+ dest.red = src;
+ dest.green = src;
+ dest.blue = src;
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::rgb && pixel_traits<P2>::grayscale>::type
+ assign(P1& dest, const P2& src)
+ {
+ unsigned char p;
+ assign_pixel(p, src);
+ dest.red = p;
+ dest.green = p;
+ dest.blue = p;
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::rgb && pixel_traits<P2>::rgb_alpha>::type
+ assign(P1& dest, const P2& src)
+ {
+ if (src.alpha == 255)
+ {
+ dest.red = src.red;
+ dest.green = src.green;
+ dest.blue = src.blue;
+ }
+ else
+ {
+ // perform this assignment using fixed point arithmetic:
+ // dest = src*(alpha/255) + dest*(1 - alpha/255);
+ // dest = src*(alpha/255) + dest*1 - dest*(alpha/255);
+ // dest = dest*1 + src*(alpha/255) - dest*(alpha/255);
+ // dest = dest*1 + (src - dest)*(alpha/255);
+ // dest += (src - dest)*(alpha/255);
+
+ unsigned int temp_r = src.red;
+ unsigned int temp_g = src.green;
+ unsigned int temp_b = src.blue;
+
+ temp_r -= dest.red;
+ temp_g -= dest.green;
+ temp_b -= dest.blue;
+
+ temp_r *= src.alpha;
+ temp_g *= src.alpha;
+ temp_b *= src.alpha;
+
+ temp_r >>= 8;
+ temp_g >>= 8;
+ temp_b >>= 8;
+
+ dest.red += static_cast<unsigned char>(temp_r&0xFF);
+ dest.green += static_cast<unsigned char>(temp_g&0xFF);
+ dest.blue += static_cast<unsigned char>(temp_b&0xFF);
+ }
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::rgb && pixel_traits<P2>::hsi>::type
+ assign(P1& dest, const P2& src)
+ {
+ COLOUR c;
+ HSL h;
+ h.h = src.h;
+ h.h = h.h/255.0*360;
+ h.s = src.s/255.0;
+ h.l = src.i/255.0;
+ c = HSL2RGB(h);
+
+ dest.red = static_cast<unsigned char>(c.r*255.0 + 0.5);
+ dest.green = static_cast<unsigned char>(c.g*255.0 + 0.5);
+ dest.blue = static_cast<unsigned char>(c.b*255.0 + 0.5);
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::rgb && pixel_traits<P2>::lab>::type
+ assign(P1& dest, const P2& src)
+ {
+ COLOUR c;
+ Lab l;
+ l.l = (src.l/255.0)*100;
+ l.a = (src.a-128.0);
+ l.b = (src.b-128.0);
+ c = Lab2RGB(l);
+
+ dest.red = static_cast<unsigned char>(c.r*255.0 + 0.5);
+ dest.green = static_cast<unsigned char>(c.g*255.0 + 0.5);
+ dest.blue = static_cast<unsigned char>(c.b*255.0 + 0.5);
+ }
+
+
+ // -----------------------------
+ // dest is a color rgb_alpha_pixel
+
+ template < typename P1 >
+ typename enable_if_c<pixel_traits<P1>::rgb_alpha>::type
+ assign(P1& dest, const unsigned char& src)
+ {
+ dest.red = src;
+ dest.green = src;
+ dest.blue = src;
+ dest.alpha = 255;
+ }
+
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::rgb_alpha && pixel_traits<P2>::grayscale>::type
+ assign(P1& dest, const P2& src)
+ {
+ unsigned char p;
+ assign_pixel(p, src);
+
+ dest.red = p;
+ dest.green = p;
+ dest.blue = p;
+ dest.alpha = 255;
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::rgb_alpha && pixel_traits<P2>::rgb>::type
+ assign(P1& dest, const P2& src)
+ {
+ dest.red = src.red;
+ dest.green = src.green;
+ dest.blue = src.blue;
+ dest.alpha = 255;
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::rgb_alpha && pixel_traits<P2>::hsi>::type
+ assign(P1& dest, const P2& src)
+ {
+ COLOUR c;
+ HSL h;
+ h.h = src.h;
+ h.h = h.h/255.0*360;
+ h.s = src.s/255.0;
+ h.l = src.i/255.0;
+ c = HSL2RGB(h);
+
+ dest.red = static_cast<unsigned char>(c.r*255.0 + 0.5);
+ dest.green = static_cast<unsigned char>(c.g*255.0 + 0.5);
+ dest.blue = static_cast<unsigned char>(c.b*255.0 + 0.5);
+ dest.alpha = 255;
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::rgb_alpha && pixel_traits<P2>::lab>::type
+ assign(P1& dest, const P2& src)
+ {
+ COLOUR c;
+ Lab l;
+ l.l = (src.l/255.0)*100;
+ l.a = (src.a-128.0);
+ l.b = (src.b-128.0);
+ c = Lab2RGB(l);
+
+ dest.red = static_cast<unsigned char>(c.r * 255 + 0.5);
+ dest.green = static_cast<unsigned char>(c.g * 255 + 0.5);
+ dest.blue = static_cast<unsigned char>(c.b * 255 + 0.5);
+ dest.alpha = 255;
+ }
+ // -----------------------------
+ // dest is an hsi pixel
+
+ template < typename P1>
+ typename enable_if_c<pixel_traits<P1>::hsi>::type
+ assign(P1& dest, const unsigned char& src)
+ {
+ dest.h = 0;
+ dest.s = 0;
+ dest.i = src;
+ }
+
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::hsi && pixel_traits<P2>::grayscale>::type
+ assign(P1& dest, const P2& src)
+ {
+ dest.h = 0;
+ dest.s = 0;
+ assign_pixel(dest.i, src);
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::hsi && pixel_traits<P2>::rgb>::type
+ assign(P1& dest, const P2& src)
+ {
+ COLOUR c1;
+ HSL c2;
+ c1.r = src.red/255.0;
+ c1.g = src.green/255.0;
+ c1.b = src.blue/255.0;
+ c2 = RGB2HSL(c1);
+
+ dest.h = static_cast<unsigned char>(c2.h/360.0*255.0 + 0.5);
+ dest.s = static_cast<unsigned char>(c2.s*255.0 + 0.5);
+ dest.i = static_cast<unsigned char>(c2.l*255.0 + 0.5);
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::hsi && pixel_traits<P2>::rgb_alpha>::type
+ assign(P1& dest, const P2& src)
+ {
+ rgb_pixel temp;
+ // convert target hsi pixel to rgb
+ assign_pixel_helpers::assign(temp,dest);
+
+ // now assign the rgb_alpha value to our temp rgb pixel
+ assign_pixel_helpers::assign(temp,src);
+
+ // now we can just go assign the new rgb value to the
+ // hsi pixel
+ assign_pixel_helpers::assign(dest,temp);
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::hsi && pixel_traits<P2>::lab>::type
+ assign(P1& dest, const P2& src)
+ {
+ rgb_pixel temp;
+ // convert lab value to our temp rgb pixel
+ assign_pixel_helpers::assign(temp,src);
+ // now we can just go assign the new rgb value to the
+ // hsi pixel
+ assign_pixel_helpers::assign(dest,temp);
+ }
+
+ // -----------------------------
+ // dest is an lab pixel
+ template < typename P1>
+ typename enable_if_c<pixel_traits<P1>::lab>::type
+ assign(P1& dest, const unsigned char& src)
+ {
+ dest.a = 128;
+ dest.b = 128;
+ dest.l = src;
+ }
+
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::lab && pixel_traits<P2>::grayscale>::type
+ assign(P1& dest, const P2& src)
+ {
+ dest.a = 128;
+ dest.b = 128;
+ assign_pixel(dest.l, src);
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::lab && pixel_traits<P2>::rgb>::type
+ assign(P1& dest, const P2& src)
+ {
+ COLOUR c1;
+ Lab c2;
+ c1.r = src.red / 255.0;
+ c1.g = src.green / 255.0;
+ c1.b = src.blue / 255.0;
+ c2 = RGB2Lab(c1);
+
+ dest.l = static_cast<unsigned char>((c2.l / 100) * 255 + 0.5);
+ dest.a = static_cast<unsigned char>(c2.a + 128 + 0.5);
+ dest.b = static_cast<unsigned char>(c2.b + 128 + 0.5);
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::lab && pixel_traits<P2>::rgb_alpha>::type
+ assign(P1& dest, const P2& src)
+ {
+ rgb_pixel temp;
+ // convert target lab pixel to rgb
+ assign_pixel_helpers::assign(temp,dest);
+
+ // now assign the rgb_alpha value to our temp rgb pixel
+ assign_pixel_helpers::assign(temp,src);
+
+ // now we can just go assign the new rgb value to the
+ // lab pixel
+ assign_pixel_helpers::assign(dest,temp);
+ }
+
+ template < typename P1, typename P2 >
+ typename enable_if_c<pixel_traits<P1>::lab && pixel_traits<P2>::hsi>::type
+ assign(P1& dest, const P2& src)
+ {
+ rgb_pixel temp;
+
+ // convert hsi value to our temp rgb pixel
+ assign_pixel_helpers::assign(temp,src);
+
+ // now we can just go assign the new rgb value to the
+ // lab pixel
+ assign_pixel_helpers::assign(dest,temp);
+ }
+ }
+
+ // -----------------------------
+
+ template < typename P1, typename P2 >
+ inline void assign_pixel (
+ P1& dest,
+ const P2& src
+ ) { assign_pixel_helpers::assign(dest,src); }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename P,
+ typename T
+ >
+ inline typename enable_if_c<pixel_traits<P>::grayscale>::type assign_pixel_intensity_helper (
+ P& dest,
+ const T& new_intensity
+ )
+ {
+ assign_pixel(dest, new_intensity);
+ }
+
+ template <
+ typename P,
+ typename T
+ >
+ inline typename enable_if_c<pixel_traits<P>::grayscale == false &&
+ pixel_traits<P>::has_alpha>::type assign_pixel_intensity_helper (
+ P& dest,
+ const T& new_intensity
+ )
+ {
+ hsi_pixel p;
+ const unsigned long old_alpha = dest.alpha;
+ dest.alpha = 255;
+ rgb_pixel temp;
+ assign_pixel(temp, dest); // put dest into an rgb_pixel to avoid the somewhat complicated assign_pixel(hsi,rgb_alpha).
+ assign_pixel(p,temp);
+ assign_pixel(p.i, new_intensity);
+ assign_pixel(dest,p);
+ dest.alpha = old_alpha;
+ }
+
+ template <
+ typename P,
+ typename T
+ >
+ inline typename enable_if_c<pixel_traits<P>::grayscale == false &&
+ pixel_traits<P>::has_alpha == false>::type assign_pixel_intensity_helper (
+ P& dest,
+ const T& new_intensity
+ )
+ {
+ hsi_pixel p;
+ assign_pixel(p,dest);
+ assign_pixel(p.i, new_intensity);
+ assign_pixel(dest,p);
+ }
+
+ template <
+ typename P,
+ typename T
+ >
+ inline void assign_pixel_intensity (
+ P& dest,
+ const T& new_intensity
+ )
+ {
+ assign_pixel_intensity_helper(dest, new_intensity);
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename P
+ >
+ inline typename enable_if_c<pixel_traits<P>::grayscale, P>::type get_pixel_intensity_helper (
+ const P& src
+ )
+ {
+ return src;
+ }
+
+ template <
+ typename P
+ >
+ inline typename enable_if_c<pixel_traits<P>::grayscale == false&&
+ pixel_traits<P>::has_alpha,
+ typename pixel_traits<P>::basic_pixel_type>::type get_pixel_intensity_helper (
+ const P& src
+ )
+ {
+ P temp = src;
+ temp.alpha = 255;
+ typename pixel_traits<P>::basic_pixel_type p;
+ assign_pixel(p,temp);
+ return p;
+ }
+
+ template <
+ typename P
+ >
+ inline typename enable_if_c<pixel_traits<P>::grayscale == false&&
+ pixel_traits<P>::has_alpha == false,
+ typename pixel_traits<P>::basic_pixel_type>::type get_pixel_intensity_helper (
+ const P& src
+ )
+ {
+ typename pixel_traits<P>::basic_pixel_type p;
+ assign_pixel(p,src);
+ return p;
+ }
+
+ template <
+ typename P
+ >
+ inline typename pixel_traits<P>::basic_pixel_type get_pixel_intensity (
+ const P& src
+ )
+ {
+ return get_pixel_intensity_helper(src);
+ }
+
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+
+ inline void serialize (
+ const rgb_alpha_pixel& item,
+ std::ostream& out
+ )
+ {
+ try
+ {
+ serialize(item.red,out);
+ serialize(item.green,out);
+ serialize(item.blue,out);
+ serialize(item.alpha,out);
+ }
+ catch (serialization_error& e)
+ {
+ throw serialization_error(e.info + "\n while serializing object of type rgb_alpha_pixel");
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ inline void deserialize (
+ rgb_alpha_pixel& item,
+ std::istream& in
+ )
+ {
+ try
+ {
+ deserialize(item.red,in);
+ deserialize(item.green,in);
+ deserialize(item.blue,in);
+ deserialize(item.alpha,in);
+ }
+ catch (serialization_error& e)
+ {
+ throw serialization_error(e.info + "\n while deserializing object of type rgb_alpha_pixel");
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ inline void serialize (
+ const rgb_pixel& item,
+ std::ostream& out
+ )
+ {
+ try
+ {
+ serialize(item.red,out);
+ serialize(item.green,out);
+ serialize(item.blue,out);
+ }
+ catch (serialization_error& e)
+ {
+ throw serialization_error(e.info + "\n while serializing object of type rgb_pixel");
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ inline void deserialize (
+ rgb_pixel& item,
+ std::istream& in
+ )
+ {
+ try
+ {
+ deserialize(item.red,in);
+ deserialize(item.green,in);
+ deserialize(item.blue,in);
+ }
+ catch (serialization_error& e)
+ {
+ throw serialization_error(e.info + "\n while deserializing object of type rgb_pixel");
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ inline void serialize (
+ const bgr_pixel& item,
+ std::ostream& out
+ )
+ {
+ try
+ {
+ serialize(item.blue,out);
+ serialize(item.green,out);
+ serialize(item.red,out);
+ }
+ catch (serialization_error& e)
+ {
+ throw serialization_error(e.info + "\n while serializing object of type bgr_pixel");
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ inline void deserialize (
+ bgr_pixel& item,
+ std::istream& in
+ )
+ {
+ try
+ {
+ deserialize(item.blue,in);
+ deserialize(item.green,in);
+ deserialize(item.red,in);
+ }
+ catch (serialization_error& e)
+ {
+ throw serialization_error(e.info + "\n while deserializing object of type bgr_pixel");
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ inline void serialize (
+ const hsi_pixel& item,
+ std::ostream& out
+ )
+ {
+ try
+ {
+ serialize(item.h,out);
+ serialize(item.s,out);
+ serialize(item.i,out);
+ }
+ catch (serialization_error& e)
+ {
+ throw serialization_error(e.info + "\n while serializing object of type hsi_pixel");
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ inline void deserialize (
+ hsi_pixel& item,
+ std::istream& in
+ )
+ {
+ try
+ {
+ deserialize(item.h,in);
+ deserialize(item.s,in);
+ deserialize(item.i,in);
+ }
+ catch (serialization_error& e)
+ {
+ throw serialization_error(e.info + "\n while deserializing object of type hsi_pixel");
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ inline void serialize (
+ const lab_pixel& item,
+ std::ostream& out
+ )
+ {
+ try
+ {
+ serialize(item.l,out);
+ serialize(item.a,out);
+ serialize(item.b,out);
+ }
+ catch (serialization_error& e)
+ {
+ throw serialization_error(e.info + "\n while serializing object of type lab_pixel");
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ inline void deserialize (
+ lab_pixel& item,
+ std::istream& in
+ )
+ {
+ try
+ {
+ deserialize(item.l,in);
+ deserialize(item.a,in);
+ deserialize(item.b,in);
+ }
+ catch (serialization_error& e)
+ {
+ throw serialization_error(e.info + "\n while deserializing object of type lab_pixel");
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+}
+
+#endif // DLIB_PIXEl_
+