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 "image_view_factory.hpp" 00036 #include "metafunctions.hpp" 00037 #include "utilities.hpp" 00038 #include "color_base_algorithm.hpp" 00039 00040 namespace boost { namespace gil { 00041 00042 // Forward-declare 00043 template <typename P> struct channel_type; 00044 00050 00053 template <typename C1, typename C2> 00054 struct default_color_converter_impl {}; 00055 00058 template <typename C> 00059 struct default_color_converter_impl<C,C> { 00060 template <typename P1, typename P2> 00061 void operator()(const P1& src, P2& dst) const { 00062 static_for_each(src,dst,default_channel_converter()); 00063 } 00064 }; 00065 00066 namespace detail { 00067 00069 00070 // The default implementation of to_luminance uses float0..1 as the intermediate channel type 00071 template <typename RedChannel, typename GreenChannel, typename BlueChannel, typename GrayChannelValue> 00072 struct rgb_to_luminance_fn { 00073 GrayChannelValue operator()(const RedChannel& red, const GreenChannel& green, const BlueChannel& blue) const { 00074 return channel_convert<GrayChannelValue>( bits32f( 00075 channel_convert<bits32f>(red )*0.30f + 00076 channel_convert<bits32f>(green)*0.59f + 00077 channel_convert<bits32f>(blue )*0.11f) ); 00078 } 00079 }; 00080 00081 // performance specialization for unsigned char 00082 template <typename GrayChannelValue> 00083 struct rgb_to_luminance_fn<uint8_t,uint8_t,uint8_t, GrayChannelValue> { 00084 GrayChannelValue operator()(uint8_t red, uint8_t green, uint8_t blue) const { 00085 return channel_convert<GrayChannelValue>(uint8_t( 00086 ((uint32_t(red )*4915 + uint32_t(green)*9667 + uint32_t(blue )*1802) + 8192) >> 14)); 00087 } 00088 }; 00089 00090 template <typename GrayChannel, typename RedChannel, typename GreenChannel, typename BlueChannel> 00091 typename channel_traits<GrayChannel>::value_type rgb_to_luminance(const RedChannel& red, const GreenChannel& green, const BlueChannel& blue) { 00092 return rgb_to_luminance_fn<RedChannel,GreenChannel,BlueChannel, 00093 typename channel_traits<GrayChannel>::value_type>()(red,green,blue); 00094 } 00095 00096 } // namespace detail 00097 00100 template <> 00101 struct default_color_converter_impl<gray_t,rgb_t> { 00102 template <typename P1, typename P2> 00103 void operator()(const P1& src, P2& dst) const { 00104 get_color(dst,red_t()) = 00105 channel_convert<typename color_element_type<P2, red_t >::type>(get_color(src,gray_color_t())); 00106 get_color(dst,green_t())= 00107 channel_convert<typename color_element_type<P2, green_t>::type>(get_color(src,gray_color_t())); 00108 get_color(dst,blue_t()) = 00109 channel_convert<typename color_element_type<P2, blue_t >::type>(get_color(src,gray_color_t())); 00110 } 00111 }; 00112 00115 template <> 00116 struct default_color_converter_impl<gray_t,cmyk_t> { 00117 template <typename P1, typename P2> 00118 void operator()(const P1& src, P2& dst) const { 00119 get_color(dst,cyan_t())= 00120 channel_traits<typename color_element_type<P2, cyan_t >::type>::min_value(); 00121 get_color(dst,magenta_t())= 00122 channel_traits<typename color_element_type<P2, magenta_t>::type>::min_value(); 00123 get_color(dst,yellow_t())= 00124 channel_traits<typename color_element_type<P2, yellow_t >::type>::min_value(); 00125 get_color(dst,black_t())= 00126 channel_convert<typename color_element_type<P2, black_t >::type>(get_color(src,gray_color_t())); 00127 } 00128 }; 00129 00132 template <> 00133 struct default_color_converter_impl<rgb_t,gray_t> { 00134 template <typename P1, typename P2> 00135 void operator()(const P1& src, P2& dst) const { 00136 get_color(dst,gray_color_t()) = 00137 detail::rgb_to_luminance<typename color_element_type<P2,gray_color_t>::type>( 00138 get_color(src,red_t()), get_color(src,green_t()), get_color(src,blue_t()) 00139 ); 00140 } 00141 }; 00142 00143 00151 template <> 00152 struct default_color_converter_impl<rgb_t,cmyk_t> { 00153 template <typename P1, typename P2> 00154 void operator()(const P1& src, P2& dst) const { 00155 typedef typename channel_type<P2>::type T2; 00156 get_color(dst,cyan_t()) = channel_invert(channel_convert<T2>(get_color(src,red_t()))); // c = 1 - r 00157 get_color(dst,magenta_t()) = channel_invert(channel_convert<T2>(get_color(src,green_t()))); // m = 1 - g 00158 get_color(dst,yellow_t()) = channel_invert(channel_convert<T2>(get_color(src,blue_t()))); // y = 1 - b 00159 get_color(dst,black_t()) = (std::min)(get_color(dst,cyan_t()), 00160 (std::min)(get_color(dst,magenta_t()), 00161 get_color(dst,yellow_t()))); // k = minimum(c, m, y) 00162 T2 x = channel_traits<T2>::max_value()-get_color(dst,black_t()); // x = 1 - k 00163 if (x>0.0001f) { 00164 float x1 = channel_traits<T2>::max_value()/float(x); 00165 get_color(dst,cyan_t()) = (T2)((get_color(dst,cyan_t()) - get_color(dst,black_t()))*x1); // c = (c - k) / x 00166 get_color(dst,magenta_t()) = (T2)((get_color(dst,magenta_t()) - get_color(dst,black_t()))*x1); // m = (m - k) / x 00167 get_color(dst,yellow_t()) = (T2)((get_color(dst,yellow_t()) - get_color(dst,black_t()))*x1); // y = (y - k) / x 00168 } else { 00169 get_color(dst,cyan_t())=get_color(dst,magenta_t())=get_color(dst,yellow_t())=0; 00170 } 00171 } 00172 }; 00173 00180 template <> 00181 struct default_color_converter_impl<cmyk_t,rgb_t> { 00182 template <typename P1, typename P2> 00183 void operator()(const P1& src, P2& dst) const { 00184 typedef typename channel_type<P1>::type T1; 00185 get_color(dst,red_t()) = 00186 channel_convert<typename color_element_type<P2,red_t>::type>( 00187 channel_invert<T1>( 00188 (std::min)(channel_traits<T1>::max_value(), 00189 T1(get_color(src,cyan_t())*channel_invert(get_color(src,black_t()))+get_color(src,black_t()))))); 00190 get_color(dst,green_t())= 00191 channel_convert<typename color_element_type<P2,green_t>::type>( 00192 channel_invert<T1>( 00193 (std::min)(channel_traits<T1>::max_value(), 00194 T1(get_color(src,magenta_t())*channel_invert(get_color(src,black_t()))+get_color(src,black_t()))))); 00195 get_color(dst,blue_t()) = 00196 channel_convert<typename color_element_type<P2,blue_t>::type>( 00197 channel_invert<T1>( 00198 (std::min)(channel_traits<T1>::max_value(), 00199 T1(get_color(src,yellow_t())*channel_invert(get_color(src,black_t()))+get_color(src,black_t()))))); 00200 } 00201 }; 00202 00203 00208 template <> 00209 struct default_color_converter_impl<cmyk_t,gray_t> { 00210 template <typename P1, typename P2> 00211 void operator()(const P1& src, P2& dst) const { 00212 get_color(dst,gray_color_t())= 00213 channel_convert<typename color_element_type<P2,gray_t>::type>( 00214 channel_multiply( 00215 channel_invert( 00216 detail::rgb_to_luminance<typename color_element_type<P1,black_t>::type>( 00217 get_color(src,cyan_t()), 00218 get_color(src,magenta_t()), 00219 get_color(src,yellow_t()) 00220 ) 00221 ), 00222 channel_invert(get_color(src,black_t())))); 00223 } 00224 }; 00225 00226 namespace detail { 00227 template <typename Pixel> 00228 typename channel_type<Pixel>::type alpha_or_max_impl(const Pixel& p, mpl::true_) { 00229 return get_color(p,alpha_t()); 00230 } 00231 template <typename Pixel> 00232 typename channel_type<Pixel>::type alpha_or_max_impl(const Pixel& p, mpl::false_) { 00233 return channel_traits<typename channel_type<Pixel>::type>::max_value(); 00234 } 00235 } // namespace detail 00236 00237 // Returns max_value if the pixel has no alpha channel. Otherwise returns the alpha. 00238 template <typename Pixel> 00239 typename channel_type<Pixel>::type alpha_or_max(const Pixel& p) { 00240 return detail::alpha_or_max_impl(p, mpl::contains<typename color_space_type<Pixel>::type,alpha_t>()); 00241 } 00242 00243 00246 template <typename C1> 00247 struct default_color_converter_impl<C1,rgba_t> { 00248 template <typename P1, typename P2> 00249 void operator()(const P1& src, P2& dst) const { 00250 typedef typename channel_type<P2>::type T2; 00251 pixel<T2,rgb_layout_t> tmp; 00252 default_color_converter_impl<C1,rgb_t>()(src,tmp); 00253 get_color(dst,red_t()) =get_color(tmp,red_t()); 00254 get_color(dst,green_t())=get_color(tmp,green_t()); 00255 get_color(dst,blue_t()) =get_color(tmp,blue_t()); 00256 get_color(dst,alpha_t())=channel_convert<T2>(alpha_or_max(src)); 00257 } 00258 }; 00259 00266 template <typename C2> 00267 struct default_color_converter_impl<rgba_t,C2> { 00268 template <typename P1, typename P2> 00269 void operator()(const P1& src, P2& dst) const { 00270 typedef typename channel_type<P1>::type T1; 00271 default_color_converter_impl<rgb_t,C2>()( 00272 pixel<T1,rgb_layout_t>(channel_multiply(get_color(src,red_t()), get_color(src,alpha_t())), 00273 channel_multiply(get_color(src,green_t()),get_color(src,alpha_t())), 00274 channel_multiply(get_color(src,blue_t()), get_color(src,alpha_t()))) 00275 ,dst); 00276 } 00277 }; 00278 00281 template <> 00282 struct default_color_converter_impl<rgba_t,rgba_t> { 00283 template <typename P1, typename P2> 00284 void operator()(const P1& src, P2& dst) const { 00285 static_for_each(src,dst,default_channel_converter()); 00286 } 00287 }; 00288 00292 00295 struct default_color_converter { 00296 template <typename SrcP, typename DstP> 00297 void operator()(const SrcP& src,DstP& dst) const { 00298 typedef typename color_space_type<SrcP>::type SrcColorSpace; 00299 typedef typename color_space_type<DstP>::type DstColorSpace; 00300 default_color_converter_impl<SrcColorSpace,DstColorSpace>()(src,dst); 00301 } 00302 }; 00303 00308 template <typename SrcP, typename DstP> 00309 inline void color_convert(const SrcP& src, DstP& dst) { 00310 default_color_converter()(src,dst); 00311 } 00312 00313 } } // namespace boost::gil 00314 00315 #endif Generated on Thu Nov 8 21:53:16 2007 for Generic Image Library by 1.4.4 |