color_convert.hpp

Go 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  doxygen 1.5.6