00001
00002
00003
00004
00005
00006
00007
00008
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
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
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
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 }
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())));
00157 get_color(dst,magenta_t()) = channel_invert(channel_convert<T2>(get_color(src,green_t())));
00158 get_color(dst,yellow_t()) = channel_invert(channel_convert<T2>(get_color(src,blue_t())));
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())));
00162 T2 x = channel_traits<T2>::max_value()-get_color(dst,black_t());
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);
00166 get_color(dst,magenta_t()) = (T2)((get_color(dst,magenta_t()) - get_color(dst,black_t()))*x1);
00167 get_color(dst,yellow_t()) = (T2)((get_color(dst,yellow_t()) - get_color(dst,black_t()))*x1);
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 }
00236
00237
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 } }
00314
00315 #endif