Modules | Alphabetical List | Class List | Directories | File List | GIL Home Page # 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