include/opencv2/gpu/device/detail/color_detail.hpp
Go to the documentation of this file.
00001 /*M///////////////////////////////////////////////////////////////////////////////////////
00002 //
00003 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
00004 //
00005 //  By downloading, copying, installing or using the software you agree to this license.
00006 //  If you do not agree to this license, do not download, install,
00007 //  copy or use the software.
00008 //
00009 //
00010 //                           License Agreement
00011 //                For Open Source Computer Vision Library
00012 //
00013 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
00014 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
00015 // Third party copyrights are property of their respective owners.
00016 //
00017 // Redistribution and use in source and binary forms, with or without modification,
00018 // are permitted provided that the following conditions are met:
00019 //
00020 //   * Redistribution's of source code must retain the above copyright notice,
00021 //     this list of conditions and the following disclaimer.
00022 //
00023 //   * Redistribution's in binary form must reproduce the above copyright notice,
00024 //     this list of conditions and the following disclaimer in the documentation
00025 //     and/or other materials provided with the distribution.
00026 //
00027 //   * The name of the copyright holders may not be used to endorse or promote products
00028 //     derived from this software without specific prior written permission.
00029 //
00030 // This software is provided by the copyright holders and contributors "as is" and
00031 // any express or bpied warranties, including, but not limited to, the bpied
00032 // warranties of merchantability and fitness for a particular purpose are disclaimed.
00033 // In no event shall the Intel Corporation or contributors be liable for any direct,
00034 // indirect, incidental, special, exemplary, or consequential damages
00035 // (including, but not limited to, procurement of substitute goods or services;
00036 // loss of use, data, or profits; or business interruption) however caused
00037 // and on any theory of liability, whether in contract, strict liability,
00038 // or tort (including negligence or otherwise) arising in any way out of
00039 // the use of this software, even if advised of the possibility of such damage.
00040 //
00041 //M*/
00042 
00043 #ifndef __OPENCV_GPU_COLOR_DETAIL_HPP__
00044 #define __OPENCV_GPU_COLOR_DETAIL_HPP__
00045 
00046 #include "../common.hpp"
00047 #include "../vec_traits.hpp"
00048 #include "../saturate_cast.hpp"
00049 #include "../limits.hpp"
00050 #include "../functional.hpp"
00051 
00052 namespace cv { namespace gpu { namespace device
00053 {
00054     #ifndef CV_DESCALE
00055         #define CV_DESCALE(x, n) (((x) + (1 << ((n)-1))) >> (n))
00056     #endif
00057 
00058     namespace color_detail
00059     {
00060         template<typename T> struct ColorChannel
00061         {
00062             typedef float worktype_f;
00063             static __device__ __forceinline__ T max() { return numeric_limits<T>::max(); }
00064             static __device__ __forceinline__ T half() { return (T)(max()/2 + 1); }
00065         };
00066 
00067         template<> struct ColorChannel<float>
00068         {
00069             typedef float worktype_f;
00070             static __device__ __forceinline__ float max() { return 1.f; }
00071             static __device__ __forceinline__ float half() { return 0.5f; }
00072         };
00073 
00074         template <typename T> static __device__ __forceinline__ void setAlpha(typename TypeVec<T, 3>::vec_type& vec, T val)
00075         {
00076         }
00077 
00078         template <typename T> static __device__ __forceinline__ void setAlpha(typename TypeVec<T, 4>::vec_type& vec, T val)
00079         {
00080             vec.w = val;
00081         }
00082 
00083         template <typename T> static __device__ __forceinline__ T getAlpha(const typename TypeVec<T, 3>::vec_type& vec)
00084         {
00085             return ColorChannel<T>::max();
00086         }
00087 
00088         template <typename T> static __device__ __forceinline__ T getAlpha(const typename TypeVec<T, 4>::vec_type& vec)
00089         {
00090             return vec.w;
00091         }
00092 
00093         enum
00094         {
00095             yuv_shift  = 14,
00096             xyz_shift  = 12,
00097             R2Y        = 4899,
00098             G2Y        = 9617,
00099             B2Y        = 1868,
00100             BLOCK_SIZE = 256
00101         };
00102     }
00103 
00105 
00106     namespace color_detail
00107     {
00108         template <typename T, int scn, int dcn, int bidx> struct RGB2RGB
00109             : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
00110         {
00111             __device__ typename TypeVec<T, dcn>::vec_type operator()(const typename TypeVec<T, scn>::vec_type& src) const
00112             {
00113                 typename TypeVec<T, dcn>::vec_type dst;
00114 
00115                 dst.x = (&src.x)[bidx];
00116                 dst.y = src.y;
00117                 dst.z = (&src.x)[bidx^2];
00118                 setAlpha(dst, getAlpha<T>(src));
00119 
00120                 return dst;
00121             }
00122 
00123             __device__ __forceinline__ RGB2RGB()
00124                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00125 
00126             __device__ __forceinline__ RGB2RGB(const RGB2RGB& other_)
00127                 :unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00128         };
00129 
00130         template <> struct RGB2RGB<uchar, 4, 4, 2> : unary_function<uint, uint>
00131         {
00132             __device__ uint operator()(uint src) const
00133             {
00134                 uint dst = 0;
00135 
00136                 dst |= (0xffu & (src >> 16));
00137                 dst |= (0xffu & (src >> 8)) << 8;
00138                 dst |= (0xffu & (src)) << 16;
00139                 dst |= (0xffu & (src >> 24)) << 24;
00140 
00141                 return dst;
00142             }
00143 
00144             __device__ __forceinline__ RGB2RGB():unary_function<uint, uint>(){}
00145             __device__ __forceinline__ RGB2RGB(const RGB2RGB& other_):unary_function<uint, uint>(){}
00146         };
00147     }
00148 
00149 #define OPENCV_GPU_IMPLEMENT_RGB2RGB_TRAITS(name, scn, dcn, bidx) \
00150     template <typename T> struct name ## _traits \
00151     { \
00152         typedef ::cv::gpu::device::color_detail::RGB2RGB<T, scn, dcn, bidx> functor_type; \
00153         static __host__ __device__ __forceinline__ functor_type create_functor() \
00154         { \
00155             return functor_type(); \
00156         } \
00157     };
00158 
00160 
00161     namespace color_detail
00162     {
00163         template <int green_bits, int bidx> struct RGB2RGB5x5Converter;
00164         template<int bidx> struct RGB2RGB5x5Converter<6, bidx>
00165         {
00166             static __device__ __forceinline__ ushort cvt(const uchar3& src)
00167             {
00168                 return (ushort)(((&src.x)[bidx] >> 3) | ((src.y & ~3) << 3) | (((&src.x)[bidx^2] & ~7) << 8));
00169             }
00170 
00171             static __device__ __forceinline__ ushort cvt(uint src)
00172             {
00173                 uint b = 0xffu & (src >> (bidx * 8));
00174                 uint g = 0xffu & (src >> 8);
00175                 uint r = 0xffu & (src >> ((bidx ^ 2) * 8));
00176                 return (ushort)((b >> 3) | ((g & ~3) << 3) | ((r & ~7) << 8));
00177             }
00178         };
00179 
00180         template<int bidx> struct RGB2RGB5x5Converter<5, bidx>
00181         {
00182             static __device__ __forceinline__ ushort cvt(const uchar3& src)
00183             {
00184                 return (ushort)(((&src.x)[bidx] >> 3) | ((src.y & ~7) << 2) | (((&src.x)[bidx^2] & ~7) << 7));
00185             }
00186 
00187             static __device__ __forceinline__ ushort cvt(uint src)
00188             {
00189                 uint b = 0xffu & (src >> (bidx * 8));
00190                 uint g = 0xffu & (src >> 8);
00191                 uint r = 0xffu & (src >> ((bidx ^ 2) * 8));
00192                 uint a = 0xffu & (src >> 24);
00193                 return (ushort)((b >> 3) | ((g & ~7) << 2) | ((r & ~7) << 7) | (a * 0x8000));
00194             }
00195         };
00196 
00197         template<int scn, int bidx, int green_bits> struct RGB2RGB5x5;
00198 
00199         template<int bidx, int green_bits> struct RGB2RGB5x5<3, bidx,green_bits> : unary_function<uchar3, ushort>
00200         {
00201             __device__ __forceinline__ ushort operator()(const uchar3& src) const
00202             {
00203                 return RGB2RGB5x5Converter<green_bits, bidx>::cvt(src);
00204             }
00205 
00206             __device__ __forceinline__ RGB2RGB5x5():unary_function<uchar3, ushort>(){}
00207             __device__ __forceinline__ RGB2RGB5x5(const RGB2RGB5x5& other_):unary_function<uchar3, ushort>(){}
00208         };
00209 
00210         template<int bidx, int green_bits> struct RGB2RGB5x5<4, bidx,green_bits> : unary_function<uint, ushort>
00211         {
00212             __device__ __forceinline__ ushort operator()(uint src) const
00213             {
00214                 return RGB2RGB5x5Converter<green_bits, bidx>::cvt(src);
00215             }
00216 
00217             __device__ __forceinline__ RGB2RGB5x5():unary_function<uint, ushort>(){}
00218             __device__ __forceinline__ RGB2RGB5x5(const RGB2RGB5x5& other_):unary_function<uint, ushort>(){}
00219         };
00220     }
00221 
00222 #define OPENCV_GPU_IMPLEMENT_RGB2RGB5x5_TRAITS(name, scn, bidx, green_bits) \
00223     struct name ## _traits \
00224     { \
00225         typedef ::cv::gpu::device::color_detail::RGB2RGB5x5<scn, bidx, green_bits> functor_type; \
00226         static __host__ __device__ __forceinline__ functor_type create_functor() \
00227         { \
00228             return functor_type(); \
00229         } \
00230     };
00231 
00232     namespace color_detail
00233     {
00234         template <int green_bits, int bidx> struct RGB5x52RGBConverter;
00235 
00236         template <int bidx> struct RGB5x52RGBConverter<5, bidx>
00237         {
00238             static __device__ __forceinline__ void cvt(uint src, uchar3& dst)
00239             {
00240                 (&dst.x)[bidx] = src << 3;
00241                 dst.y = (src >> 2) & ~7;
00242                 (&dst.x)[bidx ^ 2] = (src >> 7) & ~7;
00243             }
00244 
00245             static __device__ __forceinline__ void cvt(uint src, uint& dst)
00246             {
00247                 dst = 0;
00248 
00249                 dst |= (0xffu & (src << 3)) << (bidx * 8);
00250                 dst |= (0xffu & ((src >> 2) & ~7)) << 8;
00251                 dst |= (0xffu & ((src >> 7) & ~7)) << ((bidx ^ 2) * 8);
00252                 dst |= ((src & 0x8000) * 0xffu) << 24;
00253             }
00254         };
00255 
00256         template <int bidx> struct RGB5x52RGBConverter<6, bidx>
00257         {
00258             static __device__ __forceinline__ void cvt(uint src, uchar3& dst)
00259             {
00260                 (&dst.x)[bidx] = src << 3;
00261                 dst.y = (src >> 3) & ~3;
00262                 (&dst.x)[bidx ^ 2] = (src >> 8) & ~7;
00263             }
00264 
00265             static __device__ __forceinline__ void cvt(uint src, uint& dst)
00266             {
00267                 dst = 0xffu << 24;
00268 
00269                 dst |= (0xffu & (src << 3)) << (bidx * 8);
00270                 dst |= (0xffu &((src >> 3) & ~3)) << 8;
00271                 dst |= (0xffu & ((src >> 8) & ~7)) << ((bidx ^ 2) * 8);
00272             }
00273         };
00274 
00275         template <int dcn, int bidx, int green_bits> struct RGB5x52RGB;
00276 
00277         template <int bidx, int green_bits> struct RGB5x52RGB<3, bidx, green_bits> : unary_function<ushort, uchar3>
00278         {
00279             __device__ __forceinline__ uchar3 operator()(ushort src) const
00280             {
00281                 uchar3 dst;
00282                 RGB5x52RGBConverter<green_bits, bidx>::cvt(src, dst);
00283                 return dst;
00284             }
00285             __device__ __forceinline__ RGB5x52RGB():unary_function<ushort, uchar3>(){}
00286             __device__ __forceinline__ RGB5x52RGB(const RGB5x52RGB& other_):unary_function<ushort, uchar3>(){}
00287 
00288         };
00289 
00290         template <int bidx, int green_bits> struct RGB5x52RGB<4, bidx, green_bits> : unary_function<ushort, uint>
00291         {
00292             __device__ __forceinline__ uint operator()(ushort src) const
00293             {
00294                 uint dst;
00295                 RGB5x52RGBConverter<green_bits, bidx>::cvt(src, dst);
00296                 return dst;
00297             }
00298             __device__ __forceinline__ RGB5x52RGB():unary_function<ushort, uint>(){}
00299             __device__ __forceinline__ RGB5x52RGB(const RGB5x52RGB& other_):unary_function<ushort, uint>(){}
00300         };
00301     }
00302 
00303 #define OPENCV_GPU_IMPLEMENT_RGB5x52RGB_TRAITS(name, dcn, bidx, green_bits) \
00304     struct name ## _traits \
00305     { \
00306         typedef ::cv::gpu::device::color_detail::RGB5x52RGB<dcn, bidx, green_bits> functor_type; \
00307         static __host__ __device__ __forceinline__ functor_type create_functor() \
00308         { \
00309             return functor_type(); \
00310         } \
00311     };
00312 
00314 
00315     namespace color_detail
00316     {
00317         template <typename T, int dcn> struct Gray2RGB : unary_function<T, typename TypeVec<T, dcn>::vec_type>
00318         {
00319             __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator()(T src) const
00320             {
00321                 typename TypeVec<T, dcn>::vec_type dst;
00322 
00323                 dst.z = dst.y = dst.x = src;
00324                 setAlpha(dst, ColorChannel<T>::max());
00325 
00326                 return dst;
00327             }
00328             __device__ __forceinline__ Gray2RGB():unary_function<T, typename TypeVec<T, dcn>::vec_type>(){}
00329             __device__ __forceinline__ Gray2RGB(const Gray2RGB& other_)
00330                 : unary_function<T, typename TypeVec<T, dcn>::vec_type>(){}
00331         };
00332 
00333         template <> struct Gray2RGB<uchar, 4> : unary_function<uchar, uint>
00334         {
00335             __device__ __forceinline__ uint operator()(uint src) const
00336             {
00337                 uint dst = 0xffu << 24;
00338 
00339                 dst |= src;
00340                 dst |= src << 8;
00341                 dst |= src << 16;
00342 
00343                 return dst;
00344             }
00345             __device__ __forceinline__ Gray2RGB():unary_function<uchar, uint>(){}
00346             __device__ __forceinline__ Gray2RGB(const Gray2RGB& other_):unary_function<uchar, uint>(){}
00347         };
00348     }
00349 
00350 #define OPENCV_GPU_IMPLEMENT_GRAY2RGB_TRAITS(name, dcn) \
00351     template <typename T> struct name ## _traits \
00352     { \
00353         typedef ::cv::gpu::device::color_detail::Gray2RGB<T, dcn> functor_type; \
00354         static __host__ __device__ __forceinline__ functor_type create_functor() \
00355         { \
00356             return functor_type(); \
00357         } \
00358     };
00359 
00360     namespace color_detail
00361     {
00362         template <int green_bits> struct Gray2RGB5x5Converter;
00363         template<> struct Gray2RGB5x5Converter<6>
00364         {
00365             static __device__ __forceinline__ ushort cvt(uint t)
00366             {
00367                 return (ushort)((t >> 3) | ((t & ~3) << 3) | ((t & ~7) << 8));
00368             }
00369         };
00370 
00371         template<> struct Gray2RGB5x5Converter<5>
00372         {
00373             static __device__ __forceinline__ ushort cvt(uint t)
00374             {
00375                 t >>= 3;
00376                 return (ushort)(t | (t << 5) | (t << 10));
00377             }
00378         };
00379 
00380         template<int green_bits> struct Gray2RGB5x5 : unary_function<uchar, ushort>
00381         {
00382             __device__ __forceinline__ ushort operator()(uint src) const
00383             {
00384                 return Gray2RGB5x5Converter<green_bits>::cvt(src);
00385             }
00386 
00387             __device__ __forceinline__ Gray2RGB5x5():unary_function<uchar, ushort>(){}
00388             __device__ __forceinline__ Gray2RGB5x5(const Gray2RGB5x5& other_):unary_function<uchar, ushort>(){}
00389         };
00390     }
00391 
00392 #define OPENCV_GPU_IMPLEMENT_GRAY2RGB5x5_TRAITS(name, green_bits) \
00393     struct name ## _traits \
00394     { \
00395         typedef ::cv::gpu::device::color_detail::Gray2RGB5x5<green_bits> functor_type; \
00396         static __host__ __device__ __forceinline__ functor_type create_functor() \
00397         { \
00398             return functor_type(); \
00399         } \
00400     };
00401 
00403 
00404     namespace color_detail
00405     {
00406         template <int green_bits> struct RGB5x52GrayConverter;
00407         template <> struct RGB5x52GrayConverter<6>
00408         {
00409             static __device__ __forceinline__ uchar cvt(uint t)
00410             {
00411                 return (uchar)CV_DESCALE(((t << 3) & 0xf8) * B2Y + ((t >> 3) & 0xfc) * G2Y + ((t >> 8) & 0xf8) * R2Y, yuv_shift);
00412             }
00413         };
00414 
00415         template <> struct RGB5x52GrayConverter<5>
00416         {
00417             static __device__ __forceinline__ uchar cvt(uint t)
00418             {
00419                 return (uchar)CV_DESCALE(((t << 3) & 0xf8) * B2Y + ((t >> 2) & 0xf8) * G2Y + ((t >> 7) & 0xf8) * R2Y, yuv_shift);
00420             }
00421         };
00422 
00423         template<int green_bits> struct RGB5x52Gray : unary_function<ushort, uchar>
00424         {
00425             __device__ __forceinline__ uchar operator()(uint src) const
00426             {
00427                 return RGB5x52GrayConverter<green_bits>::cvt(src);
00428             }
00429             __device__ __forceinline__ RGB5x52Gray() : unary_function<ushort, uchar>(){}
00430             __device__ __forceinline__ RGB5x52Gray(const RGB5x52Gray& other_) : unary_function<ushort, uchar>(){}
00431         };
00432     }
00433 
00434 #define OPENCV_GPU_IMPLEMENT_RGB5x52GRAY_TRAITS(name, green_bits) \
00435     struct name ## _traits \
00436     { \
00437         typedef ::cv::gpu::device::color_detail::RGB5x52Gray<green_bits> functor_type; \
00438         static __host__ __device__ __forceinline__ functor_type create_functor() \
00439         { \
00440             return functor_type(); \
00441         } \
00442     };
00443 
00444     namespace color_detail
00445     {
00446         template <int bidx, typename T> static __device__ __forceinline__ T RGB2GrayConvert(const T* src)
00447         {
00448             return (T)CV_DESCALE((unsigned)(src[bidx] * B2Y + src[1] * G2Y + src[bidx^2] * R2Y), yuv_shift);
00449         }
00450 
00451         template <int bidx> static __device__ __forceinline__ uchar RGB2GrayConvert(uint src)
00452         {
00453             uint b = 0xffu & (src >> (bidx * 8));
00454             uint g = 0xffu & (src >> 8);
00455             uint r = 0xffu & (src >> ((bidx ^ 2) * 8));
00456             return CV_DESCALE((uint)(b * B2Y + g * G2Y + r * R2Y), yuv_shift);
00457         }
00458 
00459         template <int bidx> static __device__ __forceinline__ float RGB2GrayConvert(const float* src)
00460         {
00461             return src[bidx] * 0.114f + src[1] * 0.587f + src[bidx^2] * 0.299f;
00462         }
00463 
00464         template <typename T, int scn, int bidx> struct RGB2Gray : unary_function<typename TypeVec<T, scn>::vec_type, T>
00465         {
00466             __device__ __forceinline__ T operator()(const typename TypeVec<T, scn>::vec_type& src) const
00467             {
00468                 return RGB2GrayConvert<bidx>(&src.x);
00469             }
00470             __device__ __forceinline__ RGB2Gray() : unary_function<typename TypeVec<T, scn>::vec_type, T>(){}
00471             __device__ __forceinline__ RGB2Gray(const RGB2Gray& other_)
00472                 : unary_function<typename TypeVec<T, scn>::vec_type, T>(){}
00473         };
00474 
00475         template <int bidx> struct RGB2Gray<uchar, 4, bidx> : unary_function<uint, uchar>
00476         {
00477             __device__ __forceinline__ uchar operator()(uint src) const
00478             {
00479                 return RGB2GrayConvert<bidx>(src);
00480             }
00481             __device__ __forceinline__ RGB2Gray() : unary_function<uint, uchar>(){}
00482             __device__ __forceinline__ RGB2Gray(const RGB2Gray& other_) : unary_function<uint, uchar>(){}
00483         };
00484     }
00485 
00486 #define OPENCV_GPU_IMPLEMENT_RGB2GRAY_TRAITS(name, scn, bidx) \
00487     template <typename T> struct name ## _traits \
00488     { \
00489         typedef ::cv::gpu::device::color_detail::RGB2Gray<T, scn, bidx> functor_type; \
00490         static __host__ __device__ __forceinline__ functor_type create_functor() \
00491         { \
00492             return functor_type(); \
00493         } \
00494     };
00495 
00497 
00498     namespace color_detail
00499     {
00500         __constant__ float c_RGB2YUVCoeffs_f[5] = { 0.114f, 0.587f, 0.299f, 0.492f, 0.877f };
00501         __constant__ int   c_RGB2YUVCoeffs_i[5] = { B2Y, G2Y, R2Y, 8061, 14369 };
00502 
00503         template <int bidx, typename T, typename D> static __device__ void RGB2YUVConvert(const T* src, D& dst)
00504         {
00505             const int delta = ColorChannel<T>::half() * (1 << yuv_shift);
00506 
00507             const int Y = CV_DESCALE(src[0] * c_RGB2YUVCoeffs_i[bidx^2] + src[1] * c_RGB2YUVCoeffs_i[1] + src[2] * c_RGB2YUVCoeffs_i[bidx], yuv_shift);
00508             const int Cr = CV_DESCALE((src[bidx^2] - Y) * c_RGB2YUVCoeffs_i[3] + delta, yuv_shift);
00509             const int Cb = CV_DESCALE((src[bidx] - Y) * c_RGB2YUVCoeffs_i[4] + delta, yuv_shift);
00510 
00511             dst.x = saturate_cast<T>(Y);
00512             dst.y = saturate_cast<T>(Cr);
00513             dst.z = saturate_cast<T>(Cb);
00514         }
00515 
00516         template <int bidx, typename D> static __device__ __forceinline__ void RGB2YUVConvert(const float* src, D& dst)
00517         {
00518             dst.x = src[0] * c_RGB2YUVCoeffs_f[bidx^2] + src[1] * c_RGB2YUVCoeffs_f[1] + src[2] * c_RGB2YUVCoeffs_f[bidx];
00519             dst.y = (src[bidx^2] - dst.x) * c_RGB2YUVCoeffs_f[3] + ColorChannel<float>::half();
00520             dst.z = (src[bidx] - dst.x) * c_RGB2YUVCoeffs_f[4] + ColorChannel<float>::half();
00521         }
00522 
00523         template <typename T, int scn, int dcn, int bidx> struct RGB2YUV
00524             : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
00525         {
00526             __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator ()(const typename TypeVec<T, scn>::vec_type& src) const
00527             {
00528                 typename TypeVec<T, dcn>::vec_type dst;
00529                 RGB2YUVConvert<bidx>(&src.x, dst);
00530                 return dst;
00531             }
00532             __device__ __forceinline__ RGB2YUV()
00533                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00534             __device__ __forceinline__ RGB2YUV(const RGB2YUV& other_)
00535                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00536         };
00537     }
00538 
00539 #define OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(name, scn, dcn, bidx) \
00540     template <typename T> struct name ## _traits \
00541     { \
00542         typedef ::cv::gpu::device::color_detail::RGB2YUV<T, scn, dcn, bidx> functor_type; \
00543         static __host__ __device__ __forceinline__ functor_type create_functor() \
00544         { \
00545             return functor_type(); \
00546         } \
00547     };
00548 
00549     namespace color_detail
00550     {
00551         __constant__ float c_YUV2RGBCoeffs_f[5] = { 2.032f, -0.395f, -0.581f, 1.140f };
00552         __constant__ int   c_YUV2RGBCoeffs_i[5] = { 33292, -6472, -9519, 18678 };
00553 
00554         template <int bidx, typename T, typename D> static __device__ void YUV2RGBConvert(const T& src, D* dst)
00555         {
00556             const int b = src.x + CV_DESCALE((src.z - ColorChannel<D>::half()) * c_YUV2RGBCoeffs_i[3], yuv_shift);
00557 
00558             const int g = src.x + CV_DESCALE((src.z - ColorChannel<D>::half()) * c_YUV2RGBCoeffs_i[2]
00559                                              + (src.y - ColorChannel<D>::half()) * c_YUV2RGBCoeffs_i[1], yuv_shift);
00560 
00561             const int r = src.x + CV_DESCALE((src.y - ColorChannel<D>::half()) * c_YUV2RGBCoeffs_i[0], yuv_shift);
00562 
00563             dst[bidx] = saturate_cast<D>(b);
00564             dst[1] = saturate_cast<D>(g);
00565             dst[bidx^2] = saturate_cast<D>(r);
00566         }
00567 
00568         template <int bidx> static __device__ uint YUV2RGBConvert(uint src)
00569         {
00570             const int x = 0xff & (src);
00571             const int y = 0xff & (src >> 8);
00572             const int z = 0xff & (src >> 16);
00573 
00574             const int b = x + CV_DESCALE((z - ColorChannel<uchar>::half()) * c_YUV2RGBCoeffs_i[3], yuv_shift);
00575 
00576             const int g = x + CV_DESCALE((z - ColorChannel<uchar>::half()) * c_YUV2RGBCoeffs_i[2]
00577                                          + (y - ColorChannel<uchar>::half()) * c_YUV2RGBCoeffs_i[1], yuv_shift);
00578 
00579             const int r = x + CV_DESCALE((y - ColorChannel<uchar>::half()) * c_YUV2RGBCoeffs_i[0], yuv_shift);
00580 
00581             uint dst = 0xffu << 24;
00582 
00583             dst |= saturate_cast<uchar>(b) << (bidx * 8);
00584             dst |= saturate_cast<uchar>(g) << 8;
00585             dst |= saturate_cast<uchar>(r) << ((bidx ^ 2) * 8);
00586 
00587             return dst;
00588         }
00589 
00590         template <int bidx, typename T> static __device__ __forceinline__ void YUV2RGBConvert(const T& src, float* dst)
00591         {
00592             dst[bidx] = src.x + (src.z - ColorChannel<float>::half()) * c_YUV2RGBCoeffs_f[3];
00593 
00594             dst[1] = src.x + (src.z - ColorChannel<float>::half()) * c_YUV2RGBCoeffs_f[2]
00595                      + (src.y - ColorChannel<float>::half()) * c_YUV2RGBCoeffs_f[1];
00596 
00597             dst[bidx^2] = src.x + (src.y - ColorChannel<float>::half()) * c_YUV2RGBCoeffs_f[0];
00598         }
00599 
00600         template <typename T, int scn, int dcn, int bidx> struct YUV2RGB
00601             : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
00602         {
00603             __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator ()(const typename TypeVec<T, scn>::vec_type& src) const
00604             {
00605                 typename TypeVec<T, dcn>::vec_type dst;
00606 
00607                 YUV2RGBConvert<bidx>(src, &dst.x);
00608                 setAlpha(dst, ColorChannel<T>::max());
00609 
00610                 return dst;
00611             }
00612             __device__ __forceinline__ YUV2RGB()
00613                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00614             __device__ __forceinline__ YUV2RGB(const YUV2RGB& other_)
00615                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00616         };
00617 
00618         template <int bidx> struct YUV2RGB<uchar, 4, 4, bidx> : unary_function<uint, uint>
00619         {
00620             __device__ __forceinline__ uint operator ()(uint src) const
00621             {
00622                 return YUV2RGBConvert<bidx>(src);
00623             }
00624             __device__ __forceinline__ YUV2RGB() : unary_function<uint, uint>(){}
00625             __device__ __forceinline__ YUV2RGB(const YUV2RGB& other_) : unary_function<uint, uint>(){}
00626         };
00627     }
00628 
00629 #define OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(name, scn, dcn, bidx) \
00630     template <typename T> struct name ## _traits \
00631     { \
00632         typedef ::cv::gpu::device::color_detail::YUV2RGB<T, scn, dcn, bidx> functor_type; \
00633         static __host__ __device__ __forceinline__ functor_type create_functor() \
00634         { \
00635             return functor_type(); \
00636         } \
00637     };
00638 
00640 
00641     namespace color_detail
00642     {
00643         __constant__ float c_RGB2YCrCbCoeffs_f[5] = {0.299f, 0.587f, 0.114f, 0.713f, 0.564f};
00644         __constant__ int   c_RGB2YCrCbCoeffs_i[5] = {R2Y, G2Y, B2Y, 11682, 9241};
00645 
00646         template <int bidx, typename T, typename D> static __device__ void RGB2YCrCbConvert(const T* src, D& dst)
00647         {
00648             const int delta = ColorChannel<T>::half() * (1 << yuv_shift);
00649 
00650             const int Y = CV_DESCALE(src[0] * c_RGB2YCrCbCoeffs_i[bidx^2] + src[1] * c_RGB2YCrCbCoeffs_i[1] + src[2] * c_RGB2YCrCbCoeffs_i[bidx], yuv_shift);
00651             const int Cr = CV_DESCALE((src[bidx^2] - Y) * c_RGB2YCrCbCoeffs_i[3] + delta, yuv_shift);
00652             const int Cb = CV_DESCALE((src[bidx] - Y) * c_RGB2YCrCbCoeffs_i[4] + delta, yuv_shift);
00653 
00654             dst.x = saturate_cast<T>(Y);
00655             dst.y = saturate_cast<T>(Cr);
00656             dst.z = saturate_cast<T>(Cb);
00657         }
00658 
00659         template <int bidx> static __device__ uint RGB2YCrCbConvert(uint src)
00660         {
00661             const int delta = ColorChannel<uchar>::half() * (1 << yuv_shift);
00662 
00663             const int Y = CV_DESCALE((0xffu & src) * c_RGB2YCrCbCoeffs_i[bidx^2] + (0xffu & (src >> 8)) * c_RGB2YCrCbCoeffs_i[1] + (0xffu & (src >> 16)) * c_RGB2YCrCbCoeffs_i[bidx], yuv_shift);
00664             const int Cr = CV_DESCALE(((0xffu & (src >> ((bidx ^ 2) * 8))) - Y) * c_RGB2YCrCbCoeffs_i[3] + delta, yuv_shift);
00665             const int Cb = CV_DESCALE(((0xffu & (src >> (bidx * 8))) - Y) * c_RGB2YCrCbCoeffs_i[4] + delta, yuv_shift);
00666 
00667             uint dst = 0;
00668 
00669             dst |= saturate_cast<uchar>(Y);
00670             dst |= saturate_cast<uchar>(Cr) << 8;
00671             dst |= saturate_cast<uchar>(Cb) << 16;
00672 
00673             return dst;
00674         }
00675 
00676         template <int bidx, typename D> static __device__ __forceinline__ void RGB2YCrCbConvert(const float* src, D& dst)
00677         {
00678             dst.x = src[0] * c_RGB2YCrCbCoeffs_f[bidx^2] + src[1] * c_RGB2YCrCbCoeffs_f[1] + src[2] * c_RGB2YCrCbCoeffs_f[bidx];
00679             dst.y = (src[bidx^2] - dst.x) * c_RGB2YCrCbCoeffs_f[3] + ColorChannel<float>::half();
00680             dst.z = (src[bidx] - dst.x) * c_RGB2YCrCbCoeffs_f[4] + ColorChannel<float>::half();
00681         }
00682 
00683         template <typename T, int scn, int dcn, int bidx> struct RGB2YCrCb
00684             : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
00685         {
00686             __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator ()(const typename TypeVec<T, scn>::vec_type& src) const
00687             {
00688                 typename TypeVec<T, dcn>::vec_type dst;
00689                 RGB2YCrCbConvert<bidx>(&src.x, dst);
00690                 return dst;
00691             }
00692             __device__ __forceinline__ RGB2YCrCb()
00693                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00694             __device__ __forceinline__ RGB2YCrCb(const RGB2YCrCb& other_)
00695                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00696         };
00697 
00698         template <int bidx> struct RGB2YCrCb<uchar, 4, 4, bidx> : unary_function<uint, uint>
00699         {
00700             __device__ __forceinline__ uint operator ()(uint src) const
00701             {
00702                 return RGB2YCrCbConvert<bidx>(src);
00703             }
00704 
00705             __device__ __forceinline__ RGB2YCrCb() : unary_function<uint, uint>(){}
00706             __device__ __forceinline__ RGB2YCrCb(const RGB2YCrCb& other_) : unary_function<uint, uint>(){}
00707         };
00708     }
00709 
00710 #define OPENCV_GPU_IMPLEMENT_RGB2YCrCb_TRAITS(name, scn, dcn, bidx) \
00711     template <typename T> struct name ## _traits \
00712     { \
00713         typedef ::cv::gpu::device::color_detail::RGB2YCrCb<T, scn, dcn, bidx> functor_type; \
00714         static __host__ __device__ __forceinline__ functor_type create_functor() \
00715         { \
00716             return functor_type(); \
00717         } \
00718     };
00719 
00720     namespace color_detail
00721     {
00722         __constant__ float c_YCrCb2RGBCoeffs_f[5] = {1.403f, -0.714f, -0.344f, 1.773f};
00723         __constant__ int   c_YCrCb2RGBCoeffs_i[5] = {22987, -11698, -5636, 29049};
00724 
00725         template <int bidx, typename T, typename D> static __device__ void YCrCb2RGBConvert(const T& src, D* dst)
00726         {
00727             const int b = src.x + CV_DESCALE((src.z - ColorChannel<D>::half()) * c_YCrCb2RGBCoeffs_i[3], yuv_shift);
00728             const int g = src.x + CV_DESCALE((src.z - ColorChannel<D>::half()) * c_YCrCb2RGBCoeffs_i[2] + (src.y - ColorChannel<D>::half()) * c_YCrCb2RGBCoeffs_i[1], yuv_shift);
00729             const int r = src.x + CV_DESCALE((src.y - ColorChannel<D>::half()) * c_YCrCb2RGBCoeffs_i[0], yuv_shift);
00730 
00731             dst[bidx] = saturate_cast<D>(b);
00732             dst[1] = saturate_cast<D>(g);
00733             dst[bidx^2] = saturate_cast<D>(r);
00734         }
00735 
00736         template <int bidx> static __device__ uint YCrCb2RGBConvert(uint src)
00737         {
00738             const int x = 0xff & (src);
00739             const int y = 0xff & (src >> 8);
00740             const int z = 0xff & (src >> 16);
00741 
00742             const int b = x + CV_DESCALE((z - ColorChannel<uchar>::half()) * c_YCrCb2RGBCoeffs_i[3], yuv_shift);
00743             const int g = x + CV_DESCALE((z - ColorChannel<uchar>::half()) * c_YCrCb2RGBCoeffs_i[2] + (y - ColorChannel<uchar>::half()) * c_YCrCb2RGBCoeffs_i[1], yuv_shift);
00744             const int r = x + CV_DESCALE((y - ColorChannel<uchar>::half()) * c_YCrCb2RGBCoeffs_i[0], yuv_shift);
00745 
00746             uint dst = 0xffu << 24;
00747 
00748             dst |= saturate_cast<uchar>(b) << (bidx * 8);
00749             dst |= saturate_cast<uchar>(g) << 8;
00750             dst |= saturate_cast<uchar>(r) << ((bidx ^ 2) * 8);
00751 
00752             return dst;
00753         }
00754 
00755         template <int bidx, typename T> __device__ __forceinline__ void YCrCb2RGBConvert(const T& src, float* dst)
00756         {
00757             dst[bidx] = src.x + (src.z - ColorChannel<float>::half()) * c_YCrCb2RGBCoeffs_f[3];
00758             dst[1] = src.x + (src.z - ColorChannel<float>::half()) * c_YCrCb2RGBCoeffs_f[2] + (src.y - ColorChannel<float>::half()) * c_YCrCb2RGBCoeffs_f[1];
00759             dst[bidx^2] = src.x + (src.y - ColorChannel<float>::half()) * c_YCrCb2RGBCoeffs_f[0];
00760         }
00761 
00762         template <typename T, int scn, int dcn, int bidx> struct YCrCb2RGB
00763             : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
00764         {
00765             __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator ()(const typename TypeVec<T, scn>::vec_type& src) const
00766             {
00767                 typename TypeVec<T, dcn>::vec_type dst;
00768 
00769                 YCrCb2RGBConvert<bidx>(src, &dst.x);
00770                 setAlpha(dst, ColorChannel<T>::max());
00771 
00772                 return dst;
00773             }
00774             __device__ __forceinline__ YCrCb2RGB()
00775                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00776             __device__ __forceinline__ YCrCb2RGB(const YCrCb2RGB& other_)
00777                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00778         };
00779 
00780         template <int bidx> struct YCrCb2RGB<uchar, 4, 4, bidx> : unary_function<uint, uint>
00781         {
00782             __device__ __forceinline__ uint operator ()(uint src) const
00783             {
00784                 return YCrCb2RGBConvert<bidx>(src);
00785             }
00786             __device__ __forceinline__ YCrCb2RGB() : unary_function<uint, uint>(){}
00787             __device__ __forceinline__ YCrCb2RGB(const YCrCb2RGB& other_) : unary_function<uint, uint>(){}
00788         };
00789     }
00790 
00791 #define OPENCV_GPU_IMPLEMENT_YCrCb2RGB_TRAITS(name, scn, dcn, bidx) \
00792     template <typename T> struct name ## _traits \
00793     { \
00794         typedef ::cv::gpu::device::color_detail::YCrCb2RGB<T, scn, dcn, bidx> functor_type; \
00795         static __host__ __device__ __forceinline__ functor_type create_functor() \
00796         { \
00797             return functor_type(); \
00798         } \
00799     };
00800 
00802 
00803     namespace color_detail
00804     {
00805         __constant__ float c_RGB2XYZ_D65f[9] = { 0.412453f, 0.357580f, 0.180423f, 0.212671f, 0.715160f, 0.072169f, 0.019334f, 0.119193f, 0.950227f };
00806         __constant__ int   c_RGB2XYZ_D65i[9] = { 1689, 1465, 739, 871, 2929, 296, 79, 488, 3892 };
00807 
00808         template <int bidx, typename T, typename D> static __device__ __forceinline__ void RGB2XYZConvert(const T* src, D& dst)
00809         {
00810             dst.x = saturate_cast<T>(CV_DESCALE(src[bidx^2] * c_RGB2XYZ_D65i[0] + src[1] * c_RGB2XYZ_D65i[1] + src[bidx] * c_RGB2XYZ_D65i[2], xyz_shift));
00811             dst.y = saturate_cast<T>(CV_DESCALE(src[bidx^2] * c_RGB2XYZ_D65i[3] + src[1] * c_RGB2XYZ_D65i[4] + src[bidx] * c_RGB2XYZ_D65i[5], xyz_shift));
00812             dst.z = saturate_cast<T>(CV_DESCALE(src[bidx^2] * c_RGB2XYZ_D65i[6] + src[1] * c_RGB2XYZ_D65i[7] + src[bidx] * c_RGB2XYZ_D65i[8], xyz_shift));
00813         }
00814 
00815         template <int bidx> static __device__ __forceinline__ uint RGB2XYZConvert(uint src)
00816         {
00817             const uint b = 0xffu & (src >> (bidx * 8));
00818             const uint g = 0xffu & (src >> 8);
00819             const uint r = 0xffu & (src >> ((bidx ^ 2) * 8));
00820 
00821             const uint x = saturate_cast<uchar>(CV_DESCALE(r * c_RGB2XYZ_D65i[0] + g * c_RGB2XYZ_D65i[1] + b * c_RGB2XYZ_D65i[2], xyz_shift));
00822             const uint y = saturate_cast<uchar>(CV_DESCALE(r * c_RGB2XYZ_D65i[3] + g * c_RGB2XYZ_D65i[4] + b * c_RGB2XYZ_D65i[5], xyz_shift));
00823             const uint z = saturate_cast<uchar>(CV_DESCALE(r * c_RGB2XYZ_D65i[6] + g * c_RGB2XYZ_D65i[7] + b * c_RGB2XYZ_D65i[8], xyz_shift));
00824 
00825             uint dst = 0;
00826 
00827             dst |= x;
00828             dst |= y << 8;
00829             dst |= z << 16;
00830 
00831             return dst;
00832         }
00833 
00834         template <int bidx, typename D> static __device__ __forceinline__ void RGB2XYZConvert(const float* src, D& dst)
00835         {
00836             dst.x = src[bidx^2] * c_RGB2XYZ_D65f[0] + src[1] * c_RGB2XYZ_D65f[1] + src[bidx] * c_RGB2XYZ_D65f[2];
00837             dst.y = src[bidx^2] * c_RGB2XYZ_D65f[3] + src[1] * c_RGB2XYZ_D65f[4] + src[bidx] * c_RGB2XYZ_D65f[5];
00838             dst.z = src[bidx^2] * c_RGB2XYZ_D65f[6] + src[1] * c_RGB2XYZ_D65f[7] + src[bidx] * c_RGB2XYZ_D65f[8];
00839         }
00840 
00841         template <typename T, int scn, int dcn, int bidx> struct RGB2XYZ
00842             : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
00843         {
00844             __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator()(const typename TypeVec<T, scn>::vec_type& src) const
00845             {
00846                 typename TypeVec<T, dcn>::vec_type dst;
00847 
00848                 RGB2XYZConvert<bidx>(&src.x, dst);
00849 
00850                 return dst;
00851             }
00852             __device__ __forceinline__ RGB2XYZ()
00853                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00854             __device__ __forceinline__ RGB2XYZ(const RGB2XYZ& other_)
00855                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00856         };
00857 
00858         template <int bidx> struct RGB2XYZ<uchar, 4, 4, bidx> : unary_function<uint, uint>
00859         {
00860             __device__ __forceinline__ uint operator()(uint src) const
00861             {
00862                 return RGB2XYZConvert<bidx>(src);
00863             }
00864             __device__ __forceinline__ RGB2XYZ() : unary_function<uint, uint>(){}
00865             __device__ __forceinline__ RGB2XYZ(const RGB2XYZ& other_) : unary_function<uint, uint>(){}
00866         };
00867     }
00868 
00869 #define OPENCV_GPU_IMPLEMENT_RGB2XYZ_TRAITS(name, scn, dcn, bidx) \
00870     template <typename T> struct name ## _traits \
00871     { \
00872         typedef ::cv::gpu::device::color_detail::RGB2XYZ<T, scn, dcn, bidx> functor_type; \
00873         static __host__ __device__ __forceinline__ functor_type create_functor() \
00874         { \
00875             return functor_type(); \
00876         } \
00877     };
00878 
00879     namespace color_detail
00880     {
00881         __constant__ float c_XYZ2sRGB_D65f[9] = { 3.240479f, -1.53715f, -0.498535f, -0.969256f, 1.875991f, 0.041556f, 0.055648f, -0.204043f, 1.057311f };
00882         __constant__ int   c_XYZ2sRGB_D65i[9] = { 13273, -6296, -2042, -3970, 7684, 170, 228, -836, 4331 };
00883 
00884         template <int bidx, typename T, typename D> static __device__ __forceinline__ void XYZ2RGBConvert(const T& src, D* dst)
00885         {
00886             dst[bidx^2] = saturate_cast<D>(CV_DESCALE(src.x * c_XYZ2sRGB_D65i[0] + src.y * c_XYZ2sRGB_D65i[1] + src.z * c_XYZ2sRGB_D65i[2], xyz_shift));
00887             dst[1]      = saturate_cast<D>(CV_DESCALE(src.x * c_XYZ2sRGB_D65i[3] + src.y * c_XYZ2sRGB_D65i[4] + src.z * c_XYZ2sRGB_D65i[5], xyz_shift));
00888             dst[bidx]   = saturate_cast<D>(CV_DESCALE(src.x * c_XYZ2sRGB_D65i[6] + src.y * c_XYZ2sRGB_D65i[7] + src.z * c_XYZ2sRGB_D65i[8], xyz_shift));
00889         }
00890 
00891         template <int bidx> static __device__ __forceinline__ uint XYZ2RGBConvert(uint src)
00892         {
00893             const int x = 0xff & src;
00894             const int y = 0xff & (src >> 8);
00895             const int z = 0xff & (src >> 16);
00896 
00897             const uint r = saturate_cast<uchar>(CV_DESCALE(x * c_XYZ2sRGB_D65i[0] + y * c_XYZ2sRGB_D65i[1] + z * c_XYZ2sRGB_D65i[2], xyz_shift));
00898             const uint g = saturate_cast<uchar>(CV_DESCALE(x * c_XYZ2sRGB_D65i[3] + y * c_XYZ2sRGB_D65i[4] + z * c_XYZ2sRGB_D65i[5], xyz_shift));
00899             const uint b = saturate_cast<uchar>(CV_DESCALE(x * c_XYZ2sRGB_D65i[6] + y * c_XYZ2sRGB_D65i[7] + z * c_XYZ2sRGB_D65i[8], xyz_shift));
00900 
00901             uint dst = 0xffu << 24;
00902 
00903             dst |= b << (bidx * 8);
00904             dst |= g << 8;
00905             dst |= r << ((bidx ^ 2) * 8);
00906 
00907             return dst;
00908         }
00909 
00910         template <int bidx, typename T> static __device__ __forceinline__ void XYZ2RGBConvert(const T& src, float* dst)
00911         {
00912             dst[bidx^2] = src.x * c_XYZ2sRGB_D65f[0] + src.y * c_XYZ2sRGB_D65f[1] + src.z * c_XYZ2sRGB_D65f[2];
00913             dst[1]      = src.x * c_XYZ2sRGB_D65f[3] + src.y * c_XYZ2sRGB_D65f[4] + src.z * c_XYZ2sRGB_D65f[5];
00914             dst[bidx]   = src.x * c_XYZ2sRGB_D65f[6] + src.y * c_XYZ2sRGB_D65f[7] + src.z * c_XYZ2sRGB_D65f[8];
00915         }
00916 
00917         template <typename T, int scn, int dcn, int bidx> struct XYZ2RGB
00918             : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
00919         {
00920             __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator()(const typename TypeVec<T, scn>::vec_type& src) const
00921             {
00922                 typename TypeVec<T, dcn>::vec_type dst;
00923 
00924                 XYZ2RGBConvert<bidx>(src, &dst.x);
00925                 setAlpha(dst, ColorChannel<T>::max());
00926 
00927                 return dst;
00928             }
00929             __device__ __forceinline__ XYZ2RGB()
00930                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00931             __device__ __forceinline__ XYZ2RGB(const XYZ2RGB& other_)
00932                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00933         };
00934 
00935         template <int bidx> struct XYZ2RGB<uchar, 4, 4, bidx> : unary_function<uint, uint>
00936         {
00937             __device__ __forceinline__ uint operator()(uint src) const
00938             {
00939                 return XYZ2RGBConvert<bidx>(src);
00940             }
00941             __device__ __forceinline__ XYZ2RGB() : unary_function<uint, uint>(){}
00942             __device__ __forceinline__ XYZ2RGB(const XYZ2RGB& other_) : unary_function<uint, uint>(){}
00943         };
00944     }
00945 
00946 #define OPENCV_GPU_IMPLEMENT_XYZ2RGB_TRAITS(name, scn, dcn, bidx) \
00947     template <typename T> struct name ## _traits \
00948     { \
00949         typedef ::cv::gpu::device::color_detail::XYZ2RGB<T, scn, dcn, bidx> functor_type; \
00950         static __host__ __device__ __forceinline__ functor_type create_functor() \
00951         { \
00952             return functor_type(); \
00953         } \
00954     };
00955 
00957 
00958     namespace color_detail
00959     {
00960         __constant__ int c_HsvDivTable   [256] = {0, 1044480, 522240, 348160, 261120, 208896, 174080, 149211, 130560, 116053, 104448, 94953, 87040, 80345, 74606, 69632, 65280, 61440, 58027, 54973, 52224, 49737, 47476, 45412, 43520, 41779, 40172, 38684, 37303, 36017, 34816, 33693, 32640, 31651, 30720, 29842, 29013, 28229, 27486, 26782, 26112, 25475, 24869, 24290, 23738, 23211, 22706, 22223, 21760, 21316, 20890, 20480, 20086, 19707, 19342, 18991, 18651, 18324, 18008, 17703, 17408, 17123, 16846, 16579, 16320, 16069, 15825, 15589, 15360, 15137, 14921, 14711, 14507, 14308, 14115, 13926, 13743, 13565, 13391, 13221, 13056, 12895, 12738, 12584, 12434, 12288, 12145, 12006, 11869, 11736, 11605, 11478, 11353, 11231, 11111, 10995, 10880, 10768, 10658, 10550, 10445, 10341, 10240, 10141, 10043, 9947, 9854, 9761, 9671, 9582, 9495, 9410, 9326, 9243, 9162, 9082, 9004, 8927, 8852, 8777, 8704, 8632, 8561, 8492, 8423, 8356, 8290, 8224, 8160, 8097, 8034, 7973, 7913, 7853, 7795, 7737, 7680, 7624, 7569, 7514, 7461, 7408, 7355, 7304, 7253, 7203, 7154, 7105, 7057, 7010, 6963, 6917, 6872, 6827, 6782, 6739, 6695, 6653, 6611, 6569, 6528, 6487, 6447, 6408, 6369, 6330, 6292, 6254, 6217, 6180, 6144, 6108, 6073, 6037, 6003, 5968, 5935, 5901, 5868, 5835, 5803, 5771, 5739, 5708, 5677, 5646, 5615, 5585, 5556, 5526, 5497, 5468, 5440, 5412, 5384, 5356, 5329, 5302, 5275, 5249, 5222, 5196, 5171, 5145, 5120, 5095, 5070, 5046, 5022, 4998, 4974, 4950, 4927, 4904, 4881, 4858, 4836, 4813, 4791, 4769, 4748, 4726, 4705, 4684, 4663, 4642, 4622, 4601, 4581, 4561, 4541, 4522, 4502, 4483, 4464, 4445, 4426, 4407, 4389, 4370, 4352, 4334, 4316, 4298, 4281, 4263, 4246, 4229, 4212, 4195, 4178, 4161, 4145, 4128, 4112, 4096};
00961         __constant__ int c_HsvDivTable180[256] = {0, 122880, 61440, 40960, 30720, 24576, 20480, 17554, 15360, 13653, 12288, 11171, 10240, 9452, 8777, 8192, 7680, 7228, 6827, 6467, 6144, 5851, 5585, 5343, 5120, 4915, 4726, 4551, 4389, 4237, 4096, 3964, 3840, 3724, 3614, 3511, 3413, 3321, 3234, 3151, 3072, 2997, 2926, 2858, 2793, 2731, 2671, 2614, 2560, 2508, 2458, 2409, 2363, 2318, 2276, 2234, 2194, 2156, 2119, 2083, 2048, 2014, 1982, 1950, 1920, 1890, 1862, 1834, 1807, 1781, 1755, 1731, 1707, 1683, 1661, 1638, 1617, 1596, 1575, 1555, 1536, 1517, 1499, 1480, 1463, 1446, 1429, 1412, 1396, 1381, 1365, 1350, 1336, 1321, 1307, 1293, 1280, 1267, 1254, 1241, 1229, 1217, 1205, 1193, 1182, 1170, 1159, 1148, 1138, 1127, 1117, 1107, 1097, 1087, 1078, 1069, 1059, 1050, 1041, 1033, 1024, 1016, 1007, 999, 991, 983, 975, 968, 960, 953, 945, 938, 931, 924, 917, 910, 904, 897, 890, 884, 878, 871, 865, 859, 853, 847, 842, 836, 830, 825, 819, 814, 808, 803, 798, 793, 788, 783, 778, 773, 768, 763, 759, 754, 749, 745, 740, 736, 731, 727, 723, 719, 714, 710, 706, 702, 698, 694, 690, 686, 683, 679, 675, 671, 668, 664, 661, 657, 654, 650, 647, 643, 640, 637, 633, 630, 627, 624, 621, 617, 614, 611, 608, 605, 602, 599, 597, 594, 591, 588, 585, 582, 580, 577, 574, 572, 569, 566, 564, 561, 559, 556, 554, 551, 549, 546, 544, 541, 539, 537, 534, 532, 530, 527, 525, 523, 521, 518, 516, 514, 512, 510, 508, 506, 504, 502, 500, 497, 495, 493, 492, 490, 488, 486, 484, 482};
00962         __constant__ int c_HsvDivTable256[256] = {0, 174763, 87381, 58254, 43691, 34953, 29127, 24966, 21845, 19418, 17476, 15888, 14564, 13443, 12483, 11651, 10923, 10280, 9709, 9198, 8738, 8322, 7944, 7598, 7282, 6991, 6722, 6473, 6242, 6026, 5825, 5638, 5461, 5296, 5140, 4993, 4855, 4723, 4599, 4481, 4369, 4263, 4161, 4064, 3972, 3884, 3799, 3718, 3641, 3567, 3495, 3427, 3361, 3297, 3236, 3178, 3121, 3066, 3013, 2962, 2913, 2865, 2819, 2774, 2731, 2689, 2648, 2608, 2570, 2533, 2497, 2461, 2427, 2394, 2362, 2330, 2300, 2270, 2241, 2212, 2185, 2158, 2131, 2106, 2081, 2056, 2032, 2009, 1986, 1964, 1942, 1920, 1900, 1879, 1859, 1840, 1820, 1802, 1783, 1765, 1748, 1730, 1713, 1697, 1680, 1664, 1649, 1633, 1618, 1603, 1589, 1574, 1560, 1547, 1533, 1520, 1507, 1494, 1481, 1469, 1456, 1444, 1432, 1421, 1409, 1398, 1387, 1376, 1365, 1355, 1344, 1334, 1324, 1314, 1304, 1295, 1285, 1276, 1266, 1257, 1248, 1239, 1231, 1222, 1214, 1205, 1197, 1189, 1181, 1173, 1165, 1157, 1150, 1142, 1135, 1128, 1120, 1113, 1106, 1099, 1092, 1085, 1079, 1072, 1066, 1059, 1053, 1046, 1040, 1034, 1028, 1022, 1016, 1010, 1004, 999, 993, 987, 982, 976, 971, 966, 960, 955, 950, 945, 940, 935, 930, 925, 920, 915, 910, 906, 901, 896, 892, 887, 883, 878, 874, 869, 865, 861, 857, 853, 848, 844, 840, 836, 832, 828, 824, 820, 817, 813, 809, 805, 802, 798, 794, 791, 787, 784, 780, 777, 773, 770, 767, 763, 760, 757, 753, 750, 747, 744, 741, 737, 734, 731, 728, 725, 722, 719, 716, 713, 710, 708, 705, 702, 699, 696, 694, 691, 688, 685};
00963 
00964         template <int bidx, int hr, typename D> static __device__ void RGB2HSVConvert(const uchar* src, D& dst)
00965         {
00966             const int hsv_shift = 12;
00967             const int* hdiv_table = hr == 180 ? c_HsvDivTable180 : c_HsvDivTable256;
00968 
00969             int b = src[bidx], g = src[1], r = src[bidx^2];
00970             int h, s, v = b;
00971             int vmin = b, diff;
00972             int vr, vg;
00973 
00974             v = ::max(v, g);
00975             v = ::max(v, r);
00976             vmin = ::min(vmin, g);
00977             vmin = ::min(vmin, r);
00978 
00979             diff = v - vmin;
00980             vr = (v == r) * -1;
00981             vg = (v == g) * -1;
00982 
00983             s = (diff * c_HsvDivTable[v] + (1 << (hsv_shift-1))) >> hsv_shift;
00984             h = (vr & (g - b)) + (~vr & ((vg & (b - r + 2 * diff)) + ((~vg) & (r - g + 4 * diff))));
00985             h = (h * hdiv_table[diff] + (1 << (hsv_shift-1))) >> hsv_shift;
00986             h += (h < 0) * hr;
00987 
00988             dst.x = saturate_cast<uchar>(h);
00989             dst.y = (uchar)s;
00990             dst.z = (uchar)v;
00991         }
00992 
00993         template <int bidx, int hr> static __device__ uint RGB2HSVConvert(uint src)
00994         {
00995             const int hsv_shift = 12;
00996             const int* hdiv_table = hr == 180 ? c_HsvDivTable180 : c_HsvDivTable256;
00997 
00998             const int b = 0xff & (src >> (bidx * 8));
00999             const int g = 0xff & (src >> 8);
01000             const int r = 0xff & (src >> ((bidx ^ 2) * 8));
01001 
01002             int h, s, v = b;
01003             int vmin = b, diff;
01004             int vr, vg;
01005 
01006             v = ::max(v, g);
01007             v = ::max(v, r);
01008             vmin = ::min(vmin, g);
01009             vmin = ::min(vmin, r);
01010 
01011             diff = v - vmin;
01012             vr = (v == r) * -1;
01013             vg = (v == g) * -1;
01014 
01015             s = (diff * c_HsvDivTable[v] + (1 << (hsv_shift-1))) >> hsv_shift;
01016             h = (vr & (g - b)) + (~vr & ((vg & (b - r + 2 * diff)) + ((~vg) & (r - g + 4 * diff))));
01017             h = (h * hdiv_table[diff] + (1 << (hsv_shift-1))) >> hsv_shift;
01018             h += (h < 0) * hr;
01019 
01020             uint dst = 0;
01021 
01022             dst |= saturate_cast<uchar>(h);
01023             dst |= (0xffu & s) << 8;
01024             dst |= (0xffu & v) << 16;
01025 
01026             return dst;
01027         }
01028 
01029         template <int bidx, int hr, typename D> static __device__ void RGB2HSVConvert(const float* src, D& dst)
01030         {
01031             const float hscale = hr * (1.f / 360.f);
01032 
01033             float b = src[bidx], g = src[1], r = src[bidx^2];
01034             float h, s, v;
01035 
01036             float vmin, diff;
01037 
01038             v = vmin = r;
01039             v = fmax(v, g);
01040             v = fmax(v, b);
01041             vmin = fmin(vmin, g);
01042             vmin = fmin(vmin, b);
01043 
01044             diff = v - vmin;
01045             s = diff / (float)(::fabs(v) + numeric_limits<float>::epsilon());
01046             diff = (float)(60. / (diff + numeric_limits<float>::epsilon()));
01047 
01048             h  = (v == r) * (g - b) * diff;
01049             h += (v != r && v == g) * ((b - r) * diff + 120.f);
01050             h += (v != r && v != g) * ((r - g) * diff + 240.f);
01051             h += (h < 0) * 360.f;
01052 
01053             dst.x = h * hscale;
01054             dst.y = s;
01055             dst.z = v;
01056         }
01057 
01058         template <typename T, int scn, int dcn, int bidx, int hr> struct RGB2HSV
01059             : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
01060         {
01061             __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator()(const typename TypeVec<T, scn>::vec_type& src) const
01062             {
01063                 typename TypeVec<T, dcn>::vec_type dst;
01064 
01065                 RGB2HSVConvert<bidx, hr>(&src.x, dst);
01066 
01067                 return dst;
01068             }
01069             __device__ __forceinline__ RGB2HSV()
01070                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
01071             __device__ __forceinline__ RGB2HSV(const RGB2HSV& other_)
01072                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
01073         };
01074 
01075         template <int bidx, int hr> struct RGB2HSV<uchar, 4, 4, bidx, hr> : unary_function<uint, uint>
01076         {
01077             __device__ __forceinline__ uint operator()(uint src) const
01078             {
01079                 return RGB2HSVConvert<bidx, hr>(src);
01080             }
01081             __device__ __forceinline__ RGB2HSV():unary_function<uint, uint>(){}
01082             __device__ __forceinline__ RGB2HSV(const RGB2HSV& other_):unary_function<uint, uint>(){}
01083         };
01084     }
01085 
01086 #define OPENCV_GPU_IMPLEMENT_RGB2HSV_TRAITS(name, scn, dcn, bidx) \
01087     template <typename T> struct name ## _traits \
01088     { \
01089         typedef ::cv::gpu::device::color_detail::RGB2HSV<T, scn, dcn, bidx, 180> functor_type; \
01090         static __host__ __device__ __forceinline__ functor_type create_functor() \
01091         { \
01092             return functor_type(); \
01093         } \
01094     }; \
01095     template <typename T> struct name ## _full_traits \
01096     { \
01097         typedef ::cv::gpu::device::color_detail::RGB2HSV<T, scn, dcn, bidx, 256> functor_type; \
01098         static __host__ __device__ __forceinline__ functor_type create_functor() \
01099         { \
01100             return functor_type(); \
01101         } \
01102     }; \
01103     template <> struct name ## _traits<float> \
01104     { \
01105         typedef ::cv::gpu::device::color_detail::RGB2HSV<float, scn, dcn, bidx, 360> functor_type; \
01106         static __host__ __device__ __forceinline__ functor_type create_functor() \
01107         { \
01108             return functor_type(); \
01109         } \
01110     }; \
01111     template <> struct name ## _full_traits<float> \
01112     { \
01113         typedef ::cv::gpu::device::color_detail::RGB2HSV<float, scn, dcn, bidx, 360> functor_type; \
01114         static __host__ __device__ __forceinline__ functor_type create_functor() \
01115         { \
01116             return functor_type(); \
01117         } \
01118     };
01119 
01120     namespace color_detail
01121     {
01122         __constant__ int c_HsvSectorData[6][3] = { {1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0} };
01123 
01124         template <int bidx, int hr, typename T> static __device__ void HSV2RGBConvert(const T& src, float* dst)
01125         {
01126             const float hscale = 6.f / hr;
01127 
01128             float h = src.x, s = src.y, v = src.z;
01129             float b = v, g = v, r = v;
01130 
01131             if (s != 0)
01132             {
01133                 h *= hscale;
01134 
01135                 if( h < 0 )
01136                     do h += 6; while( h < 0 );
01137                 else if( h >= 6 )
01138                     do h -= 6; while( h >= 6 );
01139 
01140                 int sector = __float2int_rd(h);
01141                 h -= sector;
01142 
01143                 if ( (unsigned)sector >= 6u )
01144                 {
01145                     sector = 0;
01146                     h = 0.f;
01147                 }
01148 
01149                 float tab[4];
01150                 tab[0] = v;
01151                 tab[1] = v * (1.f - s);
01152                 tab[2] = v * (1.f - s * h);
01153                 tab[3] = v * (1.f - s * (1.f - h));
01154 
01155                 b = tab[c_HsvSectorData[sector][0]];
01156                 g = tab[c_HsvSectorData[sector][1]];
01157                 r = tab[c_HsvSectorData[sector][2]];
01158             }
01159 
01160             dst[bidx] = b;
01161             dst[1] = g;
01162             dst[bidx^2] = r;
01163         }
01164 
01165         template <int bidx, int HR, typename T> static __device__ void HSV2RGBConvert(const T& src, uchar* dst)
01166         {
01167             float3 buf;
01168 
01169             buf.x = src.x;
01170             buf.y = src.y * (1.f / 255.f);
01171             buf.z = src.z * (1.f / 255.f);
01172 
01173             HSV2RGBConvert<bidx, HR>(buf, &buf.x);
01174 
01175             dst[0] = saturate_cast<uchar>(buf.x * 255.f);
01176             dst[1] = saturate_cast<uchar>(buf.y * 255.f);
01177             dst[2] = saturate_cast<uchar>(buf.z * 255.f);
01178         }
01179 
01180         template <int bidx, int hr> static __device__ uint HSV2RGBConvert(uint src)
01181         {
01182             float3 buf;
01183 
01184             buf.x = src & 0xff;
01185             buf.y = ((src >> 8) & 0xff) * (1.f/255.f);
01186             buf.z = ((src >> 16) & 0xff) * (1.f/255.f);
01187 
01188             HSV2RGBConvert<bidx, hr>(buf, &buf.x);
01189 
01190             uint dst = 0xffu << 24;
01191 
01192             dst |= saturate_cast<uchar>(buf.x * 255.f);
01193             dst |= saturate_cast<uchar>(buf.y * 255.f) << 8;
01194             dst |= saturate_cast<uchar>(buf.z * 255.f) << 16;
01195 
01196             return dst;
01197         }
01198 
01199         template <typename T, int scn, int dcn, int bidx, int hr> struct HSV2RGB
01200             : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
01201         {
01202             __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator()(const typename TypeVec<T, scn>::vec_type& src) const
01203             {
01204                 typename TypeVec<T, dcn>::vec_type dst;
01205 
01206                 HSV2RGBConvert<bidx, hr>(src, &dst.x);
01207                 setAlpha(dst, ColorChannel<T>::max());
01208 
01209                 return dst;
01210             }
01211             __device__ __forceinline__ HSV2RGB()
01212                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
01213             __device__ __forceinline__ HSV2RGB(const HSV2RGB& other_)
01214                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
01215         };
01216 
01217         template <int bidx, int hr> struct HSV2RGB<uchar, 4, 4, bidx, hr> : unary_function<uint, uint>
01218         {
01219             __device__ __forceinline__ uint operator()(uint src) const
01220             {
01221                 return HSV2RGBConvert<bidx, hr>(src);
01222             }
01223             __device__ __forceinline__ HSV2RGB():unary_function<uint, uint>(){}
01224             __device__ __forceinline__ HSV2RGB(const HSV2RGB& other_):unary_function<uint, uint>(){}
01225         };
01226     }
01227 
01228 #define OPENCV_GPU_IMPLEMENT_HSV2RGB_TRAITS(name, scn, dcn, bidx) \
01229     template <typename T> struct name ## _traits \
01230     { \
01231         typedef ::cv::gpu::device::color_detail::HSV2RGB<T, scn, dcn, bidx, 180> functor_type; \
01232         static __host__ __device__ __forceinline__ functor_type create_functor() \
01233         { \
01234             return functor_type(); \
01235         } \
01236     }; \
01237     template <typename T> struct name ## _full_traits \
01238     { \
01239         typedef ::cv::gpu::device::color_detail::HSV2RGB<T, scn, dcn, bidx, 255> functor_type; \
01240         static __host__ __device__ __forceinline__ functor_type create_functor() \
01241         { \
01242             return functor_type(); \
01243         } \
01244     }; \
01245     template <> struct name ## _traits<float> \
01246     { \
01247         typedef ::cv::gpu::device::color_detail::HSV2RGB<float, scn, dcn, bidx, 360> functor_type; \
01248         static __host__ __device__ __forceinline__ functor_type create_functor() \
01249         { \
01250             return functor_type(); \
01251         } \
01252     }; \
01253     template <> struct name ## _full_traits<float> \
01254     { \
01255         typedef ::cv::gpu::device::color_detail::HSV2RGB<float, scn, dcn, bidx, 360> functor_type; \
01256         static __host__ __device__ __forceinline__ functor_type create_functor() \
01257         { \
01258             return functor_type(); \
01259         } \
01260     };
01261 
01263 
01264     namespace color_detail
01265     {
01266         template <int bidx, int hr, typename D> static __device__ void RGB2HLSConvert(const float* src, D& dst)
01267         {
01268             const float hscale = hr * (1.f / 360.f);
01269 
01270             float b = src[bidx], g = src[1], r = src[bidx^2];
01271             float h = 0.f, s = 0.f, l;
01272             float vmin, vmax, diff;
01273 
01274             vmax = vmin = r;
01275             vmax = fmax(vmax, g);
01276             vmax = fmax(vmax, b);
01277             vmin = fmin(vmin, g);
01278             vmin = fmin(vmin, b);
01279 
01280             diff = vmax - vmin;
01281             l = (vmax + vmin) * 0.5f;
01282 
01283             if (diff > numeric_limits<float>::epsilon())
01284             {
01285                 s = (l < 0.5f) * diff / (vmax + vmin);
01286                 s += (l >= 0.5f) * diff / (2.0f - vmax - vmin);
01287 
01288                 diff = 60.f / diff;
01289 
01290                 h  = (vmax == r) * (g - b) * diff;
01291                 h += (vmax != r && vmax == g) * ((b - r) * diff + 120.f);
01292                 h += (vmax != r && vmax != g) * ((r - g) * diff + 240.f);
01293                 h += (h < 0.f) * 360.f;
01294             }
01295 
01296             dst.x = h * hscale;
01297             dst.y = l;
01298             dst.z = s;
01299         }
01300 
01301         template <int bidx, int hr, typename D> static __device__ void RGB2HLSConvert(const uchar* src, D& dst)
01302         {
01303             float3 buf;
01304 
01305             buf.x = src[0] * (1.f / 255.f);
01306             buf.y = src[1] * (1.f / 255.f);
01307             buf.z = src[2] * (1.f / 255.f);
01308 
01309             RGB2HLSConvert<bidx, hr>(&buf.x, buf);
01310 
01311             dst.x = saturate_cast<uchar>(buf.x);
01312             dst.y = saturate_cast<uchar>(buf.y*255.f);
01313             dst.z = saturate_cast<uchar>(buf.z*255.f);
01314         }
01315 
01316         template <int bidx, int hr> static __device__ uint RGB2HLSConvert(uint src)
01317         {
01318             float3 buf;
01319 
01320             buf.x = (0xff & src) * (1.f / 255.f);
01321             buf.y = (0xff & (src >> 8)) * (1.f / 255.f);
01322             buf.z = (0xff & (src >> 16)) * (1.f / 255.f);
01323 
01324             RGB2HLSConvert<bidx, hr>(&buf.x, buf);
01325 
01326             uint dst = 0xffu << 24;
01327 
01328             dst |= saturate_cast<uchar>(buf.x);
01329             dst |= saturate_cast<uchar>(buf.y * 255.f) << 8;
01330             dst |= saturate_cast<uchar>(buf.z * 255.f) << 16;
01331 
01332             return dst;
01333         }
01334 
01335         template <typename T, int scn, int dcn, int bidx, int hr> struct RGB2HLS
01336             : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
01337         {
01338             __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator()(const typename TypeVec<T, scn>::vec_type& src) const
01339             {
01340                 typename TypeVec<T, dcn>::vec_type dst;
01341 
01342                 RGB2HLSConvert<bidx, hr>(&src.x, dst);
01343 
01344                 return dst;
01345             }
01346             __device__ __forceinline__ RGB2HLS()
01347                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
01348             __device__ __forceinline__ RGB2HLS(const RGB2HLS& other_)
01349                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
01350         };
01351 
01352         template <int bidx, int hr> struct RGB2HLS<uchar, 4, 4, bidx, hr> : unary_function<uint, uint>
01353         {
01354             __device__ __forceinline__ uint operator()(uint src) const
01355             {
01356                 return RGB2HLSConvert<bidx, hr>(src);
01357             }
01358             __device__ __forceinline__ RGB2HLS() : unary_function<uint, uint>(){}
01359             __device__ __forceinline__ RGB2HLS(const RGB2HLS& other_) : unary_function<uint, uint>(){}
01360         };
01361     }
01362 
01363 #define OPENCV_GPU_IMPLEMENT_RGB2HLS_TRAITS(name, scn, dcn, bidx) \
01364     template <typename T> struct name ## _traits \
01365     { \
01366         typedef ::cv::gpu::device::color_detail::RGB2HLS<T, scn, dcn, bidx, 180> functor_type; \
01367         static __host__ __device__ __forceinline__ functor_type create_functor() \
01368         { \
01369             return functor_type(); \
01370         } \
01371     }; \
01372     template <typename T> struct name ## _full_traits \
01373     { \
01374         typedef ::cv::gpu::device::color_detail::RGB2HLS<T, scn, dcn, bidx, 256> functor_type; \
01375         static __host__ __device__ __forceinline__ functor_type create_functor() \
01376         { \
01377             return functor_type(); \
01378         } \
01379     }; \
01380     template <> struct name ## _traits<float> \
01381     { \
01382         typedef ::cv::gpu::device::color_detail::RGB2HLS<float, scn, dcn, bidx, 360> functor_type; \
01383         static __host__ __device__ __forceinline__ functor_type create_functor() \
01384         { \
01385             return functor_type(); \
01386         } \
01387     }; \
01388     template <> struct name ## _full_traits<float> \
01389     { \
01390         typedef ::cv::gpu::device::color_detail::RGB2HLS<float, scn, dcn, bidx, 360> functor_type; \
01391         static __host__ __device__ __forceinline__ functor_type create_functor() \
01392         { \
01393             return functor_type(); \
01394         } \
01395     };
01396 
01397     namespace color_detail
01398     {
01399         __constant__ int c_HlsSectorData[6][3] = { {1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0} };
01400 
01401         template <int bidx, int hr, typename T> static __device__ void HLS2RGBConvert(const T& src, float* dst)
01402         {
01403             const float hscale = 6.0f / hr;
01404 
01405             float h = src.x, l = src.y, s = src.z;
01406             float b = l, g = l, r = l;
01407 
01408             if (s != 0)
01409             {
01410                 float p2  = (l <= 0.5f) * l * (1 + s);
01411                       p2 += (l > 0.5f) * (l + s - l * s);
01412                 float p1 = 2 * l - p2;
01413 
01414                 h *= hscale;
01415 
01416                 if( h < 0 )
01417                     do h += 6; while( h < 0 );
01418                 else if( h >= 6 )
01419                     do h -= 6; while( h >= 6 );
01420 
01421                 int sector;
01422                 sector = __float2int_rd(h);
01423 
01424                 h -= sector;
01425 
01426                 float tab[4];
01427                 tab[0] = p2;
01428                 tab[1] = p1;
01429                 tab[2] = p1 + (p2 - p1) * (1 - h);
01430                 tab[3] = p1 + (p2 - p1) * h;
01431 
01432                 b = tab[c_HlsSectorData[sector][0]];
01433                 g = tab[c_HlsSectorData[sector][1]];
01434                 r = tab[c_HlsSectorData[sector][2]];
01435             }
01436 
01437             dst[bidx] = b;
01438             dst[1] = g;
01439             dst[bidx^2] = r;
01440         }
01441 
01442         template <int bidx, int hr, typename T> static __device__ void HLS2RGBConvert(const T& src, uchar* dst)
01443         {
01444             float3 buf;
01445 
01446             buf.x = src.x;
01447             buf.y = src.y * (1.f / 255.f);
01448             buf.z = src.z * (1.f / 255.f);
01449 
01450             HLS2RGBConvert<bidx, hr>(buf, &buf.x);
01451 
01452             dst[0] = saturate_cast<uchar>(buf.x * 255.f);
01453             dst[1] = saturate_cast<uchar>(buf.y * 255.f);
01454             dst[2] = saturate_cast<uchar>(buf.z * 255.f);
01455         }
01456 
01457         template <int bidx, int hr> static __device__ uint HLS2RGBConvert(uint src)
01458         {
01459             float3 buf;
01460 
01461             buf.x = 0xff & src;
01462             buf.y = (0xff & (src >> 8)) * (1.f / 255.f);
01463             buf.z = (0xff & (src >> 16)) * (1.f / 255.f);
01464 
01465             HLS2RGBConvert<bidx, hr>(buf, &buf.x);
01466 
01467             uint dst = 0xffu << 24;
01468 
01469             dst |= saturate_cast<uchar>(buf.x * 255.f);
01470             dst |= saturate_cast<uchar>(buf.y * 255.f) << 8;
01471             dst |= saturate_cast<uchar>(buf.z * 255.f) << 16;
01472 
01473             return dst;
01474         }
01475 
01476         template <typename T, int scn, int dcn, int bidx, int hr> struct HLS2RGB
01477             : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
01478         {
01479             __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator()(const typename TypeVec<T, scn>::vec_type& src) const
01480             {
01481                 typename TypeVec<T, dcn>::vec_type dst;
01482 
01483                 HLS2RGBConvert<bidx, hr>(src, &dst.x);
01484                 setAlpha(dst, ColorChannel<T>::max());
01485 
01486                 return dst;
01487             }
01488             __device__ __forceinline__ HLS2RGB()
01489                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
01490             __device__ __forceinline__ HLS2RGB(const HLS2RGB& other_)
01491                 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
01492         };
01493 
01494         template <int bidx, int hr> struct HLS2RGB<uchar, 4, 4, bidx, hr> : unary_function<uint, uint>
01495         {
01496             __device__ __forceinline__ uint operator()(uint src) const
01497             {
01498                 return HLS2RGBConvert<bidx, hr>(src);
01499             }
01500             __device__ __forceinline__ HLS2RGB() : unary_function<uint, uint>(){}
01501             __device__ __forceinline__ HLS2RGB(const HLS2RGB& other_) : unary_function<uint, uint>(){}
01502         };
01503     }
01504 
01505 #define OPENCV_GPU_IMPLEMENT_HLS2RGB_TRAITS(name, scn, dcn, bidx) \
01506     template <typename T> struct name ## _traits \
01507     { \
01508         typedef ::cv::gpu::device::color_detail::HLS2RGB<T, scn, dcn, bidx, 180> functor_type; \
01509         static __host__ __device__ __forceinline__ functor_type create_functor() \
01510         { \
01511             return functor_type(); \
01512         } \
01513     }; \
01514     template <typename T> struct name ## _full_traits \
01515     { \
01516         typedef ::cv::gpu::device::color_detail::HLS2RGB<T, scn, dcn, bidx, 255> functor_type; \
01517         static __host__ __device__ __forceinline__ functor_type create_functor() \
01518         { \
01519             return functor_type(); \
01520         } \
01521     }; \
01522     template <> struct name ## _traits<float> \
01523     { \
01524         typedef ::cv::gpu::device::color_detail::HLS2RGB<float, scn, dcn, bidx, 360> functor_type; \
01525         static __host__ __device__ __forceinline__ functor_type create_functor() \
01526         { \
01527             return functor_type(); \
01528         } \
01529     }; \
01530     template <> struct name ## _full_traits<float> \
01531     { \
01532         typedef ::cv::gpu::device::color_detail::HLS2RGB<float, scn, dcn, bidx, 360> functor_type; \
01533         static __host__ __device__ __forceinline__ functor_type create_functor() \
01534         { \
01535             return functor_type(); \
01536         } \
01537     };
01538 
01539     #undef CV_DESCALE
01540 }}} // namespace cv { namespace gpu { namespace device
01541 
01542 #endif // __OPENCV_GPU_COLOR_DETAIL_HPP__