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 #include <type_traits>
24 
25 namespace boost { namespace gil {
26 
29 
30 // Forward-declare
31 template <typename P> struct channel_type;
32 
38 
41 template <typename C1, typename C2>
43 
46 template <typename C>
48  template <typename P1, typename P2>
49  void operator()(const P1& src, P2& dst) const {
50  static_for_each(src,dst,default_channel_converter());
51  }
52 };
53 
54 namespace detail {
55 
57 
58 // The default implementation of to_luminance uses float0..1 as the intermediate channel type
59 template <typename RedChannel, typename GreenChannel, typename BlueChannel, typename GrayChannelValue>
61  GrayChannelValue operator()(const RedChannel& red, const GreenChannel& green, const BlueChannel& blue) const {
62  return channel_convert<GrayChannelValue>(float32_t(
63  channel_convert<float32_t>(red )*0.30f +
64  channel_convert<float32_t>(green)*0.59f +
65  channel_convert<float32_t>(blue )*0.11f) );
66  }
67 };
68 
69 // performance specialization for unsigned char
70 template <typename GrayChannelValue>
71 struct rgb_to_luminance_fn<uint8_t,uint8_t,uint8_t, GrayChannelValue> {
72  GrayChannelValue operator()(uint8_t red, uint8_t green, uint8_t blue) const {
73  return channel_convert<GrayChannelValue>(uint8_t(
74  ((uint32_t(red )*4915 + uint32_t(green)*9667 + uint32_t(blue )*1802) + 8192) >> 14));
75  }
76 };
77 
78 template <typename GrayChannel, typename RedChannel, typename GreenChannel, typename BlueChannel>
79 typename channel_traits<GrayChannel>::value_type rgb_to_luminance(const RedChannel& red, const GreenChannel& green, const BlueChannel& blue) {
80  return rgb_to_luminance_fn<RedChannel,GreenChannel,BlueChannel,
81  typename channel_traits<GrayChannel>::value_type>()(red,green,blue);
82 }
83 
84 } // namespace detail
85 
88 template <>
89 struct default_color_converter_impl<gray_t,rgb_t> {
90  template <typename P1, typename P2>
91  void operator()(const P1& src, P2& dst) const {
92  get_color(dst,red_t()) =
93  channel_convert<typename color_element_type<P2, red_t >::type>(get_color(src,gray_color_t()));
94  get_color(dst,green_t())=
95  channel_convert<typename color_element_type<P2, green_t>::type>(get_color(src,gray_color_t()));
96  get_color(dst,blue_t()) =
97  channel_convert<typename color_element_type<P2, blue_t >::type>(get_color(src,gray_color_t()));
98  }
99 };
100 
103 template <>
104 struct default_color_converter_impl<gray_t,cmyk_t> {
105  template <typename P1, typename P2>
106  void operator()(const P1& src, P2& dst) const {
107  get_color(dst,cyan_t())=
108  channel_traits<typename color_element_type<P2, cyan_t >::type>::min_value();
109  get_color(dst,magenta_t())=
110  channel_traits<typename color_element_type<P2, magenta_t>::type>::min_value();
111  get_color(dst,yellow_t())=
112  channel_traits<typename color_element_type<P2, yellow_t >::type>::min_value();
113  get_color(dst,black_t())=
114  channel_convert<typename color_element_type<P2, black_t >::type>(get_color(src,gray_color_t()));
115  }
116 };
117 
120 template <>
121 struct default_color_converter_impl<rgb_t,gray_t> {
122  template <typename P1, typename P2>
123  void operator()(const P1& src, P2& dst) const {
124  get_color(dst,gray_color_t()) =
125  detail::rgb_to_luminance<typename color_element_type<P2,gray_color_t>::type>(
126  get_color(src,red_t()), get_color(src,green_t()), get_color(src,blue_t())
127  );
128  }
129 };
130 
131 
139 template <>
140 struct default_color_converter_impl<rgb_t,cmyk_t> {
141  template <typename P1, typename P2>
142  void operator()(const P1& src, P2& dst) const {
143  using T2 = typename channel_type<P2>::type;
144  get_color(dst,cyan_t()) = channel_invert(channel_convert<T2>(get_color(src,red_t()))); // c = 1 - r
145  get_color(dst,magenta_t()) = channel_invert(channel_convert<T2>(get_color(src,green_t()))); // m = 1 - g
146  get_color(dst,yellow_t()) = channel_invert(channel_convert<T2>(get_color(src,blue_t()))); // y = 1 - b
147  get_color(dst,black_t()) = (std::min)(get_color(dst,cyan_t()),
148  (std::min)(get_color(dst,magenta_t()),
149  get_color(dst,yellow_t()))); // k = minimum(c, m, y)
150  T2 x = channel_traits<T2>::max_value()-get_color(dst,black_t()); // x = 1 - k
151  if (x>0.0001f) {
152  float x1 = channel_traits<T2>::max_value()/float(x);
153  get_color(dst,cyan_t()) = (T2)((get_color(dst,cyan_t()) - get_color(dst,black_t()))*x1); // c = (c - k) / x
154  get_color(dst,magenta_t()) = (T2)((get_color(dst,magenta_t()) - get_color(dst,black_t()))*x1); // m = (m - k) / x
155  get_color(dst,yellow_t()) = (T2)((get_color(dst,yellow_t()) - get_color(dst,black_t()))*x1); // y = (y - k) / x
156  } else {
157  get_color(dst,cyan_t())=get_color(dst,magenta_t())=get_color(dst,yellow_t())=0;
158  }
159  }
160 };
161 
168 template <>
169 struct default_color_converter_impl<cmyk_t,rgb_t> {
170  template <typename P1, typename P2>
171  void operator()(const P1& src, P2& dst) const {
172  using T1 = typename channel_type<P1>::type;
173  get_color(dst,red_t()) =
174  channel_convert<typename color_element_type<P2,red_t>::type>(
175  channel_invert<T1>(
176  (std::min)(channel_traits<T1>::max_value(),
178  get_color(dst,green_t())=
179  channel_convert<typename color_element_type<P2,green_t>::type>(
180  channel_invert<T1>(
181  (std::min)(channel_traits<T1>::max_value(),
183  get_color(dst,blue_t()) =
184  channel_convert<typename color_element_type<P2,blue_t>::type>(
185  channel_invert<T1>(
186  (std::min)(channel_traits<T1>::max_value(),
188  }
189 };
190 
191 
196 template <>
197 struct default_color_converter_impl<cmyk_t,gray_t> {
198  template <typename P1, typename P2>
199  void operator()(const P1& src, P2& dst) const {
200  get_color(dst,gray_color_t())=
201  channel_convert<typename color_element_type<P2,gray_color_t>::type>(
204  detail::rgb_to_luminance<typename color_element_type<P1,black_t>::type>(
205  get_color(src,cyan_t()),
206  get_color(src,magenta_t()),
207  get_color(src,yellow_t())
208  )
209  ),
210  channel_invert(get_color(src,black_t()))));
211  }
212 };
213 
214 namespace detail {
215 
216 template <typename Pixel>
217 auto alpha_or_max_impl(Pixel const& p, std::true_type) -> typename channel_type<Pixel>::type
218 {
219  return get_color(p,alpha_t());
220 }
221 template <typename Pixel>
222 auto alpha_or_max_impl(Pixel const&, std::false_type) -> typename channel_type<Pixel>::type
223 {
224  return channel_traits<typename channel_type<Pixel>::type>::max_value();
225 }
226 
227 } // namespace detail
228 
229 // Returns max_value if the pixel has no alpha channel. Otherwise returns the alpha.
230 template <typename Pixel>
231 auto alpha_or_max(Pixel const& p) -> typename channel_type<Pixel>::type
232 {
233  return detail::alpha_or_max_impl(
234  p,
235  mp11::mp_contains<typename color_space_type<Pixel>::type, alpha_t>());
236 }
237 
238 
241 template <typename C1>
242 struct default_color_converter_impl<C1,rgba_t> {
243  template <typename P1, typename P2>
244  void operator()(const P1& src, P2& dst) const {
245  using T2 = typename channel_type<P2>::type;
248  get_color(dst,red_t()) =get_color(tmp,red_t());
249  get_color(dst,green_t())=get_color(tmp,green_t());
250  get_color(dst,blue_t()) =get_color(tmp,blue_t());
251  get_color(dst,alpha_t())=channel_convert<T2>(alpha_or_max(src));
252  }
253 };
254 
261 template <typename C2>
262 struct default_color_converter_impl<rgba_t,C2> {
263  template <typename P1, typename P2>
264  void operator()(const P1& src, P2& dst) const {
265  using T1 = typename channel_type<P1>::type;
270  ,dst);
271  }
272 };
273 
276 template <>
277 struct default_color_converter_impl<rgba_t,rgba_t> {
278  template <typename P1, typename P2>
279  void operator()(const P1& src, P2& dst) const {
280  static_for_each(src,dst,default_channel_converter());
281  }
282 };
283 
287 
291  template <typename SrcP, typename DstP>
292  void operator()(const SrcP& src,DstP& dst) const {
293  using SrcColorSpace = typename color_space_type<SrcP>::type;
294  using DstColorSpace = typename color_space_type<DstP>::type;
296  }
297 };
298 
303 template <typename SrcP, typename DstP>
304 inline void color_convert(const SrcP& src, DstP& dst) {
305  default_color_converter()(src,dst);
306 }
307 
308 } } // namespace boost::gil
309 
310 #endif
Magenta.
Definition: cmyk.hpp:25
channel_traits< Channel >::value_type channel_invert(Channel x)
Default implementation. Provide overloads for performance.
Definition: channel_algorithm.hpp:559
Represents a pixel value (a container of channels). Models: HomogeneousColorBaseValueConcept,...
Definition: metafunctions.hpp:23
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:28
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:539
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:190
Green.
Definition: rgb.hpp:27
Same as channel_converter, except it takes the destination channel by reference, which allows us to m...
Definition: channel_algorithm.hpp:460
Alpha.
Definition: rgba.hpp:22
Definition: color_convert.hpp:31
Color Convertion function object. To be specialized for every src/dst color space.
Definition: color_convert.hpp:42
Blue.
Definition: rgb.hpp:30
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:304
red * .3 + green * .59 + blue * .11 + .5
Definition: color_convert.hpp:60
Black.
Definition: cmyk.hpp:31
Red.
Definition: rgb.hpp:24
Gray.
Definition: gray.hpp:18
Cyan.
Definition: cmyk.hpp:22
class for color-converting one pixel to another
Definition: color_convert.hpp:290