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

Copyright © 2006-2007 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google