Modules | Alphabetical List | Class List | Directories | File List | File Members | 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 "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