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 {
44  static_assert(
45  std::is_same<C1, C2>::value,
46  "default_color_converter_impl not specialized for given color spaces");
47 };
48 
51 template <typename C>
53  template <typename P1, typename P2>
54  void operator()(const P1& src, P2& dst) const {
55  static_for_each(src,dst,default_channel_converter());
56  }
57 };
58 
59 namespace detail {
60 
62 
63 // The default implementation of to_luminance uses float0..1 as the intermediate channel type
64 template <typename RedChannel, typename GreenChannel, typename BlueChannel, typename GrayChannelValue>
66  GrayChannelValue operator()(const RedChannel& red, const GreenChannel& green, const BlueChannel& blue) const {
67  return channel_convert<GrayChannelValue>(float32_t(
68  channel_convert<float32_t>(red )*0.30f +
69  channel_convert<float32_t>(green)*0.59f +
70  channel_convert<float32_t>(blue )*0.11f) );
71  }
72 };
73 
74 // performance specialization for unsigned char
75 template <typename GrayChannelValue>
76 struct rgb_to_luminance_fn<uint8_t,uint8_t,uint8_t, GrayChannelValue> {
77  GrayChannelValue operator()(uint8_t red, uint8_t green, uint8_t blue) const {
78  return channel_convert<GrayChannelValue>(uint8_t(
79  ((uint32_t(red )*4915 + uint32_t(green)*9667 + uint32_t(blue )*1802) + 8192) >> 14));
80  }
81 };
82 
83 template <typename GrayChannel, typename RedChannel, typename GreenChannel, typename BlueChannel>
84 typename channel_traits<GrayChannel>::value_type rgb_to_luminance(const RedChannel& red, const GreenChannel& green, const BlueChannel& blue) {
85  return rgb_to_luminance_fn<RedChannel,GreenChannel,BlueChannel,
86  typename channel_traits<GrayChannel>::value_type>()(red,green,blue);
87 }
88 
89 } // namespace detail
90 
93 template <>
94 struct default_color_converter_impl<gray_t,rgb_t> {
95  template <typename P1, typename P2>
96  void operator()(const P1& src, P2& dst) const {
97  get_color(dst,red_t()) =
98  channel_convert<typename color_element_type<P2, red_t >::type>(get_color(src,gray_color_t()));
99  get_color(dst,green_t())=
100  channel_convert<typename color_element_type<P2, green_t>::type>(get_color(src,gray_color_t()));
101  get_color(dst,blue_t()) =
102  channel_convert<typename color_element_type<P2, blue_t >::type>(get_color(src,gray_color_t()));
103  }
104 };
105 
108 template <>
109 struct default_color_converter_impl<gray_t,cmyk_t> {
110  template <typename P1, typename P2>
111  void operator()(const P1& src, P2& dst) const {
112  get_color(dst,cyan_t())=
113  channel_traits<typename color_element_type<P2, cyan_t >::type>::min_value();
114  get_color(dst,magenta_t())=
115  channel_traits<typename color_element_type<P2, magenta_t>::type>::min_value();
116  get_color(dst,yellow_t())=
117  channel_traits<typename color_element_type<P2, yellow_t >::type>::min_value();
118  get_color(dst,black_t())=
119  channel_convert<typename color_element_type<P2, black_t >::type>(get_color(src,gray_color_t()));
120  }
121 };
122 
125 template <>
126 struct default_color_converter_impl<rgb_t,gray_t> {
127  template <typename P1, typename P2>
128  void operator()(const P1& src, P2& dst) const {
129  get_color(dst,gray_color_t()) =
130  detail::rgb_to_luminance<typename color_element_type<P2,gray_color_t>::type>(
131  get_color(src,red_t()), get_color(src,green_t()), get_color(src,blue_t())
132  );
133  }
134 };
135 
136 
144 template <>
145 struct default_color_converter_impl<rgb_t,cmyk_t> {
146  template <typename P1, typename P2>
147  void operator()(const P1& src, P2& dst) const {
148  using T2 = typename channel_type<P2>::type;
149  get_color(dst,cyan_t()) = channel_invert(channel_convert<T2>(get_color(src,red_t()))); // c = 1 - r
150  get_color(dst,magenta_t()) = channel_invert(channel_convert<T2>(get_color(src,green_t()))); // m = 1 - g
151  get_color(dst,yellow_t()) = channel_invert(channel_convert<T2>(get_color(src,blue_t()))); // y = 1 - b
152  get_color(dst,black_t()) = (std::min)(get_color(dst,cyan_t()),
153  (std::min)(get_color(dst,magenta_t()),
154  get_color(dst,yellow_t()))); // k = minimum(c, m, y)
155  T2 x = channel_traits<T2>::max_value()-get_color(dst,black_t()); // x = 1 - k
156  if (x>0.0001f) {
157  float x1 = channel_traits<T2>::max_value()/float(x);
158  get_color(dst,cyan_t()) = (T2)((get_color(dst,cyan_t()) - get_color(dst,black_t()))*x1); // c = (c - k) / x
159  get_color(dst,magenta_t()) = (T2)((get_color(dst,magenta_t()) - get_color(dst,black_t()))*x1); // m = (m - k) / x
160  get_color(dst,yellow_t()) = (T2)((get_color(dst,yellow_t()) - get_color(dst,black_t()))*x1); // y = (y - k) / x
161  } else {
162  get_color(dst,cyan_t())=get_color(dst,magenta_t())=get_color(dst,yellow_t())=0;
163  }
164  }
165 };
166 
173 template <>
174 struct default_color_converter_impl<cmyk_t,rgb_t> {
175  template <typename P1, typename P2>
176  void operator()(const P1& src, P2& dst) const {
177  using T1 = typename channel_type<P1>::type;
178  get_color(dst,red_t()) =
179  channel_convert<typename color_element_type<P2,red_t>::type>(
180  channel_invert<T1>(
181  (std::min)(channel_traits<T1>::max_value(),
183  get_color(dst,green_t())=
184  channel_convert<typename color_element_type<P2,green_t>::type>(
185  channel_invert<T1>(
186  (std::min)(channel_traits<T1>::max_value(),
188  get_color(dst,blue_t()) =
189  channel_convert<typename color_element_type<P2,blue_t>::type>(
190  channel_invert<T1>(
191  (std::min)(channel_traits<T1>::max_value(),
193  }
194 };
195 
196 
201 template <>
202 struct default_color_converter_impl<cmyk_t,gray_t> {
203  template <typename P1, typename P2>
204  void operator()(const P1& src, P2& dst) const {
205  get_color(dst,gray_color_t())=
206  channel_convert<typename color_element_type<P2,gray_color_t>::type>(
209  detail::rgb_to_luminance<typename color_element_type<P1,black_t>::type>(
210  get_color(src,cyan_t()),
211  get_color(src,magenta_t()),
212  get_color(src,yellow_t())
213  )
214  ),
215  channel_invert(get_color(src,black_t()))));
216  }
217 };
218 
219 namespace detail {
220 
221 template <typename Pixel>
222 auto alpha_or_max_impl(Pixel const& p, std::true_type) -> typename channel_type<Pixel>::type
223 {
224  return get_color(p,alpha_t());
225 }
226 template <typename Pixel>
227 auto alpha_or_max_impl(Pixel const&, std::false_type) -> typename channel_type<Pixel>::type
228 {
229  return channel_traits<typename channel_type<Pixel>::type>::max_value();
230 }
231 
232 } // namespace detail
233 
234 // Returns max_value if the pixel has no alpha channel. Otherwise returns the alpha.
235 template <typename Pixel>
236 auto alpha_or_max(Pixel const& p) -> typename channel_type<Pixel>::type
237 {
238  return detail::alpha_or_max_impl(
239  p,
240  mp11::mp_contains<typename color_space_type<Pixel>::type, alpha_t>());
241 }
242 
243 
246 template <typename C1>
247 struct default_color_converter_impl<C1,rgba_t> {
248  template <typename P1, typename P2>
249  void operator()(const P1& src, P2& dst) const {
250  using T2 = typename channel_type<P2>::type;
253  get_color(dst,red_t()) =get_color(tmp,red_t());
254  get_color(dst,green_t())=get_color(tmp,green_t());
255  get_color(dst,blue_t()) =get_color(tmp,blue_t());
256  get_color(dst,alpha_t())=channel_convert<T2>(alpha_or_max(src));
257  }
258 };
259 
266 template <typename C2>
267 struct default_color_converter_impl<rgba_t,C2> {
268  template <typename P1, typename P2>
269  void operator()(const P1& src, P2& dst) const {
270  using T1 = typename channel_type<P1>::type;
275  ,dst);
276  }
277 };
278 
281 template <>
282 struct default_color_converter_impl<rgba_t,rgba_t> {
283  template <typename P1, typename P2>
284  void operator()(const P1& src, P2& dst) const {
285  static_for_each(src,dst,default_channel_converter());
286  }
287 };
288 
292 
296  template <typename SrcP, typename DstP>
297  void operator()(const SrcP& src,DstP& dst) const {
298  using SrcColorSpace = typename color_space_type<SrcP>::type;
299  using DstColorSpace = typename color_space_type<DstP>::type;
301  }
302 };
303 
308 template <typename SrcP, typename DstP>
309 inline void color_convert(const SrcP& src, DstP& dst) {
310  default_color_converter()(src,dst);
311 }
312 
313 } } // namespace boost::gil
314 
315 #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:309
red * .3 + green * .59 + blue * .11 + .5
Definition: color_convert.hpp:65
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:295