Boost GIL


color_convert.hpp
1 //
2 // Copyright 2005-2007 Adobe Systems Incorporated
3 //
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
7 //
8 #ifndef BOOST_GIL_COLOR_CONVERT_HPP
9 #define BOOST_GIL_COLOR_CONVERT_HPP
10 
11 #include <boost/gil/channel_algorithm.hpp>
12 #include <boost/gil/cmyk.hpp>
13 #include <boost/gil/color_base_algorithm.hpp>
14 #include <boost/gil/gray.hpp>
15 #include <boost/gil/metafunctions.hpp>
16 #include <boost/gil/pixel.hpp>
17 #include <boost/gil/rgb.hpp>
18 #include <boost/gil/rgba.hpp>
19 #include <boost/gil/utilities.hpp>
20 
21 #include <algorithm>
22 #include <functional>
23 
24 namespace boost { namespace gil {
25 
28 
29 // Forward-declare
30 template <typename P> struct channel_type;
31 
37 
40 template <typename C1, typename C2>
42 
45 template <typename C>
47  template <typename P1, typename P2>
48  void operator()(const P1& src, P2& dst) const {
49  static_for_each(src,dst,default_channel_converter());
50  }
51 };
52 
53 namespace detail {
54 
56 
57 // The default implementation of to_luminance uses float0..1 as the intermediate channel type
58 template <typename RedChannel, typename GreenChannel, typename BlueChannel, typename GrayChannelValue>
60  GrayChannelValue operator()(const RedChannel& red, const GreenChannel& green, const BlueChannel& blue) const {
61  return channel_convert<GrayChannelValue>(float32_t(
62  channel_convert<float32_t>(red )*0.30f +
63  channel_convert<float32_t>(green)*0.59f +
64  channel_convert<float32_t>(blue )*0.11f) );
65  }
66 };
67 
68 // performance specialization for unsigned char
69 template <typename GrayChannelValue>
70 struct rgb_to_luminance_fn<uint8_t,uint8_t,uint8_t, GrayChannelValue> {
71  GrayChannelValue operator()(uint8_t red, uint8_t green, uint8_t blue) const {
72  return channel_convert<GrayChannelValue>(uint8_t(
73  ((uint32_t(red )*4915 + uint32_t(green)*9667 + uint32_t(blue )*1802) + 8192) >> 14));
74  }
75 };
76 
77 template <typename GrayChannel, typename RedChannel, typename GreenChannel, typename BlueChannel>
78 typename channel_traits<GrayChannel>::value_type rgb_to_luminance(const RedChannel& red, const GreenChannel& green, const BlueChannel& blue) {
79  return rgb_to_luminance_fn<RedChannel,GreenChannel,BlueChannel,
80  typename channel_traits<GrayChannel>::value_type>()(red,green,blue);
81 }
82 
83 } // namespace detail
84 
87 template <>
88 struct default_color_converter_impl<gray_t,rgb_t> {
89  template <typename P1, typename P2>
90  void operator()(const P1& src, P2& dst) const {
91  get_color(dst,red_t()) =
92  channel_convert<typename color_element_type<P2, red_t >::type>(get_color(src,gray_color_t()));
93  get_color(dst,green_t())=
94  channel_convert<typename color_element_type<P2, green_t>::type>(get_color(src,gray_color_t()));
95  get_color(dst,blue_t()) =
96  channel_convert<typename color_element_type<P2, blue_t >::type>(get_color(src,gray_color_t()));
97  }
98 };
99 
102 template <>
103 struct default_color_converter_impl<gray_t,cmyk_t> {
104  template <typename P1, typename P2>
105  void operator()(const P1& src, P2& dst) const {
106  get_color(dst,cyan_t())=
107  channel_traits<typename color_element_type<P2, cyan_t >::type>::min_value();
108  get_color(dst,magenta_t())=
109  channel_traits<typename color_element_type<P2, magenta_t>::type>::min_value();
110  get_color(dst,yellow_t())=
111  channel_traits<typename color_element_type<P2, yellow_t >::type>::min_value();
112  get_color(dst,black_t())=
113  channel_convert<typename color_element_type<P2, black_t >::type>(get_color(src,gray_color_t()));
114  }
115 };
116 
119 template <>
120 struct default_color_converter_impl<rgb_t,gray_t> {
121  template <typename P1, typename P2>
122  void operator()(const P1& src, P2& dst) const {
123  get_color(dst,gray_color_t()) =
124  detail::rgb_to_luminance<typename color_element_type<P2,gray_color_t>::type>(
125  get_color(src,red_t()), get_color(src,green_t()), get_color(src,blue_t())
126  );
127  }
128 };
129 
130 
138 template <>
139 struct default_color_converter_impl<rgb_t,cmyk_t> {
140  template <typename P1, typename P2>
141  void operator()(const P1& src, P2& dst) const {
142  using T2 = typename channel_type<P2>::type;
143  get_color(dst,cyan_t()) = channel_invert(channel_convert<T2>(get_color(src,red_t()))); // c = 1 - r
144  get_color(dst,magenta_t()) = channel_invert(channel_convert<T2>(get_color(src,green_t()))); // m = 1 - g
145  get_color(dst,yellow_t()) = channel_invert(channel_convert<T2>(get_color(src,blue_t()))); // y = 1 - b
146  get_color(dst,black_t()) = (std::min)(get_color(dst,cyan_t()),
147  (std::min)(get_color(dst,magenta_t()),
148  get_color(dst,yellow_t()))); // k = minimum(c, m, y)
149  T2 x = channel_traits<T2>::max_value()-get_color(dst,black_t()); // x = 1 - k
150  if (x>0.0001f) {
151  float x1 = channel_traits<T2>::max_value()/float(x);
152  get_color(dst,cyan_t()) = (T2)((get_color(dst,cyan_t()) - get_color(dst,black_t()))*x1); // c = (c - k) / x
153  get_color(dst,magenta_t()) = (T2)((get_color(dst,magenta_t()) - get_color(dst,black_t()))*x1); // m = (m - k) / x
154  get_color(dst,yellow_t()) = (T2)((get_color(dst,yellow_t()) - get_color(dst,black_t()))*x1); // y = (y - k) / x
155  } else {
156  get_color(dst,cyan_t())=get_color(dst,magenta_t())=get_color(dst,yellow_t())=0;
157  }
158  }
159 };
160 
167 template <>
168 struct default_color_converter_impl<cmyk_t,rgb_t> {
169  template <typename P1, typename P2>
170  void operator()(const P1& src, P2& dst) const {
171  using T1 = typename channel_type<P1>::type;
172  get_color(dst,red_t()) =
173  channel_convert<typename color_element_type<P2,red_t>::type>(
174  channel_invert<T1>(
175  (std::min)(channel_traits<T1>::max_value(),
177  get_color(dst,green_t())=
178  channel_convert<typename color_element_type<P2,green_t>::type>(
179  channel_invert<T1>(
180  (std::min)(channel_traits<T1>::max_value(),
182  get_color(dst,blue_t()) =
183  channel_convert<typename color_element_type<P2,blue_t>::type>(
184  channel_invert<T1>(
185  (std::min)(channel_traits<T1>::max_value(),
187  }
188 };
189 
190 
195 template <>
196 struct default_color_converter_impl<cmyk_t,gray_t> {
197  template <typename P1, typename P2>
198  void operator()(const P1& src, P2& dst) const {
199  get_color(dst,gray_color_t())=
200  channel_convert<typename color_element_type<P2,gray_color_t>::type>(
203  detail::rgb_to_luminance<typename color_element_type<P1,black_t>::type>(
204  get_color(src,cyan_t()),
205  get_color(src,magenta_t()),
206  get_color(src,yellow_t())
207  )
208  ),
209  channel_invert(get_color(src,black_t()))));
210  }
211 };
212 
213 namespace detail {
214 template <typename Pixel>
215 typename channel_type<Pixel>::type alpha_or_max_impl(const Pixel& p, mpl::true_) {
216  return get_color(p,alpha_t());
217 }
218 template <typename Pixel>
219 typename channel_type<Pixel>::type alpha_or_max_impl(const Pixel& , mpl::false_) {
220  return channel_traits<typename channel_type<Pixel>::type>::max_value();
221 }
222 } // namespace detail
223 
224 // Returns max_value if the pixel has no alpha channel. Otherwise returns the alpha.
225 template <typename Pixel>
226 typename channel_type<Pixel>::type alpha_or_max(const Pixel& p) {
227  return detail::alpha_or_max_impl(p, mpl::contains<typename color_space_type<Pixel>::type,alpha_t>());
228 }
229 
230 
233 template <typename C1>
234 struct default_color_converter_impl<C1,rgba_t> {
235  template <typename P1, typename P2>
236  void operator()(const P1& src, P2& dst) const {
237  using T2 = typename channel_type<P2>::type;
240  get_color(dst,red_t()) =get_color(tmp,red_t());
241  get_color(dst,green_t())=get_color(tmp,green_t());
242  get_color(dst,blue_t()) =get_color(tmp,blue_t());
243  get_color(dst,alpha_t())=channel_convert<T2>(alpha_or_max(src));
244  }
245 };
246 
253 template <typename C2>
254 struct default_color_converter_impl<rgba_t,C2> {
255  template <typename P1, typename P2>
256  void operator()(const P1& src, P2& dst) const {
257  using T1 = typename channel_type<P1>::type;
262  ,dst);
263  }
264 };
265 
268 template <>
269 struct default_color_converter_impl<rgba_t,rgba_t> {
270  template <typename P1, typename P2>
271  void operator()(const P1& src, P2& dst) const {
272  static_for_each(src,dst,default_channel_converter());
273  }
274 };
275 
279 
283  template <typename SrcP, typename DstP>
284  void operator()(const SrcP& src,DstP& dst) const {
285  using SrcColorSpace = typename color_space_type<SrcP>::type;
286  using DstColorSpace = typename color_space_type<DstP>::type;
288  }
289 };
290 
295 template <typename SrcP, typename DstP>
296 inline void color_convert(const SrcP& src, DstP& dst) {
297  default_color_converter()(src,dst);
298 }
299 
300 } } // namespace boost::gil
301 
302 #endif
Magenta.
Definition: cmyk.hpp:27
channel_traits< Channel >::value_type channel_invert(Channel x)
Default implementation. Provide overloads for performance.
Definition: channel_algorithm.hpp:505
Definition: algorithm.hpp:30
Represents a pixel value (a container of channels). Models: HomogeneousColorBaseValueConcept, PixelValueConcept, HomogeneousPixelBasedConcept.
Definition: metafunctions.hpp:31
scoped_channel_value< float, float_point_zero< float >, float_point_one< float > > float32_t
32-bit floating point channel type with range [0.0f ... 1.0f]. Models ChannelValueConcept ...
Definition: typedefs.hpp:124
Yellow.
Definition: cmyk.hpp:30
channel_traits< Channel >::value_type channel_multiply(Channel a, Channel b)
A function multiplying two channels. result = a * b / max_value.
Definition: channel_algorithm.hpp:485
color_element_reference_type< ColorBase, Color >::type get_color(ColorBase &cb, Color=Color())
Mutable accessor to the element associated with a given color name.
Definition: color_base_algorithm.hpp:193
Green.
Definition: rgb.hpp:28
Same as channel_converter, except it takes the destination channel by reference, which allows us to m...
Definition: channel_algorithm.hpp:406
Alpha.
Definition: rgba.hpp:23
Definition: color_convert.hpp:30
Color Convertion function object. To be specialized for every src/dst color space.
Definition: color_convert.hpp:41
Blue.
Definition: rgb.hpp:31
void color_convert(const SrcP &src, DstP &dst)
helper function for converting one pixel to another using GIL default color-converters where ScrP mod...
Definition: color_convert.hpp:296
red * .3 + green * .59 + blue * .11 + .5
Definition: color_convert.hpp:59
Black.
Definition: cmyk.hpp:33
Red.
Definition: rgb.hpp:25
Gray.
Definition: gray.hpp:21
Cyan.
Definition: cmyk.hpp:24
class for color-converting one pixel to another
Definition: color_convert.hpp:282