color_convert.hppGo to the documentation of this file.00001 /* 00002 Copyright 2005-2007 Adobe Systems Incorporated 00003 00004 Use, modification and distribution are subject to the Boost Software License, 00005 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 00006 http://www.boost.org/LICENSE_1_0.txt). 00007 00008 See http://opensource.adobe.com/gil for most recent version including documentation. 00009 */ 00010 /*************************************************************************************************/ 00011 00012 #ifndef GIL_COLOR_CONVERT_HPP 00013 #define GIL_COLOR_CONVERT_HPP 00014 00026 00027 #include <functional> 00028 #include "gil_config.hpp" 00029 #include "channel_algorithm.hpp" 00030 #include "pixel.hpp" 00031 #include "gray.hpp" 00032 #include "rgb.hpp" 00033 #include "rgba.hpp" 00034 #include "cmyk.hpp" 00035 #include "metafunctions.hpp" 00036 #include "utilities.hpp" 00037 #include "color_base_algorithm.hpp" 00038 00039 namespace boost { namespace gil { 00040 00041 // Forward-declare 00042 template <typename P> struct channel_type; 00043 00049 00052 template <typename C1, typename C2> 00053 struct default_color_converter_impl {}; 00054 00057 template <typename C> 00058 struct default_color_converter_impl<C,C> { 00059 template <typename P1, typename P2> 00060 void operator()(const P1& src, P2& dst) const { 00061 static_for_each(src,dst,default_channel_converter()); 00062 } 00063 }; 00064 00065 namespace detail { 00066 00068 00069 // The default implementation of to_luminance uses float0..1 as the intermediate channel type 00070 template <typename RedChannel, typename GreenChannel, typename BlueChannel, typename GrayChannelValue> 00071 struct rgb_to_luminance_fn { 00072 GrayChannelValue operator()(const RedChannel& red, const GreenChannel& green, const BlueChannel& blue) const { 00073 return channel_convert<GrayChannelValue>( bits32f( 00074 channel_convert<bits32f>(red )*0.30f + 00075 channel_convert<bits32f>(green)*0.59f + 00076 channel_convert<bits32f>(blue )*0.11f) ); 00077 } 00078 }; 00079 00080 // performance specialization for unsigned char 00081 template <typename GrayChannelValue> 00082 struct rgb_to_luminance_fn<uint8_t,uint8_t,uint8_t, GrayChannelValue> { 00083 GrayChannelValue operator()(uint8_t red, uint8_t green, uint8_t blue) const { 00084 return channel_convert<GrayChannelValue>(uint8_t( 00085 ((uint32_t(red )*4915 + uint32_t(green)*9667 + uint32_t(blue )*1802) + 8192) >> 14)); 00086 } 00087 }; 00088 00089 template <typename GrayChannel, typename RedChannel, typename GreenChannel, typename BlueChannel> 00090 typename channel_traits<GrayChannel>::value_type rgb_to_luminance(const RedChannel& red, const GreenChannel& green, const BlueChannel& blue) { 00091 return rgb_to_luminance_fn<RedChannel,GreenChannel,BlueChannel, 00092 typename channel_traits<GrayChannel>::value_type>()(red,green,blue); 00093 } 00094 00095 } // namespace detail 00096 00099 template <> 00100 struct default_color_converter_impl<gray_t,rgb_t> { 00101 template <typename P1, typename P2> 00102 void operator()(const P1& src, P2& dst) const { 00103 get_color(dst,red_t()) = 00104 channel_convert<typename color_element_type<P2, red_t >::type>(get_color(src,gray_color_t())); 00105 get_color(dst,green_t())= 00106 channel_convert<typename color_element_type<P2, green_t>::type>(get_color(src,gray_color_t())); 00107 get_color(dst,blue_t()) = 00108 channel_convert<typename color_element_type<P2, blue_t >::type>(get_color(src,gray_color_t())); 00109 } 00110 }; 00111 00114 template <> 00115 struct default_color_converter_impl<gray_t,cmyk_t> { 00116 template <typename P1, typename P2> 00117 void operator()(const P1& src, P2& dst) const { 00118 get_color(dst,cyan_t())= 00119 channel_traits<typename color_element_type<P2, cyan_t >::type>::min_value(); 00120 get_color(dst,magenta_t())= 00121 channel_traits<typename color_element_type<P2, magenta_t>::type>::min_value(); 00122 get_color(dst,yellow_t())= 00123 channel_traits<typename color_element_type<P2, yellow_t >::type>::min_value(); 00124 get_color(dst,black_t())= 00125 channel_convert<typename color_element_type<P2, black_t >::type>(get_color(src,gray_color_t())); 00126 } 00127 }; 00128 00131 template <> 00132 struct default_color_converter_impl<rgb_t,gray_t> { 00133 template <typename P1, typename P2> 00134 void operator()(const P1& src, P2& dst) const { 00135 get_color(dst,gray_color_t()) = 00136 detail::rgb_to_luminance<typename color_element_type<P2,gray_color_t>::type>( 00137 get_color(src,red_t()), get_color(src,green_t()), get_color(src,blue_t()) 00138 ); 00139 } 00140 }; 00141 00142 00150 template <> 00151 struct default_color_converter_impl<rgb_t,cmyk_t> { 00152 template <typename P1, typename P2> 00153 void operator()(const P1& src, P2& dst) const { 00154 typedef typename channel_type<P2>::type T2; 00155 get_color(dst,cyan_t()) = channel_invert(channel_convert<T2>(get_color(src,red_t()))); // c = 1 - r 00156 get_color(dst,magenta_t()) = channel_invert(channel_convert<T2>(get_color(src,green_t()))); // m = 1 - g 00157 get_color(dst,yellow_t()) = channel_invert(channel_convert<T2>(get_color(src,blue_t()))); // y = 1 - b 00158 get_color(dst,black_t()) = (std::min)(get_color(dst,cyan_t()), 00159 (std::min)(get_color(dst,magenta_t()), 00160 get_color(dst,yellow_t()))); // k = minimum(c, m, y) 00161 T2 x = channel_traits<T2>::max_value()-get_color(dst,black_t()); // x = 1 - k 00162 if (x>0.0001f) { 00163 float x1 = channel_traits<T2>::max_value()/float(x); 00164 get_color(dst,cyan_t()) = (T2)((get_color(dst,cyan_t()) - get_color(dst,black_t()))*x1); // c = (c - k) / x 00165 get_color(dst,magenta_t()) = (T2)((get_color(dst,magenta_t()) - get_color(dst,black_t()))*x1); // m = (m - k) / x 00166 get_color(dst,yellow_t()) = (T2)((get_color(dst,yellow_t()) - get_color(dst,black_t()))*x1); // y = (y - k) / x 00167 } else { 00168 get_color(dst,cyan_t())=get_color(dst,magenta_t())=get_color(dst,yellow_t())=0; 00169 } 00170 } 00171 }; 00172 00179 template <> 00180 struct default_color_converter_impl<cmyk_t,rgb_t> { 00181 template <typename P1, typename P2> 00182 void operator()(const P1& src, P2& dst) const { 00183 typedef typename channel_type<P1>::type T1; 00184 get_color(dst,red_t()) = 00185 channel_convert<typename color_element_type<P2,red_t>::type>( 00186 channel_invert<T1>( 00187 (std::min)(channel_traits<T1>::max_value(), 00188 T1(get_color(src,cyan_t())*channel_invert(get_color(src,black_t()))+get_color(src,black_t()))))); 00189 get_color(dst,green_t())= 00190 channel_convert<typename color_element_type<P2,green_t>::type>( 00191 channel_invert<T1>( 00192 (std::min)(channel_traits<T1>::max_value(), 00193 T1(get_color(src,magenta_t())*channel_invert(get_color(src,black_t()))+get_color(src,black_t()))))); 00194 get_color(dst,blue_t()) = 00195 channel_convert<typename color_element_type<P2,blue_t>::type>( 00196 channel_invert<T1>( 00197 (std::min)(channel_traits<T1>::max_value(), 00198 T1(get_color(src,yellow_t())*channel_invert(get_color(src,black_t()))+get_color(src,black_t()))))); 00199 } 00200 }; 00201 00202 00207 template <> 00208 struct default_color_converter_impl<cmyk_t,gray_t> { 00209 template <typename P1, typename P2> 00210 void operator()(const P1& src, P2& dst) const { 00211 get_color(dst,gray_color_t())= 00212 channel_convert<typename color_element_type<P2,gray_t>::type>( 00213 channel_multiply( 00214 channel_invert( 00215 detail::rgb_to_luminance<typename color_element_type<P1,black_t>::type>( 00216 get_color(src,cyan_t()), 00217 get_color(src,magenta_t()), 00218 get_color(src,yellow_t()) 00219 ) 00220 ), 00221 channel_invert(get_color(src,black_t())))); 00222 } 00223 }; 00224 00225 namespace detail { 00226 template <typename Pixel> 00227 typename channel_type<Pixel>::type alpha_or_max_impl(const Pixel& p, mpl::true_) { 00228 return get_color(p,alpha_t()); 00229 } 00230 template <typename Pixel> 00231 typename channel_type<Pixel>::type alpha_or_max_impl(const Pixel& , mpl::false_) { 00232 return channel_traits<typename channel_type<Pixel>::type>::max_value(); 00233 } 00234 } // namespace detail 00235 00236 // Returns max_value if the pixel has no alpha channel. Otherwise returns the alpha. 00237 template <typename Pixel> 00238 typename channel_type<Pixel>::type alpha_or_max(const Pixel& p) { 00239 return detail::alpha_or_max_impl(p, mpl::contains<typename color_space_type<Pixel>::type,alpha_t>()); 00240 } 00241 00242 00245 template <typename C1> 00246 struct default_color_converter_impl<C1,rgba_t> { 00247 template <typename P1, typename P2> 00248 void operator()(const P1& src, P2& dst) const { 00249 typedef typename channel_type<P2>::type T2; 00250 pixel<T2,rgb_layout_t> tmp; 00251 default_color_converter_impl<C1,rgb_t>()(src,tmp); 00252 get_color(dst,red_t()) =get_color(tmp,red_t()); 00253 get_color(dst,green_t())=get_color(tmp,green_t()); 00254 get_color(dst,blue_t()) =get_color(tmp,blue_t()); 00255 get_color(dst,alpha_t())=channel_convert<T2>(alpha_or_max(src)); 00256 } 00257 }; 00258 00265 template <typename C2> 00266 struct default_color_converter_impl<rgba_t,C2> { 00267 template <typename P1, typename P2> 00268 void operator()(const P1& src, P2& dst) const { 00269 typedef typename channel_type<P1>::type T1; 00270 default_color_converter_impl<rgb_t,C2>()( 00271 pixel<T1,rgb_layout_t>(channel_multiply(get_color(src,red_t()), get_color(src,alpha_t())), 00272 channel_multiply(get_color(src,green_t()),get_color(src,alpha_t())), 00273 channel_multiply(get_color(src,blue_t()), get_color(src,alpha_t()))) 00274 ,dst); 00275 } 00276 }; 00277 00280 template <> 00281 struct default_color_converter_impl<rgba_t,rgba_t> { 00282 template <typename P1, typename P2> 00283 void operator()(const P1& src, P2& dst) const { 00284 static_for_each(src,dst,default_channel_converter()); 00285 } 00286 }; 00287 00291 00294 struct default_color_converter { 00295 template <typename SrcP, typename DstP> 00296 void operator()(const SrcP& src,DstP& dst) const { 00297 typedef typename color_space_type<SrcP>::type SrcColorSpace; 00298 typedef typename color_space_type<DstP>::type DstColorSpace; 00299 default_color_converter_impl<SrcColorSpace,DstColorSpace>()(src,dst); 00300 } 00301 }; 00302 00307 template <typename SrcP, typename DstP> 00308 inline void color_convert(const SrcP& src, DstP& dst) { 00309 default_color_converter()(src,dst); 00310 } 00311 00312 } } // namespace boost::gil 00313 00314 #endif Generated on Sat May 2 13:50:13 2009 for Generic Image Library by 1.5.6 |