aihot  2017-05-23 23:26:42  云计算 |   查看评论   
实现代码cvtColor.hpp:
  1. // fbc_cv是免费软件,并且使用与OpenCV相同的许可证  
  2. #ifndef FBC_CV_CVTCOLOR_HPP_  
  3. #define FBC_CV_CVTCOLOR_HPP_  
  4.   
  5. // reference: include/opencv2/imgproc.hpp  
  6.   
  7. #include "core/mat.hpp"  
  8. #include "core/saturate.hpp"  
  9. #include "imgproc.hpp"  
  10. #include "core/core.hpp"  
  11.   
  12. namespace fbc {  
  13. #define  FBC_DESCALE(x,n)     (((x) + (1 << ((n)-1))) >> (n))  
  14.   
  15. template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx);  
  16. template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2Gray(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx);  
  17. template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_Gray2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst);  
  18. template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2YCrCb(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs_f, const int* coeffs_i);  
  19. template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_YCrCb2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs_f, const int* coeffs_i);  
  20. template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2XYZ(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx);  
  21. template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_XYZ2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx);  
  22. template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2HSV(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, int hrange);  
  23. template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2HLS(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, int hrange);  
  24. template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_HSV2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, int hrange);  
  25. template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_HLS2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, int hrange);  
  26. template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2Lab(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs, const float* whitept, bool srgb);  
  27. template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2Luv(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs, const float* whitept, bool srgb);  
  28. template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_Lab2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs, const float* whitept, bool srgb);  
  29. template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_Luv2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs, const float* whitept, bool srgb);  
  30.   
  31.   
  32. // 将图像从一个颜色空间转换为另一个
  33. // 支持类型:uchar / ushort / float
  34. template<typename _Tp, int chs1, int chs2>  
  35. int cvtColor(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int code)  
  36. {  
  37.     FBC_Assert(src.cols > 0 &&  src.rows > 0 && dst.cols > 0 && dst.rows > 0);  
  38.     FBC_Assert(src.cols == dst.cols);  
  39.     FBC_Assert(src.data != NULL && dst.data != NULL);  
  40.     FBC_Assert((sizeof(_Tp) == 1) || sizeof(_Tp) == 2 || sizeof(_Tp) == 4); // uchar || ushort || float  
  41.   
  42.     int scn = src.channels;  
  43.     int dcn = dst.channels; // 目的地图像中的频道数量
  44.     Size sz = src.size();  
  45.     Size dz = dst.size();  
  46.     int bidx;  
  47.   
  48.     switch (code) {  
  49.         case CV_BGR2BGRA: case CV_RGB2BGRA: case CV_BGRA2BGR:  
  50.         case CV_RGBA2BGR: case CV_RGB2BGR: case CV_BGRA2RGBA: {  
  51.             FBC_Assert(scn == 3 || scn == 4);  
  52.             dcn = code == CV_BGR2BGRA || code == CV_RGB2BGRA || code == CV_BGRA2RGBA ? 4 : 3;  
  53.             FBC_Assert(dst.channels == dcn);  
  54.             bidx = code == CV_BGR2BGRA || code == CV_BGRA2BGR ? 0 : 2;  
  55.   
  56.             CvtColorLoop_RGB2RGB(src, dst, bidx); // uchar/ushort/float  
  57.             break;  
  58.         }  
  59.         case CV_BGR2GRAY: case CV_BGRA2GRAY: case CV_RGB2GRAY: case CV_RGBA2GRAY: {  
  60.             FBC_Assert(scn == 3 || scn == 4);  
  61.             FBC_Assert(dst.channels == 1);  
  62.             bidx = code == CV_BGR2GRAY || code == CV_BGRA2GRAY ? 0 : 2;  
  63.   
  64.             CvtColorLoop_RGB2Gray(src, dst, bidx);  
  65.             break;  
  66.         }  
  67.         case CV_GRAY2BGR: case CV_GRAY2BGRA: {  
  68.             FBC_Assert(scn == 1 && (dcn == 3 || dcn == 4));  
  69.   
  70.             CvtColorLoop_Gray2RGB(src, dst);  
  71.             break;  
  72.         }  
  73.         case CV_BGR2YCrCb: case CV_RGB2YCrCb:  
  74.         case CV_BGR2YUV: case CV_RGB2YUV: {  
  75.             FBC_Assert(scn == 3 || scn == 4);  
  76.             bidx = code == CV_BGR2YCrCb || code == CV_BGR2YUV ? 0 : 2;  
  77.             static const float yuv_f[] = { 0.114f, 0.587f, 0.299f, 0.492f, 0.877f };  
  78.             static const int yuv_i[] = { B2Y, G2Y, R2Y, 8061, 14369 };  
  79.             const float* coeffs_f = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_f;  
  80.             const int* coeffs_i = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_i;  
  81.   
  82.             CvtColorLoop_RGB2YCrCb(src, dst, bidx, coeffs_f, coeffs_i);  
  83.             break;  
  84.         }  
  85.         case CV_YCrCb2BGR: case CV_YCrCb2RGB:  
  86.         case CV_YUV2BGR: case CV_YUV2RGB: {  
  87.             FBC_Assert(scn == 3 && (dcn == 3 || dcn == 4));  
  88.             bidx = code == CV_YCrCb2BGR || code == CV_YUV2BGR ? 0 : 2;  
  89.             static const float yuv_f[] = { 2.032f, -0.395f, -0.581f, 1.140f };  
  90.             static const int yuv_i[] = { 33292, -6472, -9519, 18678 };  
  91.             const float* coeffs_f = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_f;  
  92.             const int* coeffs_i = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_i;  
  93.   
  94.             CvtColorLoop_YCrCb2RGB(src, dst, bidx, coeffs_f, coeffs_i);  
  95.             break;  
  96.         }  
  97.         case CV_BGR2XYZ: case CV_RGB2XYZ: {  
  98.             FBC_Assert(scn == 3 || scn == 4);  
  99.             bidx = code == CV_BGR2XYZ ? 0 : 2;  
  100.   
  101.             CvtColorLoop_RGB2XYZ(src, dst, bidx);  
  102.             break;  
  103.         }  
  104.         case CV_XYZ2BGR: case CV_XYZ2RGB: {  
  105.             FBC_Assert(scn == 3 && (dcn == 3 || dcn == 4));  
  106.             bidx = code == CV_XYZ2BGR ? 0 : 2;  
  107.   
  108.             CvtColorLoop_XYZ2RGB(src, dst, bidx);  
  109.             break;  
  110.         }  
  111.         case CV_BGR2HSV: case CV_RGB2HSV: case CV_BGR2HSV_FULL: case CV_RGB2HSV_FULL:  
  112.         case CV_BGR2HLS: case CV_RGB2HLS: case CV_BGR2HLS_FULL: case CV_RGB2HLS_FULL: {  
  113.             FBC_Assert(scn == 3 || scn == 4);  
  114.             FBC_Assert(sizeof(_Tp) == 1 || sizeof(_Tp) == 4);  
  115.             bidx = code == CV_BGR2HSV || code == CV_BGR2HLS ||  
  116.                 code == CV_BGR2HSV_FULL || code == CV_BGR2HLS_FULL ? 0 : 2;  
  117.             int hrange = sizeof(_Tp) == 4 ? 360 : code == CV_BGR2HSV || code == CV_RGB2HSV ||  
  118.                 code == CV_BGR2HLS || code == CV_RGB2HLS ? 180 : 256;  
  119.   
  120.             if (code == CV_BGR2HSV || code == CV_RGB2HSV || code == CV_BGR2HSV_FULL || code == CV_RGB2HSV_FULL) {  
  121.                 CvtColorLoop_RGB2HSV(src, dst, bidx, hrange);  
  122.             } else {  
  123.                 CvtColorLoop_RGB2HLS(src, dst, bidx, hrange);  
  124.             }  
  125.             break;  
  126.         }  
  127.         case CV_HSV2BGR: case CV_HSV2RGB: case CV_HSV2BGR_FULL: case CV_HSV2RGB_FULL:  
  128.         case CV_HLS2BGR: case CV_HLS2RGB: case CV_HLS2BGR_FULL: case CV_HLS2RGB_FULL: {  
  129.             FBC_Assert(scn == 3 && (dcn == 3 || dcn == 4));  
  130.             FBC_Assert(sizeof(_Tp) == 1 || sizeof(_Tp) == 4);  
  131.             bidx = code == CV_HSV2BGR || code == CV_HLS2BGR ||  
  132.                 code == CV_HSV2BGR_FULL || code == CV_HLS2BGR_FULL ? 0 : 2;  
  133.             int hrange = sizeof(_Tp) == 4 ? 360 : code == CV_HSV2BGR || code == CV_HSV2RGB ||  
  134.                 code == CV_HLS2BGR || code == CV_HLS2RGB ? 180 : 255;  
  135.   
  136.             if (code == CV_HSV2BGR || code == CV_HSV2RGB || code == CV_HSV2BGR_FULL || code == CV_HSV2RGB_FULL) {  
  137.                 CvtColorLoop_HSV2RGB(src, dst, bidx, hrange);  
  138.             } else {  
  139.                 CvtColorLoop_HLS2RGB(src, dst, bidx, hrange);  
  140.             }  
  141.             break;  
  142.         }  
  143.         case CV_BGR2Lab: case CV_RGB2Lab:  
  144.         case CV_BGR2Luv: case CV_RGB2Luv: {  
  145.             FBC_Assert(scn == 3 || scn == 4);  
  146.             FBC_Assert(sizeof(_Tp) == 1 || sizeof(_Tp) == 4);  
  147.             bidx = code == CV_BGR2Lab || code == CV_BGR2Luv ? 0 : 2;  
  148.             bool srgb = code == CV_BGR2Lab || code == CV_RGB2Lab || code == CV_BGR2Luv || code == CV_RGB2Luv;  
  149.   
  150.             if (code == CV_BGR2Lab || code == CV_RGB2Lab) {  
  151.                 CvtColorLoop_RGB2Lab(src, dst, bidx, 0, 0, srgb);  
  152.             } else {  
  153.                 CvtColorLoop_RGB2Luv(src, dst, bidx, 0, 0, srgb);  
  154.             }  
  155.             break;  
  156.         }  
  157.         case CV_Lab2BGR: case CV_Lab2RGB:  
  158.         case CV_Luv2BGR: case CV_Luv2RGB: {  
  159.             FBC_Assert(scn == 3 && (dcn == 3 || dcn == 4));  
  160.             FBC_Assert(sizeof(_Tp) == 1 || sizeof(_Tp) == 4);  
  161.             bidx = code == CV_Lab2BGR || code == CV_Luv2BGR ? 0 : 2;  
  162.             bool srgb = code == CV_Lab2BGR || code == CV_Lab2RGB || code == CV_Luv2BGR || code == CV_Luv2RGB;  
  163.   
  164.             if (code == CV_Lab2BGR || code == CV_Lab2RGB) {  
  165.                 CvtColorLoop_Lab2RGB(src, dst, bidx, 0, 0, srgb);  
  166.             } else {  
  167.                 CvtColorLoop_Luv2RGB(src, dst, bidx, 0, 0, srgb);  
  168.             }  
  169.             break;  
  170.         }  
  171.         case CV_YUV2BGR_NV21:  case CV_YUV2RGB_NV21:  case CV_YUV2BGR_NV12:  case CV_YUV2RGB_NV12:  
  172.         case CV_YUV2BGRA_NV21: case CV_YUV2RGBA_NV21: case CV_YUV2BGRA_NV12: case CV_YUV2RGBA_NV12: {  
  173.             // http://www.fourcc.org/yuv.php#NV21 == yuv420sp -> 8位Y采样的平面,之后是包含8位2x2次采样色度采样的交错V / U平面
  174.             // http://www.fourcc.org/yuv.php#NV12 -> 8位Y采样的平面,之后是包含8位2x2次采样色差采样的交错U / V平面  
  175.   
  176.             dcn = (code == CV_YUV420sp2BGRA || code == CV_YUV420sp2RGBA || code == CV_YUV2BGRA_NV12 || code == CV_YUV2RGBA_NV12) ? 4 : 3;  
  177.             FBC_Assert(dcn == dst.channels);  
  178.             const int bIdx = (code == CV_YUV2BGR_NV21 || code == CV_YUV2BGRA_NV21 || code == CV_YUV2BGR_NV12 || code == CV_YUV2BGRA_NV12) ? 0 : 2;  
  179.             const int uIdx = (code == CV_YUV2BGR_NV21 || code == CV_YUV2BGRA_NV21 || code == CV_YUV2RGB_NV21 || code == CV_YUV2RGBA_NV21) ? 1 : 0;  
  180.   
  181.             FBC_Assert(dcn == 3 || dcn == 4);  
  182.             FBC_Assert(sz.width % 2 == 0 && sz.height % 3 == 0);  
  183.             FBC_Assert(sizeof(_Tp) == 1);  
  184.             //Size dstSz(sz.width, sz.height * 2 / 3);  
  185.             FBC_Assert((sz.width == dz.width) && (dz.height = sz.height * 2 / 3));  
  186.   
  187.             int srcstep = (int)src.step;  
  188.             const uchar* y = src.ptr();  
  189.             const uchar* uv = y + srcstep * dz.height;  
  190.   
  191.             switch (dcn * 100 + bIdx * 10 + uIdx) {  
  192.                 case 300: cvtYUV420sp2RGB<_Tp, chs2, 0, 0>(dst, srcstep, y, uv); break;  
  193.                 case 301: cvtYUV420sp2RGB<_Tp, chs2, 0, 1>(dst, srcstep, y, uv); break;  
  194.                 case 320: cvtYUV420sp2RGB<_Tp, chs2, 2, 0>(dst, srcstep, y, uv); break;  
  195.                 case 321: cvtYUV420sp2RGB<_Tp, chs2, 2, 1>(dst, srcstep, y, uv); break;  
  196.                 case 400: cvtYUV420sp2RGBA<_Tp, chs2, 0, 0>(dst, srcstep, y, uv); break;  
  197.                 case 401: cvtYUV420sp2RGBA<_Tp, chs2, 0, 1>(dst, srcstep, y, uv); break;  
  198.                 case 420: cvtYUV420sp2RGBA<_Tp, chs2, 2, 0>(dst, srcstep, y, uv); break;  
  199.                 case 421: cvtYUV420sp2RGBA<_Tp, chs2, 2, 1>(dst, srcstep, y, uv); break;  
  200.                 default: FBC_Error("Unknown/unsupported color conversion code"); break;  
  201.             };  
  202.             break;  
  203.         }  
  204.         case CV_YUV2BGR_YV12: case CV_YUV2RGB_YV12: case CV_YUV2BGRA_YV12: case CV_YUV2RGBA_YV12:  
  205.         case CV_YUV2BGR_IYUV: case CV_YUV2RGB_IYUV: case CV_YUV2BGRA_IYUV: case CV_YUV2RGBA_IYUV: {  
  206.             //http://www.fourcc.org/yuv.php#YV12 == yuv420p -> 它包括N×M Y平面,随后是(N / 2)×(M / 2)V和U平面.  
  207.             //http://www.fourcc.org/yuv.php#IYUV == I420 -> 它包括N×N Y平面,随后是(N / 2)×(N / 2)U和V平面 
  208.   
  209.             dcn = (code == CV_YUV2BGRA_YV12 || code == CV_YUV2RGBA_YV12 || code == CV_YUV2RGBA_IYUV || code == CV_YUV2BGRA_IYUV) ? 4 : 3;  
  210.             FBC_Assert(dcn == dst.channels);  
  211.             const int bIdx = (code == CV_YUV2BGR_YV12 || code == CV_YUV2BGRA_YV12 || code == CV_YUV2BGR_IYUV || code == CV_YUV2BGRA_IYUV) ? 0 : 2;  
  212.             const int uIdx = (code == CV_YUV2BGR_YV12 || code == CV_YUV2RGB_YV12 || code == CV_YUV2BGRA_YV12 || code == CV_YUV2RGBA_YV12) ? 1 : 0;  
  213.   
  214.             FBC_Assert(dcn == 3 || dcn == 4);  
  215.             FBC_Assert(sz.width % 2 == 0 && sz.height % 3 == 0);  
  216.             FBC_Assert(sizeof(_Tp) == 1);  
  217.   
  218.             //Size dstSz(sz.width, sz.height * 2 / 3);  
  219.             FBC_Assert((sz.width == dz.width) && (dz.height = sz.height * 2 / 3));  
  220.   
  221.             int srcstep = (int)src.step;  
  222.             const uchar* y = src.ptr();  
  223.             const uchar* u = y + srcstep * dz.height;  
  224.             const uchar* v = y + srcstep * (dz.height + dz.height / 4) + (dz.width / 2) * ((dz.height % 4) / 2);  
  225.   
  226.             int ustepIdx = 0;  
  227.             int vstepIdx = dz.height % 4 == 2 ? 1 : 0;  
  228.   
  229.             if (uIdx == 1) { std::swap(u, v), std::swap(ustepIdx, vstepIdx); }  
  230.   
  231.             switch (dcn * 10 + bIdx) {  
  232.                 case 30: cvtYUV420p2RGB<_Tp, chs2, 0>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;  
  233.                 case 32: cvtYUV420p2RGB<_Tp, chs2, 2>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;  
  234.                 case 40: cvtYUV420p2RGBA<_Tp, chs2, 0>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;  
  235.                 case 42: cvtYUV420p2RGBA<_Tp, chs2, 2>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;  
  236.                 default: FBC_Error("Unknown/unsupported color conversion code"); break;  
  237.             };  
  238.             break;  
  239.         }  
  240.         case CV_YUV2GRAY_420: {  
  241.             FBC_Assert(dcn == 1 && scn == 1);  
  242.             FBC_Assert(sz.width % 2 == 0 && sz.height % 3 == 0);  
  243.             FBC_Assert(sizeof(_Tp) == 1);  
  244.   
  245.             //Size dstSz(sz.width, sz.height * 2 / 3);  
  246.             FBC_Assert((sz.width == dz.width) && (dz.height = sz.height * 2 / 3));  
  247.   
  248.             //src.copyTo(dst, Rect(0, 0, sz.width, dz.height));  
  249.             memcpy(dst.data, src.data, dz.area());  
  250.   
  251.             break;  
  252.         }  
  253.         case CV_RGB2YUV_YV12: case CV_BGR2YUV_YV12: case CV_RGBA2YUV_YV12: case CV_BGRA2YUV_YV12:  
  254.         case CV_RGB2YUV_IYUV: case CV_BGR2YUV_IYUV: case CV_RGBA2YUV_IYUV: case CV_BGRA2YUV_IYUV: {  
  255.             const int bIdx = (code == CV_BGR2YUV_IYUV || code == CV_BGRA2YUV_IYUV || code == CV_BGR2YUV_YV12 || code == CV_BGRA2YUV_YV12) ? 0 : 2;  
  256.             const int uIdx = (code == CV_BGR2YUV_IYUV || code == CV_BGRA2YUV_IYUV || code == CV_RGB2YUV_IYUV || code == CV_RGBA2YUV_IYUV) ? 1 : 2;  
  257.   
  258.             FBC_Assert(scn == 3 || scn == 4);  
  259.             FBC_Assert(sizeof(_Tp) == 1);  
  260.             FBC_Assert(dcn == 1);  
  261.             FBC_Assert(sz.width % 2 == 0 && sz.height % 2 == 0);  
  262.   
  263.             //Size dstSz(sz.width, sz.height / 2 * 3);  
  264.             FBC_Assert((dz.width == sz.width) && (sz.height / 2 * 3 == dz.height));  
  265.   
  266.             switch (bIdx + uIdx * 10) {  
  267.                 case 10: cvtRGBtoYUV420p<_Tp, chs1, chs2, 0, 1>(src, dst); break;  
  268.                 case 12: cvtRGBtoYUV420p<_Tp, chs1, chs2, 2, 1>(src, dst); break;  
  269.                 case 20: cvtRGBtoYUV420p<_Tp, chs1, chs2, 0, 2>(src, dst); break;  
  270.                 case 22: cvtRGBtoYUV420p<_Tp, chs1, chs2, 2, 2>(src, dst); break;  
  271.                 default: FBC_Error("未知/不支持的颜色转换代码"); break;  
  272.             };  
  273.   
  274.             break;  
  275.         }  
  276.         default:  
  277.             FBC_Error("未知/不支持的颜色转换代码");  
  278.     }  
  279.   
  280.     return 0;  
  281. }  
  282.   
  283. // 计算函数的三次样条系数: (xi=i, yi=f[i]), i=0..n  
  284. template<typename _Tp> static void splineBuild(const _Tp* f, int n, _Tp* tab)  
  285. {  
  286.     _Tp cn = 0;  
  287.     int i;  
  288.     tab[0] = tab[1] = (_Tp)0;  
  289.   
  290.     for (i = 1; i < n - 1; i++) {  
  291.         _Tp t = 3 * (f[i + 1] - 2 * f[i] + f[i - 1]);  
  292.         _Tp l = 1 / (4 - tab[(i - 1) * 4]);  
  293.         tab[i * 4] = l; tab[i * 4 + 1] = (t - tab[(i - 1) * 4 + 1])*l;  
  294.     }  
  295.   
  296.     for (i = n - 1; i >= 0; i--) {  
  297.         _Tp c = tab[i * 4 + 1] - tab[i * 4] * cn;  
  298.         _Tp b = f[i + 1] - f[i] - (cn + c * 2)*(_Tp)0.3333333333333333;  
  299.         _Tp d = (cn - c)*(_Tp)0.3333333333333333;  
  300.         tab[i * 4] = f[i]; tab[i * 4 + 1] = b;  
  301.         tab[i * 4 + 2] = c; tab[i * 4 + 3] = d;  
  302.         cn = c;  
  303.     }  
  304. }  
  305.   
  306. // 使用三次样条在x,0 <= x <= n内插函数的值.  
  307. template<typename _Tp> static inline _Tp splineInterpolate(_Tp x, const _Tp* tab, int n)  
  308. {  
  309.     // 不要紧急需要触摸此功能 - 某些版本的gcc无法正确插入
  310.     int ix = std::min(std::max(int(x), 0), n - 1);  
  311.     x -= ix;  
  312.     tab += ix * 4;  
  313.     return ((tab[3] * x + tab[2])*x + tab[1])*x + tab[0];  
  314. }  
  315.   
  316. template<typename _Tp> struct ColorChannel  
  317. {  
  318.     typedef float worktype_f;  
  319.     static _Tp max() { return std::numeric_limits<_Tp>::max(); }  
  320.     static _Tp half() { return (_Tp)(max() / 2 + 1); }  
  321. };  
  322.   
  323. template<> struct ColorChannel<float>  
  324. {  
  325.     typedef float worktype_f;  
  326.     static float max() { return 1.f; }  
  327.     static float half() { return 0.5f; }  
  328. };  
  329.   
  330. #undef R2Y  
  331. #undef G2Y  
  332. #undef B2Y  
  333.   
  334. enum  
  335. {  
  336.     yuv_shift = 14,  
  337.     xyz_shift = 12,  
  338.     R2Y = 4899,  
  339.     G2Y = 9617,  
  340.     B2Y = 1868,  
  341.     BLOCK_SIZE = 256  
  342. };  
  343.   
  344. template<typename _Tp> struct RGB2Gray  
  345. {  
  346.     typedef _Tp channel_type;  
  347.   
  348.     RGB2Gray(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)  
  349.     {  
  350.         static const float coeffs0[] = { 0.299f, 0.587f, 0.114f };  
  351.         memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 3 * sizeof(coeffs[0]));  
  352.         if (blueIdx == 0)  
  353.             std::swap(coeffs[0], coeffs[2]);  
  354.     }  
  355.   
  356.     void operator()(const _Tp* src, _Tp* dst, int n) const  
  357.     {  
  358.         int scn = srccn;  
  359.         float cb = coeffs[0], cg = coeffs[1], cr = coeffs[2];  
  360.         for (int i = 0; i < n; i++, src += scn)  
  361.             dst[i] = saturate_cast<_Tp>(src[0] * cb + src[1] * cg + src[2] * cr);  
  362.     }  
  363.     int srccn;  
  364.     float coeffs[3];  
  365. };  
  366.   
  367. template<> struct RGB2Gray<uchar>  
  368. {  
  369.     typedef uchar channel_type;  
  370.   
  371.     RGB2Gray(int _srccn, int blueIdx, const int* coeffs) : srccn(_srccn)  
  372.     {  
  373.         const int coeffs0[] = { R2Y, G2Y, B2Y };  
  374.         if (!coeffs) coeffs = coeffs0;  
  375.   
  376.         int b = 0, g = 0, r = (1 << (yuv_shift - 1));  
  377.         int db = coeffs[blueIdx ^ 2], dg = coeffs[1], dr = coeffs[blueIdx];  
  378.   
  379.         for (int i = 0; i < 256; i++, b += db, g += dg, r += dr) {  
  380.             tab[i] = b;  
  381.             tab[i + 256] = g;  
  382.             tab[i + 512] = r;  
  383.         }  
  384.     }  
  385.     void operator()(const uchar* src, uchar* dst, int n) const  
  386.     {  
  387.         int scn = srccn;  
  388.         const int* _tab = tab;  
  389.         for (int i = 0; i < n; i++, src += scn)  
  390.             dst[i] = (uchar)((_tab[src[0]] + _tab[src[1] + 256] + _tab[src[2] + 512]) >> yuv_shift);  
  391.     }  
  392.     int srccn;  
  393.     int tab[256 * 3];  
  394. };  
  395.   
  396. template<> struct RGB2Gray<ushort>  
  397. {  
  398.     typedef ushort channel_type;  
  399.   
  400.     RGB2Gray(int _srccn, int blueIdx, const int* _coeffs) : srccn(_srccn)  
  401.     {  
  402.         static const int coeffs0[] = { R2Y, G2Y, B2Y };  
  403.         memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 3 * sizeof(coeffs[0]));  
  404.         if (blueIdx == 0)  
  405.             std::swap(coeffs[0], coeffs[2]);  
  406.     }  
  407.   
  408.     void operator()(const ushort* src, ushort* dst, int n) const  
  409.     {  
  410.         int scn = srccn, cb = coeffs[0], cg = coeffs[1], cr = coeffs[2];  
  411.         for (int i = 0; i < n; i++, src += scn)  
  412.             dst[i] = (ushort)FBC_DESCALE((unsigned)(src[0] * cb + src[1] * cg + src[2] * cr), yuv_shift);  
  413.     }  
  414.     int srccn;  
  415.     int coeffs[3];  
  416. };  
  417.   
  418. template<typename _Tp>  
  419. struct Gray2RGB  
  420. {  
  421.     typedef _Tp channel_type;  
  422.   
  423.     Gray2RGB(int _dstcn) : dstcn(_dstcn) {}  
  424.     void operator()(const _Tp* src, _Tp* dst, int n) const  
  425.     {  
  426.         if (dstcn == 3) {  
  427.             for (int i = 0; i < n; i++, dst += 3)  
  428.                 dst[0] = dst[1] = dst[2] = src[i];  
  429.         } else {  
  430.             _Tp alpha = ColorChannel<_Tp>::max();  
  431.             for (int i = 0; i < n; i++, dst += 4) {  
  432.                 dst[0] = dst[1] = dst[2] = src[i];  
  433.                 dst[3] = alpha;  
  434.             }  
  435.         }  
  436.     }  
  437.   
  438.     int dstcn;  
  439. };  
  440.   
  441. template<typename _Tp> struct RGB2YCrCb_f  
  442. {  
  443.     typedef _Tp channel_type;  
  444.   
  445.     RGB2YCrCb_f(int _srccn, int _blueIdx, const float* _coeffs) : srccn(_srccn), blueIdx(_blueIdx)  
  446.     {  
  447.         static const float coeffs0[] = { 0.299f, 0.587f, 0.114f, 0.713f, 0.564f };  
  448.         memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 5 * sizeof(coeffs[0]));  
  449.         if (blueIdx == 0) std::swap(coeffs[0], coeffs[2]);  
  450.     }  
  451.   
  452.     void operator()(const _Tp* src, _Tp* dst, int n) const  
  453.     {  
  454.         int scn = srccn, bidx = blueIdx;  
  455.         const _Tp delta = ColorChannel<_Tp>::half();  
  456.         float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3], C4 = coeffs[4];  
  457.         n *= 3;  
  458.         for (int i = 0; i < n; i += 3, src += scn) {  
  459.             _Tp Y = saturate_cast<_Tp>(src[0] * C0 + src[1] * C1 + src[2] * C2);  
  460.             _Tp Cr = saturate_cast<_Tp>((src[bidx ^ 2] - Y)*C3 + delta);  
  461.             _Tp Cb = saturate_cast<_Tp>((src[bidx] - Y)*C4 + delta);  
  462.             dst[i] = Y; dst[i + 1] = Cr; dst[i + 2] = Cb;  
  463.         }  
  464.     }  
  465.     int srccn, blueIdx;  
  466.     float coeffs[5];  
  467. };  
  468.   
  469. template<typename _Tp> struct RGB2YCrCb_i  
  470. {  
  471.     typedef _Tp channel_type;  
  472.   
  473.     RGB2YCrCb_i(int _srccn, int _blueIdx, const int* _coeffs) : srccn(_srccn), blueIdx(_blueIdx)  
  474.     {  
  475.         static const int coeffs0[] = { R2Y, G2Y, B2Y, 11682, 9241 };  
  476.         memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 5 * sizeof(coeffs[0]));  
  477.         if (blueIdx == 0) std::swap(coeffs[0], coeffs[2]);  
  478.     }  
  479.   
  480.     void operator()(const _Tp* src, _Tp* dst, int n) const  
  481.     {  
  482.         int scn = srccn, bidx = blueIdx;  
  483.         int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3], C4 = coeffs[4];  
  484.         int delta = ColorChannel<_Tp>::half()*(1 << yuv_shift);  
  485.         n *= 3;  
  486.         for (int i = 0; i < n; i += 3, src += scn) {  
  487.             int Y = FBC_DESCALE(src[0] * C0 + src[1] * C1 + src[2] * C2, yuv_shift);  
  488.             int Cr = FBC_DESCALE((src[bidx ^ 2] - Y)*C3 + delta, yuv_shift);  
  489.             int Cb = FBC_DESCALE((src[bidx] - Y)*C4 + delta, yuv_shift);  
  490.             dst[i] = saturate_cast<_Tp>(Y);  
  491.             dst[i + 1] = saturate_cast<_Tp>(Cr);  
  492.             dst[i + 2] = saturate_cast<_Tp>(Cb);  
  493.         }  
  494.     }  
  495.     int srccn, blueIdx;  
  496.     int coeffs[5];  
  497. };  
  498.   
  499. template<typename _Tp> struct YCrCb2RGB_f  
  500. {  
  501.     typedef _Tp channel_type;  
  502.   
  503.     YCrCb2RGB_f(int _dstcn, int _blueIdx, const float* _coeffs)  
  504.         : dstcn(_dstcn), blueIdx(_blueIdx)  
  505.     {  
  506.         static const float coeffs0[] = { 1.403f, -0.714f, -0.344f, 1.773f };  
  507.         memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 4 * sizeof(coeffs[0]));  
  508.     }  
  509.     void operator()(const _Tp* src, _Tp* dst, int n) const  
  510.     {  
  511.         int dcn = dstcn, bidx = blueIdx;  
  512.         const _Tp delta = ColorChannel<_Tp>::half(), alpha = ColorChannel<_Tp>::max();  
  513.         float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3];  
  514.         n *= 3;  
  515.         for (int i = 0; i < n; i += 3, dst += dcn) {  
  516.             _Tp Y = src[i];  
  517.             _Tp Cr = src[i + 1];  
  518.             _Tp Cb = src[i + 2];  
  519.   
  520.             _Tp b = saturate_cast<_Tp>(Y + (Cb - delta)*C3);  
  521.             _Tp g = saturate_cast<_Tp>(Y + (Cb - delta)*C2 + (Cr - delta)*C1);  
  522.             _Tp r = saturate_cast<_Tp>(Y + (Cr - delta)*C0);  
  523.   
  524.             dst[bidx] = b; dst[1] = g; dst[bidx ^ 2] = r;  
  525.             if (dcn == 4)  
  526.                 dst[3] = alpha;  
  527.         }  
  528.     }  
  529.     int dstcn, blueIdx;  
  530.     float coeffs[4];  
  531. };  
  532.   
  533. template<typename _Tp> struct YCrCb2RGB_i  
  534. {  
  535.     typedef _Tp channel_type;  
  536.   
  537.     YCrCb2RGB_i(int _dstcn, int _blueIdx, const int* _coeffs)  
  538.         : dstcn(_dstcn), blueIdx(_blueIdx)  
  539.     {  
  540.         static const int coeffs0[] = { 22987, -11698, -5636, 29049 };  
  541.         memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 4 * sizeof(coeffs[0]));  
  542.     }  
  543.   
  544.     void operator()(const _Tp* src, _Tp* dst, int n) const  
  545.     {  
  546.         int dcn = dstcn, bidx = blueIdx;  
  547.         const _Tp delta = ColorChannel<_Tp>::half(), alpha = ColorChannel<_Tp>::max();  
  548.         int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3];  
  549.         n *= 3;  
  550.         for (int i = 0; i < n; i += 3, dst += dcn) {  
  551.             _Tp Y = src[i];  
  552.             _Tp Cr = src[i + 1];  
  553.             _Tp Cb = src[i + 2];  
  554.   
  555.             int b = Y + FBC_DESCALE((Cb - delta)*C3, yuv_shift);  
  556.             int g = Y + FBC_DESCALE((Cb - delta)*C2 + (Cr - delta)*C1, yuv_shift);  
  557.             int r = Y + FBC_DESCALE((Cr - delta)*C0, yuv_shift);  
  558.   
  559.             dst[bidx] = saturate_cast<_Tp>(b);  
  560.             dst[1] = saturate_cast<_Tp>(g);  
  561.             dst[bidx ^ 2] = saturate_cast<_Tp>(r);  
  562.             if (dcn == 4)  
  563.                 dst[3] = alpha;  
  564.         }  
  565.     }  
  566.     int dstcn, blueIdx;  
  567.     int coeffs[4];  
  568. };  
  569.   
  570. static const float sRGB2XYZ_D65[] =  
  571. {  
  572.     0.412453f, 0.357580f, 0.180423f,  
  573.     0.212671f, 0.715160f, 0.072169f,  
  574.     0.019334f, 0.119193f, 0.950227f  
  575. };  
  576.   
  577. static const float XYZ2sRGB_D65[] =  
  578. {  
  579.     3.240479f, -1.53715f, -0.498535f,  
  580.     -0.969256f, 1.875991f, 0.041556f,  
  581.     0.055648f, -0.204043f, 1.057311f  
  582. };  
  583.   
  584. template<typename _Tp> struct RGB2XYZ_f  
  585. {  
  586.     typedef _Tp channel_type;  
  587.   
  588.     RGB2XYZ_f(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)  
  589.     {  
  590.         memcpy(coeffs, _coeffs ? _coeffs : sRGB2XYZ_D65, 9 * sizeof(coeffs[0]));  
  591.         if (blueIdx == 0) {  
  592.             std::swap(coeffs[0], coeffs[2]);  
  593.             std::swap(coeffs[3], coeffs[5]);  
  594.             std::swap(coeffs[6], coeffs[8]);  
  595.         }  
  596.     }  
  597.     void operator()(const _Tp* src, _Tp* dst, int n) const  
  598.     {  
  599.         int scn = srccn;  
  600.         float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],  
  601.             C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],  
  602.             C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];  
  603.   
  604.         n *= 3;  
  605.         for (int i = 0; i < n; i += 3, src += scn) {  
  606.             _Tp X = saturate_cast<_Tp>(src[0] * C0 + src[1] * C1 + src[2] * C2);  
  607.             _Tp Y = saturate_cast<_Tp>(src[0] * C3 + src[1] * C4 + src[2] * C5);  
  608.             _Tp Z = saturate_cast<_Tp>(src[0] * C6 + src[1] * C7 + src[2] * C8);  
  609.             dst[i] = X; dst[i + 1] = Y; dst[i + 2] = Z;  
  610.         }  
  611.     }  
  612.     int srccn;  
  613.     float coeffs[9];  
  614. };  
  615.   
  616. template<typename _Tp> struct RGB2XYZ_i  
  617. {  
  618.     typedef _Tp channel_type;  
  619.   
  620.     RGB2XYZ_i(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)  
  621.     {  
  622.         static const int coeffs0[] = {  
  623.             1689, 1465, 739,  
  624.             871, 2929, 296,  
  625.             79, 488, 3892  
  626.         };  
  627.         for (int i = 0; i < 9; i++)  
  628.             coeffs[i] = _coeffs ? cvRound(_coeffs[i] * (1 << xyz_shift)) : coeffs0[i];  
  629.         if (blueIdx == 0) {  
  630.             std::swap(coeffs[0], coeffs[2]);  
  631.             std::swap(coeffs[3], coeffs[5]);  
  632.             std::swap(coeffs[6], coeffs[8]);  
  633.         }  
  634.     }  
  635.     void operator()(const _Tp* src, _Tp* dst, int n) const  
  636.     {  
  637.         int scn = srccn;  
  638.         int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],  
  639.             C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],  
  640.             C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];  
  641.         n *= 3;  
  642.   
  643.         for (int i = 0; i < n; i += 3, src += scn) {  
  644.             int X = FBC_DESCALE(src[0] * C0 + src[1] * C1 + src[2] * C2, xyz_shift);  
  645.             int Y = FBC_DESCALE(src[0] * C3 + src[1] * C4 + src[2] * C5, xyz_shift);  
  646.             int Z = FBC_DESCALE(src[0] * C6 + src[1] * C7 + src[2] * C8, xyz_shift);  
  647.             dst[i] = saturate_cast<_Tp>(X); dst[i + 1] = saturate_cast<_Tp>(Y);  
  648.             dst[i + 2] = saturate_cast<_Tp>(Z);  
  649.         }  
  650.     }  
  651.     int srccn;  
  652.     int coeffs[9];  
  653. };  
  654.   
  655. template<typename _Tp> struct XYZ2RGB_f  
  656. {  
  657.     typedef _Tp channel_type;  
  658.   
  659.     XYZ2RGB_f(int _dstcn, int _blueIdx, const float* _coeffs) : dstcn(_dstcn), blueIdx(_blueIdx)  
  660.     {  
  661.         memcpy(coeffs, _coeffs ? _coeffs : XYZ2sRGB_D65, 9 * sizeof(coeffs[0]));  
  662.         if (blueIdx == 0) {  
  663.             std::swap(coeffs[0], coeffs[6]);  
  664.             std::swap(coeffs[1], coeffs[7]);  
  665.             std::swap(coeffs[2], coeffs[8]);  
  666.         }  
  667.     }  
  668.   
  669.     void operator()(const _Tp* src, _Tp* dst, int n) const  
  670.     {  
  671.         int dcn = dstcn;  
  672.         _Tp alpha = ColorChannel<_Tp>::max();  
  673.         float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],  
  674.             C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],  
  675.             C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];  
  676.         n *= 3;  
  677.         for (int i = 0; i < n; i += 3, dst += dcn) {  
  678.             _Tp B = saturate_cast<_Tp>(src[i] * C0 + src[i + 1] * C1 + src[i + 2] * C2);  
  679.             _Tp G = saturate_cast<_Tp>(src[i] * C3 + src[i + 1] * C4 + src[i + 2] * C5);  
  680.             _Tp R = saturate_cast<_Tp>(src[i] * C6 + src[i + 1] * C7 + src[i + 2] * C8);  
  681.             dst[0] = B; dst[1] = G; dst[2] = R;  
  682.             if (dcn == 4)  
  683.                 dst[3] = alpha;  
  684.         }  
  685.     }  
  686.     int dstcn, blueIdx;  
  687.     float coeffs[9];  
  688. };  
  689.   
  690. template<typename _Tp> struct XYZ2RGB_i  
  691. {  
  692.     typedef _Tp channel_type;  
  693.   
  694.     XYZ2RGB_i(int _dstcn, int _blueIdx, const int* _coeffs)  
  695.         : dstcn(_dstcn), blueIdx(_blueIdx)  
  696.     {  
  697.         static const int coeffs0[] = {  
  698.             13273, -6296, -2042,  
  699.             -3970, 7684, 170,  
  700.             228, -836, 4331  
  701.         };  
  702.         for (int i = 0; i < 9; i++)  
  703.             coeffs[i] = _coeffs ? cvRound(_coeffs[i] * (1 << xyz_shift)) : coeffs0[i];  
  704.   
  705.         if (blueIdx == 0) {  
  706.             std::swap(coeffs[0], coeffs[6]);  
  707.             std::swap(coeffs[1], coeffs[7]);  
  708.             std::swap(coeffs[2], coeffs[8]);  
  709.         }  
  710.     }  
  711.     void operator()(const _Tp* src, _Tp* dst, int n) const  
  712.     {  
  713.         int dcn = dstcn;  
  714.         _Tp alpha = ColorChannel<_Tp>::max();  
  715.         int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],  
  716.             C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],  
  717.             C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];  
  718.         n *= 3;  
  719.         for (int i = 0; i < n; i += 3, dst += dcn) {  
  720.             int B = FBC_DESCALE(src[i] * C0 + src[i + 1] * C1 + src[i + 2] * C2, xyz_shift);  
  721.             int G = FBC_DESCALE(src[i] * C3 + src[i + 1] * C4 + src[i + 2] * C5, xyz_shift);  
  722.             int R = FBC_DESCALE(src[i] * C6 + src[i + 1] * C7 + src[i + 2] * C8, xyz_shift);  
  723.             dst[0] = saturate_cast<_Tp>(B); dst[1] = saturate_cast<_Tp>(G);  
  724.             dst[2] = saturate_cast<_Tp>(R);  
  725.             if (dcn == 4)  
  726.                 dst[3] = alpha;  
  727.         }  
  728.     }  
  729.     int dstcn, blueIdx;  
  730.     int coeffs[9];  
  731. };  
  732.   
  733. struct RGB2HSV_b  
  734. {  
  735.     typedef uchar channel_type;  
  736.   
  737.     RGB2HSV_b(int _srccn, int _blueIdx, int _hrange) : srccn(_srccn), blueIdx(_blueIdx), hrange(_hrange)  
  738.     {  
  739.         FBC_Assert(hrange == 180 || hrange == 256);  
  740.     }  
  741.   
  742.     void operator()(const uchar* src, uchar* dst, int n) const  
  743.     {  
  744.         int i, bidx = blueIdx, scn = srccn;  
  745.         const int hsv_shift = 12;  
  746.   
  747.         static int sdiv_table[256];  
  748.         static int hdiv_table180[256];  
  749.         static int hdiv_table256[256];  
  750.         static volatile bool initialized = false;  
  751.   
  752.         int hr = hrange;  
  753.         const int* hdiv_table = hr == 180 ? hdiv_table180 : hdiv_table256;  
  754.         n *= 3;  
  755.   
  756.         if (!initialized) {  
  757.             sdiv_table[0] = hdiv_table180[0] = hdiv_table256[0] = 0;  
  758.             for (i = 1; i < 256; i++) {  
  759.                 sdiv_table[i] = saturate_cast<int>((255 << hsv_shift) / (1.*i));  
  760.                 hdiv_table180[i] = saturate_cast<int>((180 << hsv_shift) / (6.*i));  
  761.                 hdiv_table256[i] = saturate_cast<int>((256 << hsv_shift) / (6.*i));  
  762.             }  
  763.             initialized = true;  
  764.         }  
  765.   
  766.         for (i = 0; i < n; i += 3, src += scn) {  
  767.             int b = src[bidx], g = src[1], r = src[bidx ^ 2];  
  768.             int h, s, v = b;  
  769.             int vmin = b, diff;  
  770.             int vr, vg;  
  771.   
  772.             FBC_CALC_MAX_8U(v, g);  
  773.             FBC_CALC_MAX_8U(v, r);  
  774.             FBC_CALC_MIN_8U(vmin, g);  
  775.             FBC_CALC_MIN_8U(vmin, r);  
  776.   
  777.             diff = v - vmin;  
  778.             vr = v == r ? -1 : 0;  
  779.             vg = v == g ? -1 : 0;  
  780.   
  781.             s = (diff * sdiv_table[v] + (1 << (hsv_shift - 1))) >> hsv_shift;  
  782.             h = (vr & (g - b)) + (~vr & ((vg & (b - r + 2 * diff)) + ((~vg) & (r - g + 4 * diff))));  
  783.             h = (h * hdiv_table[diff] + (1 << (hsv_shift - 1))) >> hsv_shift;  
  784.             h += h < 0 ? hr : 0;  
  785.   
  786.             dst[i] = saturate_cast<uchar>(h);  
  787.             dst[i + 1] = (uchar)s;  
  788.             dst[i + 2] = (uchar)v;  
  789.         }  
  790.     }  
  791.   
  792.     int srccn, blueIdx, hrange;  
  793. };  
  794.   
  795. struct RGB2HSV_f  
  796. {  
  797.     typedef float channel_type;  
  798.   
  799.     RGB2HSV_f(int _srccn, int _blueIdx, float _hrange) : srccn(_srccn), blueIdx(_blueIdx), hrange(_hrange) {}  
  800.   
  801.     void operator()(const float* src, float* dst, int n) const  
  802.     {  
  803.         int i, bidx = blueIdx, scn = srccn;  
  804.         float hscale = hrange*(1.f / 360.f);  
  805.         n *= 3;  
  806.   
  807.         for (i = 0; i < n; i += 3, src += scn) {  
  808.             float b = src[bidx], g = src[1], r = src[bidx ^ 2];  
  809.             float h, s, v;  
  810.   
  811.             float vmin, diff;  
  812.   
  813.             v = vmin = r;  
  814.             if (v < g) v = g;  
  815.             if (v < b) v = b;  
  816.             if (vmin > g) vmin = g;  
  817.             if (vmin > b) vmin = b;  
  818.   
  819.             diff = v - vmin;  
  820.             s = diff / (float)(fabs(v) + FLT_EPSILON);  
  821.             diff = (float)(60. / (diff + FLT_EPSILON));  
  822.             if (v == r)  
  823.                 h = (g - b)*diff;  
  824.             else if (v == g)  
  825.                 h = (b - r)*diff + 120.f;  
  826.             else  
  827.                 h = (r - g)*diff + 240.f;  
  828.   
  829.             if (h < 0) h += 360.f;  
  830.   
  831.             dst[i] = h*hscale;  
  832.             dst[i + 1] = s;  
  833.             dst[i + 2] = v;  
  834.         }  
  835.     }  
  836.   
  837.     int srccn, blueIdx;  
  838.     float hrange;  
  839. };  
  840.   
  841. struct RGB2HLS_f  
  842. {  
  843.     typedef float channel_type;  
  844.   
  845.     RGB2HLS_f(int _srccn, int _blueIdx, float _hrange) : srccn(_srccn), blueIdx(_blueIdx), hrange(_hrange) {}  
  846.   
  847.     void operator()(const float* src, float* dst, int n) const  
  848.     {  
  849.         int i, bidx = blueIdx, scn = srccn;  
  850.         float hscale = hrange*(1.f / 360.f);  
  851.         n *= 3;  
  852.   
  853.         for (i = 0; i < n; i += 3, src += scn) {  
  854.             float b = src[bidx], g = src[1], r = src[bidx ^ 2];  
  855.             float h = 0.f, s = 0.f, l;  
  856.             float vmin, vmax, diff;  
  857.   
  858.             vmax = vmin = r;  
  859.             if (vmax < g) vmax = g;  
  860.             if (vmax < b) vmax = b;  
  861.             if (vmin > g) vmin = g;  
  862.             if (vmin > b) vmin = b;  
  863.   
  864.             diff = vmax - vmin;  
  865.             l = (vmax + vmin)*0.5f;  
  866.   
  867.             if (diff > FLT_EPSILON) {  
  868.                 s = l < 0.5f ? diff / (vmax + vmin) : diff / (2 - vmax - vmin);  
  869.                 diff = 60.f / diff;  
  870.   
  871.                 if (vmax == r)  
  872.                     h = (g - b)*diff;  
  873.                 else if (vmax == g)  
  874.                     h = (b - r)*diff + 120.f;  
  875.                 else  
  876.                     h = (r - g)*diff + 240.f;  
  877.   
  878.                 if (h < 0.f) h += 360.f;  
  879.             }  
  880.   
  881.             dst[i] = h*hscale;  
  882.             dst[i + 1] = l;  
  883.             dst[i + 2] = s;  
  884.         }  
  885.     }  
  886.   
  887.     int srccn, blueIdx;  
  888.     float hrange;  
  889. };  
  890.   
  891. struct RGB2HLS_b  
  892. {  
  893.     typedef uchar channel_type;  
  894.   
  895.     RGB2HLS_b(int _srccn, int _blueIdx, int _hrange) : srccn(_srccn), cvt(3, _blueIdx, (float)_hrange) { }  
  896.   
  897.     void operator()(const uchar* src, uchar* dst, int n) const  
  898.     {  
  899.         int i, j, scn = srccn;  
  900.         float FBC_DECL_ALIGNED(16) buf[3 * BLOCK_SIZE];  
  901.   
  902.         for (i = 0; i < n; i += BLOCK_SIZE, dst += BLOCK_SIZE * 3) {  
  903.             int dn = std::min(n - i, (int)BLOCK_SIZE);  
  904.             j = 0;  
  905.   
  906.             for (; j < dn * 3; j += 3, src += scn) {  
  907.                 buf[j] = src[0] * (1.f / 255.f);  
  908.                 buf[j + 1] = src[1] * (1.f / 255.f);  
  909.                 buf[j + 2] = src[2] * (1.f / 255.f);  
  910.             }  
  911.             cvt(buf, buf, dn);  
  912.   
  913.             j = 0;  
  914.             for (; j < dn * 3; j += 3) {  
  915.                 dst[j] = saturate_cast<uchar>(buf[j]);  
  916.                 dst[j + 1] = saturate_cast<uchar>(buf[j + 1] * 255.f);  
  917.                 dst[j + 2] = saturate_cast<uchar>(buf[j + 2] * 255.f);  
  918.             }  
  919.         }  
  920.     }  
  921.   
  922.     int srccn;  
  923.     RGB2HLS_f cvt;  
  924. };  
  925.   
  926. struct HSV2RGB_f  
  927. {  
  928.     typedef float channel_type;  
  929.   
  930.     HSV2RGB_f(int _dstcn, int _blueIdx, float _hrange)  
  931.         : dstcn(_dstcn), blueIdx(_blueIdx), hscale(6.f / _hrange) {}  
  932.   
  933.     void operator()(const float* src, float* dst, int n) const  
  934.     {  
  935.         int i, bidx = blueIdx, dcn = dstcn;  
  936.         float _hscale = hscale;  
  937.         float alpha = ColorChannel<float>::max();  
  938.         n *= 3;  
  939.   
  940.         for (i = 0; i < n; i += 3, dst += dcn) {  
  941.             float h = src[i], s = src[i + 1], v = src[i + 2];  
  942.             float b, g, r;  
  943.   
  944.             if (s == 0)  
  945.                 b = g = r = v;  
  946.             else {  
  947.                 static const int sector_data[][3] =  
  948.                 { { 1, 3, 0 }, { 1, 0, 2 }, { 3, 0, 1 }, { 0, 2, 1 }, { 0, 1, 3 }, { 2, 1, 0 } };  
  949.                 float tab[4];  
  950.                 int sector;  
  951.                 h *= _hscale;  
  952.                 if (h < 0)  
  953.                     do h += 6; while (h < 0);  
  954.                 else if (h >= 6)  
  955.                     do h -= 6; while (h >= 6);  
  956.                 sector = fbcFloor(h);  
  957.                 h -= sector;  
  958.                 if ((unsigned)sector >= 6u) {  
  959.                     sector = 0;  
  960.                     h = 0.f;  
  961.                 }  
  962.   
  963.                 tab[0] = v;  
  964.                 tab[1] = v*(1.f - s);  
  965.                 tab[2] = v*(1.f - s*h);  
  966.                 tab[3] = v*(1.f - s*(1.f - h));  
  967.   
  968.                 b = tab[sector_data[sector][0]];  
  969.                 g = tab[sector_data[sector][1]];  
  970.                 r = tab[sector_data[sector][2]];  
  971.             }  
  972.   
  973.             dst[bidx] = b;  
  974.             dst[1] = g;  
  975.             dst[bidx ^ 2] = r;  
  976.             if (dcn == 4)  
  977.                 dst[3] = alpha;  
  978.         }  
  979.     }  
  980.   
  981.     int dstcn, blueIdx;  
  982.     float hscale;  
  983. };  
  984.   
  985. struct HSV2RGB_b  
  986. {  
  987.     typedef uchar channel_type;  
  988.   
  989.     HSV2RGB_b(int _dstcn, int _blueIdx, int _hrange) : dstcn(_dstcn), cvt(3, _blueIdx, (float)_hrange) {}  
  990.   
  991.     void operator()(const uchar* src, uchar* dst, int n) const  
  992.     {  
  993.         int i, j, dcn = dstcn;  
  994.         uchar alpha = ColorChannel<uchar>::max();  
  995.         float FBC_DECL_ALIGNED(16) buf[3 * BLOCK_SIZE];  
  996.   
  997.         for (i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE * 3) {  
  998.             int dn = std::min(n - i, (int)BLOCK_SIZE);  
  999.             j = 0;  
  1000.   
  1001.             for (; j < dn * 3; j += 3) {  
  1002.                 buf[j] = src[j];  
  1003.                 buf[j + 1] = src[j + 1] * (1.f / 255.f);  
  1004.                 buf[j + 2] = src[j + 2] * (1.f / 255.f);  
  1005.             }  
  1006.             cvt(buf, buf, dn);  
  1007.   
  1008.             j = 0;  
  1009.             for (; j < dn * 3; j += 3, dst += dcn) {  
  1010.                 dst[0] = saturate_cast<uchar>(buf[j] * 255.f);  
  1011.                 dst[1] = saturate_cast<uchar>(buf[j + 1] * 255.f);  
  1012.                 dst[2] = saturate_cast<uchar>(buf[j + 2] * 255.f);  
  1013.                 if (dcn == 4)  
  1014.                     dst[3] = alpha;  
  1015.             }  
  1016.         }  
  1017.     }  
  1018.   
  1019.     int dstcn;  
  1020.     HSV2RGB_f cvt;  
  1021. };  
  1022.   
  1023. struct HLS2RGB_f  
  1024. {  
  1025.     typedef float channel_type;  
  1026.   
  1027.     HLS2RGB_f(int _dstcn, int _blueIdx, float _hrange) : dstcn(_dstcn), blueIdx(_blueIdx), hscale(6.f / _hrange) {}  
  1028.   
  1029.     void operator()(const float* src, float* dst, int n) const  
  1030.     {  
  1031.         int i, bidx = blueIdx, dcn = dstcn;  
  1032.         float _hscale = hscale;  
  1033.         float alpha = ColorChannel<float>::max();  
  1034.         n *= 3;  
  1035.   
  1036.         for (i = 0; i < n; i += 3, dst += dcn) {  
  1037.             float h = src[i], l = src[i + 1], s = src[i + 2];  
  1038.             float b, g, r;  
  1039.   
  1040.             if (s == 0)  
  1041.                 b = g = r = l;  
  1042.             else {  
  1043.                 static const int sector_data[][3] =  
  1044.                 { { 1, 3, 0 }, { 1, 0, 2 }, { 3, 0, 1 }, { 0, 2, 1 }, { 0, 1, 3 }, { 2, 1, 0 } };  
  1045.                 float tab[4];  
  1046.                 int sector;  
  1047.   
  1048.                 float p2 = l <= 0.5f ? l*(1 + s) : l + s - l*s;  
  1049.                 float p1 = 2 * l - p2;  
  1050.   
  1051.                 h *= _hscale;  
  1052.                 if (h < 0)  
  1053.                     do h += 6; while (h < 0);  
  1054.                 else if (h >= 6)  
  1055.                     do h -= 6; while (h >= 6);  
  1056.   
  1057.                 assert(0 <= h && h < 6);  
  1058.                 sector = fbcFloor(h);  
  1059.                 h -= sector;  
  1060.   
  1061.                 tab[0] = p2;  
  1062.                 tab[1] = p1;  
  1063.                 tab[2] = p1 + (p2 - p1)*(1 - h);  
  1064.                 tab[3] = p1 + (p2 - p1)*h;  
  1065.   
  1066.                 b = tab[sector_data[sector][0]];  
  1067.                 g = tab[sector_data[sector][1]];  
  1068.                 r = tab[sector_data[sector][2]];  
  1069.             }  
  1070.   
  1071.             dst[bidx] = b;  
  1072.             dst[1] = g;  
  1073.             dst[bidx ^ 2] = r;  
  1074.             if (dcn == 4)  
  1075.                 dst[3] = alpha;  
  1076.         }  
  1077.     }  
  1078.   
  1079.     int dstcn, blueIdx;  
  1080.     float hscale;  
  1081. };  
  1082.   
  1083. struct HLS2RGB_b  
  1084. {  
  1085.     typedef uchar channel_type;  
  1086.   
  1087.     HLS2RGB_b(int _dstcn, int _blueIdx, int _hrange) : dstcn(_dstcn), cvt(3, _blueIdx, (float)_hrange) { }  
  1088.   
  1089.     void operator()(const uchar* src, uchar* dst, int n) const  
  1090.     {  
  1091.         int i, j, dcn = dstcn;  
  1092.         uchar alpha = ColorChannel<uchar>::max();  
  1093.         float FBC_DECL_ALIGNED(16) buf[3 * BLOCK_SIZE];  
  1094.   
  1095.         for (i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE * 3) {  
  1096.             int dn = std::min(n - i, (int)BLOCK_SIZE);  
  1097.             j = 0;  
  1098.   
  1099.             for (; j < dn * 3; j += 3) {  
  1100.                 buf[j] = src[j];  
  1101.                 buf[j + 1] = src[j + 1] * (1.f / 255.f);  
  1102.                 buf[j + 2] = src[j + 2] * (1.f / 255.f);  
  1103.             }  
  1104.             cvt(buf, buf, dn);  
  1105.   
  1106.             j = 0;  
  1107.             for (; j < dn * 3; j += 3, dst += dcn) {  
  1108.                 dst[0] = saturate_cast<uchar>(buf[j] * 255.f);  
  1109.                 dst[1] = saturate_cast<uchar>(buf[j + 1] * 255.f);  
  1110.                 dst[2] = saturate_cast<uchar>(buf[j + 2] * 255.f);  
  1111.                 if (dcn == 4)  
  1112.                     dst[3] = alpha;  
  1113.             }  
  1114.         }  
  1115.     }  
  1116.   
  1117.     int dstcn;  
  1118.     HLS2RGB_f cvt;  
  1119. };  
  1120.   
  1121. static const float D65[] = { 0.950456f, 1.f, 1.088754f };  
  1122.   
  1123. enum { LAB_CBRT_TAB_SIZE = 1024, GAMMA_TAB_SIZE = 1024 };  
  1124. static float LabCbrtTab[LAB_CBRT_TAB_SIZE * 4];  
  1125. static const float LabCbrtTabScale = LAB_CBRT_TAB_SIZE / 1.5f;  
  1126.   
  1127. static float sRGBGammaTab[GAMMA_TAB_SIZE * 4], sRGBInvGammaTab[GAMMA_TAB_SIZE * 4];  
  1128. static const float GammaTabScale = (float)GAMMA_TAB_SIZE;  
  1129.   
  1130. static ushort sRGBGammaTab_b[256], linearGammaTab_b[256];  
  1131. #undef lab_shift  
  1132. #define lab_shift xyz_shift  
  1133. #define gamma_shift 3  
  1134. #define lab_shift2 (lab_shift + gamma_shift)  
  1135. #define LAB_CBRT_TAB_SIZE_B (256*3/2*(1<<gamma_shift))  
  1136. static ushort LabCbrtTab_b[LAB_CBRT_TAB_SIZE_B];  
  1137.   
  1138. static void initLabTabs()  
  1139. {  
  1140.     static bool initialized = false;  
  1141.     if (!initialized) {  
  1142.         float f[LAB_CBRT_TAB_SIZE + 1], g[GAMMA_TAB_SIZE + 1], ig[GAMMA_TAB_SIZE + 1], scale = 1.f / LabCbrtTabScale;  
  1143.         int i;  
  1144.         for (i = 0; i <= LAB_CBRT_TAB_SIZE; i++) {  
  1145.             float x = i*scale;  
  1146.             f[i] = x < 0.008856f ? x*7.787f + 0.13793103448275862f : fbcCbrt(x);  
  1147.         }  
  1148.         splineBuild(f, LAB_CBRT_TAB_SIZE, LabCbrtTab);  
  1149.   
  1150.         scale = 1.f / GammaTabScale;  
  1151.         for (i = 0; i <= GAMMA_TAB_SIZE; i++) {  
  1152.             float x = i*scale;  
  1153.             g[i] = x <= 0.04045f ? x*(1.f / 12.92f) : (float)std::pow((double)(x + 0.055)*(1. / 1.055), 2.4);  
  1154.             ig[i] = x <= 0.0031308 ? x*12.92f : (float)(1.055*std::pow((double)x, 1. / 2.4) - 0.055);  
  1155.         }  
  1156.         splineBuild(g, GAMMA_TAB_SIZE, sRGBGammaTab);  
  1157.         splineBuild(ig, GAMMA_TAB_SIZE, sRGBInvGammaTab);  
  1158.   
  1159.         for (i = 0; i < 256; i++) {  
  1160.             float x = i*(1.f / 255.f);  
  1161.             sRGBGammaTab_b[i] = saturate_cast<ushort>(255.f*(1 << gamma_shift)*(x <= 0.04045f ? x*(1.f / 12.92f) : (float)std::pow((double)(x + 0.055)*(1. / 1.055), 2.4)));  
  1162.             linearGammaTab_b[i] = (ushort)(i*(1 << gamma_shift));  
  1163.         }  
  1164.   
  1165.         for (i = 0; i < LAB_CBRT_TAB_SIZE_B; i++) {  
  1166.             float x = i*(1.f / (255.f*(1 << gamma_shift)));  
  1167.             LabCbrtTab_b[i] = saturate_cast<ushort>((1 << lab_shift2)*(x < 0.008856f ? x*7.787f + 0.13793103448275862f : fbcCbrt(x)));  
  1168.         }  
  1169.         initialized = true;  
  1170.     }  
  1171. }  
  1172.   
  1173. struct RGB2Lab_b  
  1174. {  
  1175.     typedef uchar channel_type;  
  1176.   
  1177.     RGB2Lab_b(int _srccn, int blueIdx, const float* _coeffs, const float* _whitept, bool _srgb) : srccn(_srccn), srgb(_srgb)  
  1178.     {  
  1179.         static volatile int _3 = 3;  
  1180.         initLabTabs();  
  1181.   
  1182.         if (!_coeffs)  
  1183.             _coeffs = sRGB2XYZ_D65;  
  1184.         if (!_whitept)  
  1185.             _whitept = D65;  
  1186.   
  1187.         float scale[] = {  
  1188.             (1 << lab_shift) / _whitept[0],  
  1189.             (float)(1 << lab_shift),  
  1190.             (1 << lab_shift) / _whitept[2]  
  1191.         };  
  1192.   
  1193.         for (int i = 0; i < _3; i++) {  
  1194.             coeffs[i * 3 + (blueIdx ^ 2)] = fbcRound(_coeffs[i * 3] * scale[i]);  
  1195.             coeffs[i * 3 + 1] = fbcRound(_coeffs[i * 3 + 1] * scale[i]);  
  1196.             coeffs[i * 3 + blueIdx] = fbcRound(_coeffs[i * 3 + 2] * scale[i]);  
  1197.   
  1198.             FBC_Assert(coeffs[i] >= 0 && coeffs[i * 3 + 1] >= 0 && coeffs[i * 3 + 2] >= 0 &&  
  1199.                 coeffs[i * 3] + coeffs[i * 3 + 1] + coeffs[i * 3 + 2] < 2 * (1 << lab_shift));  
  1200.         }  
  1201.     }  
  1202.   
  1203.     void operator()(const uchar* src, uchar* dst, int n) const  
  1204.     {  
  1205.         const int Lscale = (116 * 255 + 50) / 100;  
  1206.         const int Lshift = -((16 * 255 * (1 << lab_shift2) + 50) / 100);  
  1207.         const ushort* tab = srgb ? sRGBGammaTab_b : linearGammaTab_b;  
  1208.         int i, scn = srccn;  
  1209.         int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],  
  1210.             C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],  
  1211.             C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];  
  1212.         n *= 3;  
  1213.   
  1214.         for (i = 0; i < n; i += 3, src += scn) {  
  1215.             int R = tab[src[0]], G = tab[src[1]], B = tab[src[2]];  
  1216.             int fX = LabCbrtTab_b[FBC_DESCALE(R*C0 + G*C1 + B*C2, lab_shift)];  
  1217.             int fY = LabCbrtTab_b[FBC_DESCALE(R*C3 + G*C4 + B*C5, lab_shift)];  
  1218.             int fZ = LabCbrtTab_b[FBC_DESCALE(R*C6 + G*C7 + B*C8, lab_shift)];  
  1219.   
  1220.             int L = FBC_DESCALE(Lscale*fY + Lshift, lab_shift2);  
  1221.             int a = FBC_DESCALE(500 * (fX - fY) + 128 * (1 << lab_shift2), lab_shift2);  
  1222.             int b = FBC_DESCALE(200 * (fY - fZ) + 128 * (1 << lab_shift2), lab_shift2);  
  1223.   
  1224.             dst[i] = saturate_cast<uchar>(L);  
  1225.             dst[i + 1] = saturate_cast<uchar>(a);  
  1226.             dst[i + 2] = saturate_cast<uchar>(b);  
  1227.         }  
  1228.     }  
  1229.   
  1230.     int srccn;  
  1231.     int coeffs[9];  
  1232.     bool srgb;  
  1233. };  
  1234.   
  1235. template<typename _Tp> static _Tp clip(_Tp value)  
  1236. {  
  1237.     return value < 0.0f ? 0.0f : value > 1.0f ? 1.0f : value;  
  1238. }  
  1239.   
  1240. struct RGB2Lab_f  
  1241. {  
  1242.     typedef float channel_type;  
  1243.   
  1244.     RGB2Lab_f(int _srccn, int blueIdx, const float* _coeffs, const float* _whitept, bool _srgb) : srccn(_srccn), srgb(_srgb)  
  1245.     {  
  1246.         volatile int _3 = 3;  
  1247.         initLabTabs();  
  1248.   
  1249.         if (!_coeffs)  
  1250.             _coeffs = sRGB2XYZ_D65;  
  1251.         if (!_whitept)  
  1252.             _whitept = D65;  
  1253.   
  1254.         float scale[] = { 1.0f / _whitept[0], 1.0f, 1.0f / _whitept[2] };  
  1255.   
  1256.         for (int i = 0; i < _3; i++) {  
  1257.             int j = i * 3;  
  1258.             coeffs[j + (blueIdx ^ 2)] = _coeffs[j] * scale[i];  
  1259.             coeffs[j + 1] = _coeffs[j + 1] * scale[i];  
  1260.             coeffs[j + blueIdx] = _coeffs[j + 2] * scale[i];  
  1261.   
  1262.             FBC_Assert(coeffs[j] >= 0 && coeffs[j + 1] >= 0 && coeffs[j + 2] >= 0 &&  
  1263.                 coeffs[j] + coeffs[j + 1] + coeffs[j + 2] < 1.5f*LabCbrtTabScale);  
  1264.         }  
  1265.     }  
  1266.   
  1267.     void operator()(const float* src, float* dst, int n) const  
  1268.     {  
  1269.         int i, scn = srccn;  
  1270.         float gscale = GammaTabScale;  
  1271.         const float* gammaTab = srgb ? sRGBGammaTab : 0;  
  1272.         float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],  
  1273.             C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],  
  1274.             C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];  
  1275.         n *= 3;  
  1276.   
  1277.         static const float _1_3 = 1.0f / 3.0f;  
  1278.         static const float _a = 16.0f / 116.0f;  
  1279.         for (i = 0; i < n; i += 3, src += scn) {  
  1280.             float R = clip<float>(src[0]);  
  1281.             float G = clip<float>(src[1]);  
  1282.             float B = clip<float>(src[2]);  
  1283.   
  1284.             if (gammaTab) {  
  1285.                 R = splineInterpolate(R * gscale, gammaTab, GAMMA_TAB_SIZE);  
  1286.                 G = splineInterpolate(G * gscale, gammaTab, GAMMA_TAB_SIZE);  
  1287.                 B = splineInterpolate(B * gscale, gammaTab, GAMMA_TAB_SIZE);  
  1288.             }  
  1289.             float X = R*C0 + G*C1 + B*C2;  
  1290.             float Y = R*C3 + G*C4 + B*C5;  
  1291.             float Z = R*C6 + G*C7 + B*C8;  
  1292.   
  1293.             float FX = X > 0.008856f ? std::pow(X, _1_3) : (7.787f * X + _a);  
  1294.             float FY = Y > 0.008856f ? std::pow(Y, _1_3) : (7.787f * Y + _a);  
  1295.             float FZ = Z > 0.008856f ? std::pow(Z, _1_3) : (7.787f * Z + _a);  
  1296.   
  1297.             float L = Y > 0.008856f ? (116.f * FY - 16.f) : (903.3f * Y);  
  1298.             float a = 500.f * (FX - FY);  
  1299.             float b = 200.f * (FY - FZ);  
  1300.   
  1301.             dst[i] = L;  
  1302.             dst[i + 1] = a;  
  1303.             dst[i + 2] = b;  
  1304.         }  
  1305.     }  
  1306.   
  1307.     int srccn;  
  1308.     float coeffs[9];  
  1309.     bool srgb;  
  1310. };  
  1311.   
  1312. struct RGB2Luv_f  
  1313. {  
  1314.     typedef float channel_type;  
  1315.   
  1316.     RGB2Luv_f(int _srccn, int blueIdx, const float* _coeffs, const float* whitept, bool _srgb) : srccn(_srccn), srgb(_srgb)  
  1317.     {  
  1318.         volatile int i;  
  1319.         initLabTabs();  
  1320.   
  1321.         if (!_coeffs) _coeffs = sRGB2XYZ_D65;  
  1322.         if (!whitept) whitept = D65;  
  1323.   
  1324.         for (i = 0; i < 3; i++) {  
  1325.             coeffs[i * 3] = _coeffs[i * 3];  
  1326.             coeffs[i * 3 + 1] = _coeffs[i * 3 + 1];  
  1327.             coeffs[i * 3 + 2] = _coeffs[i * 3 + 2];  
  1328.             if (blueIdx == 0)  
  1329.                 std::swap(coeffs[i * 3], coeffs[i * 3 + 2]);  
  1330.             FBC_Assert(coeffs[i * 3] >= 0 && coeffs[i * 3 + 1] >= 0 && coeffs[i * 3 + 2] >= 0 &&  
  1331.                 coeffs[i * 3] + coeffs[i * 3 + 1] + coeffs[i * 3 + 2] < 1.5f);  
  1332.         }  
  1333.   
  1334.         float d = 1.f / (whitept[0] + whitept[1] * 15 + whitept[2] * 3);  
  1335.         un = 4 * whitept[0] * d;  
  1336.         vn = 9 * whitept[1] * d;  
  1337.   
  1338.         FBC_Assert(whitept[1] == 1.f);  
  1339.     }  
  1340.   
  1341.     void operator()(const float* src, float* dst, int n) const  
  1342.     {  
  1343.         int i, scn = srccn;  
  1344.         float gscale = GammaTabScale;  
  1345.         const float* gammaTab = srgb ? sRGBGammaTab : 0;  
  1346.         float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],  
  1347.             C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],  
  1348.             C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];  
  1349.         float _un = 13 * un, _vn = 13 * vn;  
  1350.         n *= 3;  
  1351.   
  1352.         for (i = 0; i < n; i += 3, src += scn) {  
  1353.             float R = src[0], G = src[1], B = src[2];  
  1354.             if (gammaTab) {  
  1355.                 R = splineInterpolate(R*gscale, gammaTab, GAMMA_TAB_SIZE);  
  1356.                 G = splineInterpolate(G*gscale, gammaTab, GAMMA_TAB_SIZE);  
  1357.                 B = splineInterpolate(B*gscale, gammaTab, GAMMA_TAB_SIZE);  
  1358.             }  
  1359.   
  1360.             float X = R*C0 + G*C1 + B*C2;  
  1361.             float Y = R*C3 + G*C4 + B*C5;  
  1362.             float Z = R*C6 + G*C7 + B*C8;  
  1363.   
  1364.             float L = splineInterpolate(Y*LabCbrtTabScale, LabCbrtTab, LAB_CBRT_TAB_SIZE);  
  1365.             L = 116.f*L - 16.f;  
  1366.   
  1367.             float d = (4 * 13) / std::max(X + 15 * Y + 3 * Z, FLT_EPSILON);  
  1368.             float u = L*(X*d - _un);  
  1369.             float v = L*((9 * 0.25f)*Y*d - _vn);  
  1370.   
  1371.             dst[i] = L; dst[i + 1] = u; dst[i + 2] = v;  
  1372.         }  
  1373.     }  
  1374.   
  1375.     int srccn;  
  1376.     float coeffs[9], un, vn;  
  1377.     bool srgb;  
  1378. };  
  1379.   
  1380. struct RGB2Luv_b  
  1381. {  
  1382.     typedef uchar channel_type;  
  1383.   
  1384.     RGB2Luv_b(int _srccn, int blueIdx, const float* _coeffs, const float* _whitept, bool _srgb)  
  1385.         : srccn(_srccn), cvt(3, blueIdx, _coeffs, _whitept, _srgb) { }  
  1386.   
  1387.     void operator()(const uchar* src, uchar* dst, int n) const  
  1388.     {  
  1389.         int i, j, scn = srccn;  
  1390.         float FBC_DECL_ALIGNED(16) buf[3 * BLOCK_SIZE];  
  1391.   
  1392.         for (i = 0; i < n; i += BLOCK_SIZE, dst += BLOCK_SIZE * 3) {  
  1393.             int dn = std::min(n - i, (int)BLOCK_SIZE);  
  1394.             j = 0;  
  1395.             for (; j < dn * 3; j += 3, src += scn) {  
  1396.                 buf[j] = src[0] * (1.f / 255.f);  
  1397.                 buf[j + 1] = (float)(src[1] * (1.f / 255.f));  
  1398.                 buf[j + 2] = (float)(src[2] * (1.f / 255.f));  
  1399.             }  
  1400.             cvt(buf, buf, dn);  
  1401.   
  1402.             j = 0;  
  1403.             for (; j < dn * 3; j += 3) {  
  1404.                 dst[j] = saturate_cast<uchar>(buf[j] * 2.55f);  
  1405.                 dst[j + 1] = saturate_cast<uchar>(buf[j + 1] * 0.72033898305084743f + 96.525423728813564f);  
  1406.                 dst[j + 2] = saturate_cast<uchar>(buf[j + 2] * 0.9732824427480916f + 136.259541984732824f);  
  1407.             }  
  1408.         }  
  1409.     }  
  1410.   
  1411.     int srccn;  
  1412.     RGB2Luv_f cvt;  
  1413. };  
  1414.   
  1415. struct Lab2RGB_f  
  1416. {  
  1417.     typedef float channel_type;  
  1418.   
  1419.     Lab2RGB_f(int _dstcn, int blueIdx, const float* _coeffs, const float* _whitept, bool _srgb) : dstcn(_dstcn), srgb(_srgb)  
  1420.     {  
  1421.         initLabTabs();  
  1422.   
  1423.         if (!_coeffs)  
  1424.             _coeffs = XYZ2sRGB_D65;  
  1425.         if (!_whitept)  
  1426.             _whitept = D65;  
  1427.   
  1428.         for (int i = 0; i < 3; i++) {  
  1429.             coeffs[i + (blueIdx ^ 2) * 3] = _coeffs[i] * _whitept[i];  
  1430.             coeffs[i + 3] = _coeffs[i + 3] * _whitept[i];  
  1431.             coeffs[i + blueIdx * 3] = _coeffs[i + 6] * _whitept[i];  
  1432.         }  
  1433.     }  
  1434.   
  1435.     void operator()(const float* src, float* dst, int n) const  
  1436.     {  
  1437.         int i, dcn = dstcn;  
  1438.         const float* gammaTab = srgb ? sRGBInvGammaTab : 0;  
  1439.         float gscale = GammaTabScale;  
  1440.         float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],  
  1441.             C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],  
  1442.             C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];  
  1443.         float alpha = ColorChannel<float>::max();  
  1444.         n *= 3;  
  1445.   
  1446.         static const float lThresh = 0.008856f * 903.3f;  
  1447.         static const float fThresh = 7.787f * 0.008856f + 16.0f / 116.0f;  
  1448.         for (i = 0; i < n; i += 3, dst += dcn) {  
  1449.             float li = src[i];  
  1450.             float ai = src[i + 1];  
  1451.             float bi = src[i + 2];  
  1452.   
  1453.             float y, fy;  
  1454.             if (li <= lThresh) {  
  1455.                 y = li / 903.3f;  
  1456.                 fy = 7.787f * y + 16.0f / 116.0f;  
  1457.             } else {  
  1458.                 fy = (li + 16.0f) / 116.0f;  
  1459.                 y = fy * fy * fy;  
  1460.             }  
  1461.   
  1462.             float fxz[] = { ai / 500.0f + fy, fy - bi / 200.0f };  
  1463.   
  1464.             for (int j = 0; j < 2; j++)  
  1465.                 if (fxz[j] <= fThresh)  
  1466.                     fxz[j] = (fxz[j] - 16.0f / 116.0f) / 7.787f;  
  1467.                 else  
  1468.                     fxz[j] = fxz[j] * fxz[j] * fxz[j];  
  1469.   
  1470.   
  1471.             float x = fxz[0], z = fxz[1];  
  1472.             float ro = C0 * x + C1 * y + C2 * z;  
  1473.             float go = C3 * x + C4 * y + C5 * z;  
  1474.             float bo = C6 * x + C7 * y + C8 * z;  
  1475.             ro = clip(ro);  
  1476.             go = clip(go);  
  1477.             bo = clip(bo);  
  1478.   
  1479.             if (gammaTab) {  
  1480.                 ro = splineInterpolate(ro * gscale, gammaTab, GAMMA_TAB_SIZE);  
  1481.                 go = splineInterpolate(go * gscale, gammaTab, GAMMA_TAB_SIZE);  
  1482.                 bo = splineInterpolate(bo * gscale, gammaTab, GAMMA_TAB_SIZE);  
  1483.             }  
  1484.   
  1485.             dst[0] = ro, dst[1] = go, dst[2] = bo;  
  1486.             if (dcn == 4)  
  1487.                 dst[3] = alpha;  
  1488.         }  
  1489.     }  
  1490.   
  1491.     int dstcn;  
  1492.     float coeffs[9];  
  1493.     bool srgb;  
  1494. };  
  1495.   
  1496. struct Lab2RGB_b  
  1497. {  
  1498.     typedef uchar channel_type;  
  1499.   
  1500.     Lab2RGB_b(int _dstcn, int blueIdx, const float* _coeffs, const float* _whitept, bool _srgb)  
  1501.         : dstcn(_dstcn), cvt(3, blueIdx, _coeffs, _whitept, _srgb) { }  
  1502.   
  1503.     void operator()(const uchar* src, uchar* dst, int n) const  
  1504.     {  
  1505.         int i, j, dcn = dstcn;  
  1506.         uchar alpha = ColorChannel<uchar>::max();  
  1507.         float FBC_DECL_ALIGNED(16) buf[3 * BLOCK_SIZE];  
  1508.   
  1509.         for (i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE * 3)  
  1510.         {  
  1511.             int dn = std::min(n - i, (int)BLOCK_SIZE);  
  1512.             j = 0;  
  1513.             for (; j < dn * 3; j += 3) {  
  1514.                 buf[j] = src[j] * (100.f / 255.f);  
  1515.                 buf[j + 1] = (float)(src[j + 1] - 128);  
  1516.                 buf[j + 2] = (float)(src[j + 2] - 128);  
  1517.             }  
  1518.             cvt(buf, buf, dn);  
  1519.             j = 0;  
  1520.             for (; j < dn * 3; j += 3, dst += dcn) {  
  1521.                 dst[0] = saturate_cast<uchar>(buf[j] * 255.f);  
  1522.                 dst[1] = saturate_cast<uchar>(buf[j + 1] * 255.f);  
  1523.                 dst[2] = saturate_cast<uchar>(buf[j + 2] * 255.f);  
  1524.                 if (dcn == 4)  
  1525.                     dst[3] = alpha;  
  1526.             }  
  1527.         }  
  1528.     }  
  1529.   
  1530.     int dstcn;  
  1531.     Lab2RGB_f cvt;  
  1532. };  
  1533.   
  1534. struct Luv2RGB_f  
  1535. {  
  1536.     typedef float channel_type;  
  1537.   
  1538.     Luv2RGB_f(int _dstcn, int blueIdx, const float* _coeffs, const float* whitept, bool _srgb) : dstcn(_dstcn), srgb(_srgb)  
  1539.     {  
  1540.         initLabTabs();  
  1541.   
  1542.         if (!_coeffs) _coeffs = XYZ2sRGB_D65;  
  1543.         if (!whitept) whitept = D65;  
  1544.   
  1545.         for (int i = 0; i < 3; i++) {  
  1546.             coeffs[i + (blueIdx ^ 2) * 3] = _coeffs[i];  
  1547.             coeffs[i + 3] = _coeffs[i + 3];  
  1548.             coeffs[i + blueIdx * 3] = _coeffs[i + 6];  
  1549.         }  
  1550.   
  1551.         float d = 1.f / (whitept[0] + whitept[1] * 15 + whitept[2] * 3);  
  1552.         un = 4 * whitept[0] * d;  
  1553.         vn = 9 * whitept[1] * d;  
  1554.   
  1555.         FBC_Assert(whitept[1] == 1.f);  
  1556.     }  
  1557.   
  1558.     void operator()(const float* src, float* dst, int n) const  
  1559.     {  
  1560.         int i, dcn = dstcn;  
  1561.         const float* gammaTab = srgb ? sRGBInvGammaTab : 0;  
  1562.         float gscale = GammaTabScale;  
  1563.         float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],  
  1564.             C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],  
  1565.             C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];  
  1566.         float alpha = ColorChannel<float>::max();  
  1567.         float _un = un, _vn = vn;  
  1568.         n *= 3;  
  1569.   
  1570.         for (i = 0; i < n; i += 3, dst += dcn) {  
  1571.             float L = src[i], u = src[i + 1], v = src[i + 2], d, X, Y, Z;  
  1572.             Y = (L + 16.f) * (1.f / 116.f);  
  1573.             Y = Y*Y*Y;  
  1574.             d = (1.f / 13.f) / L;  
  1575.             u = u*d + _un;  
  1576.             v = v*d + _vn;  
  1577.             float iv = 1.f / v;  
  1578.             X = 2.25f * u * Y * iv;  
  1579.             Z = (12 - 3 * u - 20 * v) * Y * 0.25f * iv;  
  1580.   
  1581.             float R = X*C0 + Y*C1 + Z*C2;  
  1582.             float G = X*C3 + Y*C4 + Z*C5;  
  1583.             float B = X*C6 + Y*C7 + Z*C8;  
  1584.   
  1585.             R = std::min(std::max(R, 0.f), 1.f);  
  1586.             G = std::min(std::max(G, 0.f), 1.f);  
  1587.             B = std::min(std::max(B, 0.f), 1.f);  
  1588.   
  1589.             if (gammaTab) {  
  1590.                 R = splineInterpolate(R*gscale, gammaTab, GAMMA_TAB_SIZE);  
  1591.                 G = splineInterpolate(G*gscale, gammaTab, GAMMA_TAB_SIZE);  
  1592.                 B = splineInterpolate(B*gscale, gammaTab, GAMMA_TAB_SIZE);  
  1593.             }  
  1594.   
  1595.             dst[0] = R; dst[1] = G; dst[2] = B;  
  1596.             if (dcn == 4)  
  1597.                 dst[3] = alpha;  
  1598.         }  
  1599.     }  
  1600.   
  1601.     int dstcn;  
  1602.     float coeffs[9], un, vn;  
  1603.     bool srgb;  
  1604. };  
  1605.   
  1606. struct Luv2RGB_b  
  1607. {  
  1608.     typedef uchar channel_type;  
  1609.   
  1610.     Luv2RGB_b(int _dstcn, int blueIdx, const float* _coeffs, const float* _whitept, bool _srgb)  
  1611.         : dstcn(_dstcn), cvt(3, blueIdx, _coeffs, _whitept, _srgb) { }  
  1612.   
  1613.     void operator()(const uchar* src, uchar* dst, int n) const  
  1614.     {  
  1615.         int i, j, dcn = dstcn;  
  1616.         uchar alpha = ColorChannel<uchar>::max();  
  1617.         float FBC_DECL_ALIGNED(16) buf[3 * BLOCK_SIZE];  
  1618.   
  1619.         for (i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE * 3) {  
  1620.             int dn = std::min(n - i, (int)BLOCK_SIZE);  
  1621.             j = 0;  
  1622.             for (; j < dn * 3; j += 3) {  
  1623.                 buf[j] = src[j] * (100.f / 255.f);  
  1624.                 buf[j + 1] = (float)(src[j + 1] * 1.388235294117647f - 134.f);  
  1625.                 buf[j + 2] = (float)(src[j + 2] * 1.027450980392157f - 140.f);  
  1626.             }  
  1627.             cvt(buf, buf, dn);  
  1628.   
  1629.             j = 0;  
  1630.             for (; j < dn * 3; j += 3, dst += dcn) {  
  1631.                 dst[0] = saturate_cast<uchar>(buf[j] * 255.f);  
  1632.                 dst[1] = saturate_cast<uchar>(buf[j + 1] * 255.f);  
  1633.                 dst[2] = saturate_cast<uchar>(buf[j + 2] * 255.f);  
  1634.                 if (dcn == 4)  
  1635.                     dst[3] = alpha;  
  1636.             }  
  1637.         }  
  1638.     }  
  1639.   
  1640.     int dstcn;  
  1641.     Luv2RGB_f cvt;  
  1642. };  
  1643.   
  1644. const int ITUR_BT_601_CY = 1220542;  
  1645. const int ITUR_BT_601_CUB = 2116026;  
  1646. const int ITUR_BT_601_CUG = -409993;  
  1647. const int ITUR_BT_601_CVG = -852492;  
  1648. const int ITUR_BT_601_CVR = 1673527;  
  1649. const int ITUR_BT_601_SHIFT = 20;  
  1650.   
  1651. // RGB到YUV420p转换的系数
  1652. const int ITUR_BT_601_CRY = 269484;  
  1653. const int ITUR_BT_601_CGY = 528482;  
  1654. const int ITUR_BT_601_CBY = 102760;  
  1655. const int ITUR_BT_601_CRU = -155188;  
  1656. const int ITUR_BT_601_CGU = -305135;  
  1657. const int ITUR_BT_601_CBU = 460324;  
  1658. const int ITUR_BT_601_CGV = -385875;  
  1659. const int ITUR_BT_601_CBV = -74448;  
  1660.   
  1661. template<typename _Tp, int chs, int bIdx, int uIdx>  
  1662. struct YUV420sp2RGB888Invoker  
  1663. {  
  1664.     Mat_<_Tp, chs>* dst;  
  1665.     const uchar* my1, *muv;  
  1666.     int width, stride;  
  1667.   
  1668.     YUV420sp2RGB888Invoker(Mat_<_Tp, chs>* _dst, int _stride, const uchar* _y1, const uchar* _uv)  
  1669.         : dst(_dst), my1(_y1), muv(_uv), width(_dst->cols), stride(_stride) {}  
  1670.   
  1671.     void operator()(const Range& range) const  
  1672.     {  
  1673.         int rangeBegin = range.start * 2;  
  1674.         int rangeEnd = range.end * 2;  
  1675.   
  1676.         //R = 1.164(Y - 16) + 1.596(V - 128)  
  1677.         //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)  
  1678.         //B = 1.164(Y - 16)                  + 2.018(U - 128)  
  1679.   
  1680.         //R = (1220542(Y - 16) + 1673527(V - 128)                  + (1 << 19)) >> 20  
  1681.         //G = (1220542(Y - 16) - 852492(V - 128) - 409993(U - 128) + (1 << 19)) >> 20  
  1682.         //B = (1220542(Y - 16)                  + 2116026(U - 128) + (1 << 19)) >> 20  
  1683.   
  1684.         const uchar* y1 = my1 + rangeBegin * stride, *uv = muv + rangeBegin * stride / 2;  
  1685.   
  1686.         for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, uv += stride) {  
  1687.             uchar* row1 = (uchar*)dst->ptr(j);  
  1688.             uchar* row2 = (uchar*)dst->ptr(j + 1);  
  1689.             const uchar* y2 = y1 + stride;  
  1690.   
  1691.             for (int i = 0; i < width; i += 2, row1 += 6, row2 += 6) {  
  1692.                 int u = int(uv[i + 0 + uIdx]) - 128;  
  1693.                 int v = int(uv[i + 1 - uIdx]) - 128;  
  1694.   
  1695.                 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;  
  1696.                 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;  
  1697.                 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;  
  1698.   
  1699.                 int y00 = std::max(0, int(y1[i]) - 16) * ITUR_BT_601_CY;  
  1700.                 row1[2 - bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);  
  1701.                 row1[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);  
  1702.                 row1[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);  
  1703.   
  1704.                 int y01 = std::max(0, int(y1[i + 1]) - 16) * ITUR_BT_601_CY;  
  1705.                 row1[5 - bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);  
  1706.                 row1[4] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);  
  1707.                 row1[3 + bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);  
  1708.   
  1709.                 int y10 = std::max(0, int(y2[i]) - 16) * ITUR_BT_601_CY;  
  1710.                 row2[2 - bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);  
  1711.                 row2[1] = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);  
  1712.                 row2[bIdx] = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);  
  1713.   
  1714.                 int y11 = std::max(0, int(y2[i + 1]) - 16) * ITUR_BT_601_CY;  
  1715.                 row2[5 - bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);  
  1716.                 row2[4] = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);  
  1717.                 row2[3 + bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);  
  1718.             }  
  1719.         }  
  1720.     }  
  1721. };  
  1722.   
  1723. template<typename _Tp, int chs, int bIdx, int uIdx>  
  1724. struct YUV420sp2RGBA8888Invoker  
  1725. {  
  1726.     Mat_<_Tp, chs>* dst;  
  1727.     const uchar* my1, *muv;  
  1728.     int width, stride;  
  1729.   
  1730.     YUV420sp2RGBA8888Invoker(Mat_<_Tp, chs>* _dst, int _stride, const uchar* _y1, const uchar* _uv)  
  1731.         : dst(_dst), my1(_y1), muv(_uv), width(_dst->cols), stride(_stride) {}  
  1732.   
  1733.     void operator()(const Range& range) const  
  1734.     {  
  1735.         int rangeBegin = range.start * 2;  
  1736.         int rangeEnd = range.end * 2;  
  1737.   
  1738.         //R = 1.164(Y - 16) + 1.596(V - 128)  
  1739.         //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)  
  1740.         //B = 1.164(Y - 16)                  + 2.018(U - 128)  
  1741.   
  1742.         //R = (1220542(Y - 16) + 1673527(V - 128)                  + (1 << 19)) >> 20  
  1743.         //G = (1220542(Y - 16) - 852492(V - 128) - 409993(U - 128) + (1 << 19)) >> 20  
  1744.         //B = (1220542(Y - 16)                  + 2116026(U - 128) + (1 << 19)) >> 20  
  1745.   
  1746.         const uchar* y1 = my1 + rangeBegin * stride, *uv = muv + rangeBegin * stride / 2;  
  1747.   
  1748.         for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, uv += stride) {  
  1749.             uchar* row1 = (uchar*)dst->ptr(j);  
  1750.             uchar* row2 = (uchar*)dst->ptr(j + 1);  
  1751.             const uchar* y2 = y1 + stride;  
  1752.   
  1753.             for (int i = 0; i < width; i += 2, row1 += 8, row2 += 8) {  
  1754.                 int u = int(uv[i + 0 + uIdx]) - 128;  
  1755.                 int v = int(uv[i + 1 - uIdx]) - 128;  
  1756.   
  1757.                 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;  
  1758.                 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;  
  1759.                 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;  
  1760.   
  1761.                 int y00 = std::max(0, int(y1[i]) - 16) * ITUR_BT_601_CY;  
  1762.                 row1[2 - bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);  
  1763.                 row1[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);  
  1764.                 row1[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);  
  1765.                 row1[3] = uchar(0xff);  
  1766.   
  1767.                 int y01 = std::max(0, int(y1[i + 1]) - 16) * ITUR_BT_601_CY;  
  1768.                 row1[6 - bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);  
  1769.                 row1[5] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);  
  1770.                 row1[4 + bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);  
  1771.                 row1[7] = uchar(0xff);  
  1772.   
  1773.                 int y10 = std::max(0, int(y2[i]) - 16) * ITUR_BT_601_CY;  
  1774.                 row2[2 - bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);  
  1775.                 row2[1] = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);  
  1776.                 row2[bIdx] = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);  
  1777.                 row2[3] = uchar(0xff);  
  1778.   
  1779.                 int y11 = std::max(0, int(y2[i + 1]) - 16) * ITUR_BT_601_CY;  
  1780.                 row2[6 - bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);  
  1781.                 row2[5] = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);  
  1782.                 row2[4 + bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);  
  1783.                 row2[7] = uchar(0xff);  
  1784.             }  
  1785.         }  
  1786.     }  
  1787. };  
  1788.   
  1789. template<typename _Tp, int chs, int bIdx>  
  1790. struct YUV420p2RGB888Invoker  
  1791. {  
  1792.     Mat_<_Tp, chs>* dst;  
  1793.     const uchar* my1, *mu, *mv;  
  1794.     int width, stride;  
  1795.     int ustepIdx, vstepIdx;  
  1796.   
  1797.     YUV420p2RGB888Invoker(Mat_<_Tp, chs>* _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int _ustepIdx, int _vstepIdx)  
  1798.         : dst(_dst), my1(_y1), mu(_u), mv(_v), width(_dst->cols), stride(_stride), ustepIdx(_ustepIdx), vstepIdx(_vstepIdx) {}  
  1799.   
  1800.     void operator()(const Range& range) const  
  1801.     {  
  1802.         const int rangeBegin = range.start * 2;  
  1803.         const int rangeEnd = range.end * 2;  
  1804.   
  1805.         int uvsteps[2] = { width / 2, stride - width / 2 };  
  1806.         int usIdx = ustepIdx, vsIdx = vstepIdx;  
  1807.   
  1808.         const uchar* y1 = my1 + rangeBegin * stride;  
  1809.         const uchar* u1 = mu + (range.start / 2) * stride;  
  1810.         const uchar* v1 = mv + (range.start / 2) * stride;  
  1811.   
  1812.         if (range.start % 2 == 1) {  
  1813.             u1 += uvsteps[(usIdx++) & 1];  
  1814.             v1 += uvsteps[(vsIdx++) & 1];  
  1815.         }  
  1816.   
  1817.         for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, u1 += uvsteps[(usIdx++) & 1], v1 += uvsteps[(vsIdx++) & 1]) {  
  1818.             uchar* row1 = (uchar*)dst->ptr(j);  
  1819.             uchar* row2 = (uchar*)dst->ptr(j + 1);  
  1820.             const uchar* y2 = y1 + stride;  
  1821.   
  1822.             for (int i = 0; i < width / 2; i += 1, row1 += 6, row2 += 6) {  
  1823.                 int u = int(u1[i]) - 128;  
  1824.                 int v = int(v1[i]) - 128;  
  1825.   
  1826.                 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;  
  1827.                 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;  
  1828.                 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;  
  1829.   
  1830.                 int y00 = std::max(0, int(y1[2 * i]) - 16) * ITUR_BT_601_CY;  
  1831.                 row1[2 - bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);  
  1832.                 row1[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);  
  1833.                 row1[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);  
  1834.   
  1835.                 int y01 = std::max(0, int(y1[2 * i + 1]) - 16) * ITUR_BT_601_CY;  
  1836.                 row1[5 - bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);  
  1837.                 row1[4] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);  
  1838.                 row1[3 + bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);  
  1839.   
  1840.                 int y10 = std::max(0, int(y2[2 * i]) - 16) * ITUR_BT_601_CY;  
  1841.                 row2[2 - bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);  
  1842.                 row2[1] = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);  
  1843.                 row2[bIdx] = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);  
  1844.   
  1845.                 int y11 = std::max(0, int(y2[2 * i + 1]) - 16) * ITUR_BT_601_CY;  
  1846.                 row2[5 - bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);  
  1847.                 row2[4] = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);  
  1848.                 row2[3 + bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);  
  1849.             }  
  1850.         }  
  1851.     }  
  1852. };  
  1853.   
  1854. template<typename _Tp, int chs, int bIdx>  
  1855. struct YUV420p2RGBA8888Invoker  
  1856. {  
  1857.     Mat_<_Tp, chs>* dst;  
  1858.     const uchar* my1, *mu, *mv;  
  1859.     int width, stride;  
  1860.     int ustepIdx, vstepIdx;  
  1861.   
  1862.     YUV420p2RGBA8888Invoker(Mat_<_Tp, chs>* _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int _ustepIdx, int _vstepIdx)  
  1863.         : dst(_dst), my1(_y1), mu(_u), mv(_v), width(_dst->cols), stride(_stride), ustepIdx(_ustepIdx), vstepIdx(_vstepIdx) {}  
  1864.   
  1865.     void operator()(const Range& range) const  
  1866.     {  
  1867.         int rangeBegin = range.start * 2;  
  1868.         int rangeEnd = range.end * 2;  
  1869.   
  1870.         int uvsteps[2] = { width / 2, stride - width / 2 };  
  1871.         int usIdx = ustepIdx, vsIdx = vstepIdx;  
  1872.   
  1873.         const uchar* y1 = my1 + rangeBegin * stride;  
  1874.         const uchar* u1 = mu + (range.start / 2) * stride;  
  1875.         const uchar* v1 = mv + (range.start / 2) * stride;  
  1876.   
  1877.         if (range.start % 2 == 1) {  
  1878.             u1 += uvsteps[(usIdx++) & 1];  
  1879.             v1 += uvsteps[(vsIdx++) & 1];  
  1880.         }  
  1881.   
  1882.         for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, u1 += uvsteps[(usIdx++) & 1], v1 += uvsteps[(vsIdx++) & 1]) {  
  1883.             uchar* row1 = (uchar*)dst->ptr(j);  
  1884.             uchar* row2 = (uchar*)dst->ptr(j + 1);  
  1885.             const uchar* y2 = y1 + stride;  
  1886.   
  1887.             for (int i = 0; i < width / 2; i += 1, row1 += 8, row2 += 8) {  
  1888.                 int u = int(u1[i]) - 128;  
  1889.                 int v = int(v1[i]) - 128;  
  1890.   
  1891.                 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;  
  1892.                 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;  
  1893.                 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;  
  1894.   
  1895.                 int y00 = std::max(0, int(y1[2 * i]) - 16) * ITUR_BT_601_CY;  
  1896.                 row1[2 - bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);  
  1897.                 row1[1] = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);  
  1898.                 row1[bIdx] = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);  
  1899.                 row1[3] = uchar(0xff);  
  1900.   
  1901.                 int y01 = std::max(0, int(y1[2 * i + 1]) - 16) * ITUR_BT_601_CY;  
  1902.                 row1[6 - bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);  
  1903.                 row1[5] = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);  
  1904.                 row1[4 + bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);  
  1905.                 row1[7] = uchar(0xff);  
  1906.   
  1907.                 int y10 = std::max(0, int(y2[2 * i]) - 16) * ITUR_BT_601_CY;  
  1908.                 row2[2 - bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);  
  1909.                 row2[1] = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);  
  1910.                 row2[bIdx] = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);  
  1911.                 row2[3] = uchar(0xff);  
  1912.   
  1913.                 int y11 = std::max(0, int(y2[2 * i + 1]) - 16) * ITUR_BT_601_CY;  
  1914.                 row2[6 - bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);  
  1915.                 row2[5] = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);  
  1916.                 row2[4 + bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);  
  1917.                 row2[7] = uchar(0xff);  
  1918.             }  
  1919.         }  
  1920.     }  
  1921. };  
  1922.   
  1923. template<typename _Tp, int chs, int bIdx, int uIdx>  
  1924. inline void cvtYUV420sp2RGB(Mat_<_Tp, chs>& _dst, int _stride, const uchar* _y1, const uchar* _uv)  
  1925. {  
  1926.     YUV420sp2RGB888Invoker<_Tp, chs, bIdx, uIdx> converter(&_dst, _stride, _y1, _uv);  
  1927.     converter(Range(0, _dst.rows / 2));  
  1928. }  
  1929.   
  1930. template<typename _Tp, int chs, int bIdx, int uIdx>  
  1931. inline void cvtYUV420sp2RGBA(Mat_<_Tp, chs>& _dst, int _stride, const uchar* _y1, const uchar* _uv)  
  1932. {  
  1933.     YUV420sp2RGBA8888Invoker<_Tp, chs, bIdx, uIdx> converter(&_dst, _stride, _y1, _uv);  
  1934.     converter(Range(0, _dst.rows / 2));  
  1935. }  
  1936.   
  1937. template<typename _Tp, int chs, int bIdx>  
  1938. inline void cvtYUV420p2RGB(Mat_<_Tp, chs>& _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int ustepIdx, int vstepIdx)  
  1939. {  
  1940.     YUV420p2RGB888Invoker<_Tp, chs, bIdx> converter(&_dst, _stride, _y1, _u, _v, ustepIdx, vstepIdx);  
  1941.     converter(Range(0, _dst.rows / 2));  
  1942. }  
  1943.   
  1944. template<typename _Tp, int chs, int bIdx>  
  1945. inline void cvtYUV420p2RGBA(Mat_<_Tp, chs>& _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int ustepIdx, int vstepIdx)  
  1946. {  
  1947.     YUV420p2RGBA8888Invoker<_Tp, chs, bIdx> converter(&_dst, _stride, _y1, _u, _v, ustepIdx, vstepIdx);  
  1948.     converter(Range(0, _dst.rows / 2));  
  1949. }  
  1950.   
  1951. template<typename _Tp, int chs1, int chs2, int bIdx>  
  1952. struct RGB888toYUV420pInvoker  
  1953. {  
  1954.     RGB888toYUV420pInvoker(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>* dst, const int uIdx)  
  1955.         : src_(src), dst_(dst), uIdx_(uIdx) { }  
  1956.   
  1957.     void operator()(const Range& rowRange) const  
  1958.     {  
  1959.         const int w = src_.cols;  
  1960.         const int h = src_.rows;  
  1961.   
  1962.         const int cn = src_.channels;  
  1963.         for (int i = rowRange.start; i < rowRange.end; i++) {  
  1964.             const uchar* row0 = src_.ptr(2 * i);  
  1965.             const uchar* row1 = src_.ptr(2 * i + 1);  
  1966.   
  1967.             uchar* y = (uchar*)dst_->ptr(2 * i);  
  1968.             uchar* u = (uchar*)dst_->ptr(h + i / 2) + (i % 2) * (w / 2);  
  1969.             uchar* v = (uchar*)dst_->ptr(h + (i + h / 2) / 2) + ((i + h / 2) % 2) * (w / 2);  
  1970.             if (uIdx_ == 2) std::swap(u, v);  
  1971.   
  1972.             for (int j = 0, k = 0; j < w * cn; j += 2 * cn, k++) {  
  1973.                 int r00 = row0[2 - bIdx + j];      int g00 = row0[1 + j];      int b00 = row0[bIdx + j];  
  1974.                 int r01 = row0[2 - bIdx + cn + j]; int g01 = row0[1 + cn + j]; int b01 = row0[bIdx + cn + j];  
  1975.                 int r10 = row1[2 - bIdx + j];      int g10 = row1[1 + j];      int b10 = row1[bIdx + j];  
  1976.                 int r11 = row1[2 - bIdx + cn + j]; int g11 = row1[1 + cn + j]; int b11 = row1[bIdx + cn + j];  
  1977.   
  1978.                 const int shifted16 = (16 << ITUR_BT_601_SHIFT);  
  1979.                 const int halfShift = (1 << (ITUR_BT_601_SHIFT - 1));  
  1980.                 int y00 = ITUR_BT_601_CRY * r00 + ITUR_BT_601_CGY * g00 + ITUR_BT_601_CBY * b00 + halfShift + shifted16;  
  1981.                 int y01 = ITUR_BT_601_CRY * r01 + ITUR_BT_601_CGY * g01 + ITUR_BT_601_CBY * b01 + halfShift + shifted16;  
  1982.                 int y10 = ITUR_BT_601_CRY * r10 + ITUR_BT_601_CGY * g10 + ITUR_BT_601_CBY * b10 + halfShift + shifted16;  
  1983.                 int y11 = ITUR_BT_601_CRY * r11 + ITUR_BT_601_CGY * g11 + ITUR_BT_601_CBY * b11 + halfShift + shifted16;  
  1984.   
  1985.                 y[2 * k + 0] = saturate_cast<uchar>(y00 >> ITUR_BT_601_SHIFT);  
  1986.                 y[2 * k + 1] = saturate_cast<uchar>(y01 >> ITUR_BT_601_SHIFT);  
  1987.                 y[2 * k + dst_->step + 0] = saturate_cast<uchar>(y10 >> ITUR_BT_601_SHIFT);  
  1988.                 y[2 * k + dst_->step + 1] = saturate_cast<uchar>(y11 >> ITUR_BT_601_SHIFT);  
  1989.   
  1990.                 const int shifted128 = (128 << ITUR_BT_601_SHIFT);  
  1991.                 int u00 = ITUR_BT_601_CRU * r00 + ITUR_BT_601_CGU * g00 + ITUR_BT_601_CBU * b00 + halfShift + shifted128;  
  1992.                 int v00 = ITUR_BT_601_CBU * r00 + ITUR_BT_601_CGV * g00 + ITUR_BT_601_CBV * b00 + halfShift + shifted128;  
  1993.   
  1994.                 u[k] = saturate_cast<uchar>(u00 >> ITUR_BT_601_SHIFT);  
  1995.                 v[k] = saturate_cast<uchar>(v00 >> ITUR_BT_601_SHIFT);  
  1996.             }  
  1997.         }  
  1998.     }  
  1999.   
  2000. private:  
  2001.     RGB888toYUV420pInvoker& operator=(const RGB888toYUV420pInvoker&);  
  2002.   
  2003.     const Mat_<_Tp, chs1>& src_;  
  2004.     Mat_<_Tp, chs2>* const dst_;  
  2005.     const int uIdx_;  
  2006. };  
  2007.   
  2008. template<typename _Tp, int chs1, int chs2, int bIdx, int uIdx>  
  2009. static void cvtRGBtoYUV420p(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst)  
  2010. {  
  2011.     RGB888toYUV420pInvoker<_Tp, chs1, chs2, bIdx> colorConverter(src, &dst, uIdx);  
  2012.     colorConverter(Range(0, src.rows / 2));  
  2013. }  
  2014.   
  2015. template<typename _Tp, int chs1, int chs2>  
  2016. static int CvtColorLoop_RGB2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx)  
  2017. {  
  2018.     Range range(0, src.rows);  
  2019.   
  2020.     const uchar* yS_ = src.ptr(range.start);  
  2021.     uchar* yD_ = (uchar*)dst.ptr(range.start);  
  2022.     int scn = src.channels, dcn = dst.channels;  
  2023.   
  2024.     for (int h = range.start; h < range.end; ++h, yS_ += src.step, yD_ += dst.step) {  
  2025.         int n = src.cols;  
  2026.         const _Tp* yS = (const _Tp*)yS_;  
  2027.         _Tp* yD = (_Tp*)yD_;  
  2028.   
  2029.         if (dcn == 3) {  
  2030.             n *= 3;  
  2031.             for (int i = 0; i < n; i += 3, yS += scn) {  
  2032.                 _Tp t0 = yS[bidx], t1 = yS[1], t2 = yS[bidx ^ 2];  
  2033.                 yD[i] = t0; yD[i + 1] = t1; yD[i + 2] = t2;  
  2034.             }  
  2035.         } else if (scn == 3) {  
  2036.             n *= 3;  
  2037.             _Tp alpha = ColorChannel<_Tp>::max(); // Note: _Tp = float: alpha = 1.0f  
  2038.             for (int i = 0; i < n; i += 3, yD += 4) {  
  2039.                 _Tp t0 = yS[i], t1 = yS[i + 1], t2 = yS[i + 2];  
  2040.                 yD[bidx] = t0; yD[1] = t1; yD[bidx ^ 2] = t2; yD[3] = alpha;  
  2041.             }  
  2042.         } else {  
  2043.             n *= 4;  
  2044.             for (int i = 0; i < n; i += 4) {  
  2045.                 _Tp t0 = yS[i], t1 = yS[i + 1], t2 = yS[i + 2], t3 = yS[i + 3];  
  2046.                 yD[i] = t2; yD[i + 1] = t1; yD[i + 2] = t0; yD[i + 3] = t3;  
  2047.             }  
  2048.         }  
  2049.     }  
  2050.   
  2051.     return 0;  
  2052. }  
  2053.   
  2054. template<typename _Tp, int chs1, int chs2>  
  2055. static int CvtColorLoop_RGB2Gray(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx)  
  2056. {  
  2057.     Range range(0, src.rows);  
  2058.     const uchar* yS = src.ptr(range.start);  
  2059.     uchar* yD = (uchar*)dst.ptr(range.start);  
  2060.     int scn = src.channels, dcn = dst.channels;  
  2061.   
  2062.     RGB2Gray<_Tp> rgb2gray(scn, bidx, 0);  
  2063.   
  2064.     for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2065.         rgb2gray((const _Tp*)yS, (_Tp*)yD, src.cols);  
  2066.     }  
  2067.   
  2068.     return 0;  
  2069. }  
  2070.   
  2071. template<typename _Tp, int chs1, int chs2>  
  2072. static int CvtColorLoop_Gray2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst)  
  2073. {  
  2074.     Range range(0, src.rows);  
  2075.     const uchar* yS = src.ptr(range.start);  
  2076.     uchar* yD = (uchar*)dst.ptr(range.start);  
  2077.     int scn = src.channels, dcn = dst.channels;  
  2078.   
  2079.     Gray2RGB<_Tp> gray2rgb(dcn);  
  2080.   
  2081.     for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2082.         gray2rgb((const _Tp*)yS, (_Tp*)yD, src.cols);  
  2083.     }  
  2084.   
  2085.     return 0;  
  2086. }  
  2087.   
  2088. template<typename _Tp, int chs1, int chs2>  
  2089. static int CvtColorLoop_RGB2YCrCb(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs_f, const int* coeffs_i)  
  2090. {  
  2091.     Range range(0, src.rows);  
  2092.     const uchar* yS = src.ptr(range.start);  
  2093.     uchar* yD = (uchar*)dst.ptr(range.start);  
  2094.     int scn = src.channels, dcn = dst.channels;  
  2095.   
  2096.     if (sizeof(_Tp) == 4) {  
  2097.         RGB2YCrCb_f<_Tp> rgb2ycrcb(scn, bidx, coeffs_f);  
  2098.   
  2099.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2100.             rgb2ycrcb((const _Tp*)yS, (_Tp*)yD, src.cols);  
  2101.         }  
  2102.     } else {  
  2103.         if (sizeof(_Tp) == 1) {  
  2104.             RGB2YCrCb_i<uchar> rgb2ycrcb(scn, bidx, coeffs_i);  
  2105.   
  2106.             for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2107.                 rgb2ycrcb((const uchar*)yS, (uchar*)yD, src.cols);  
  2108.             }  
  2109.         } else {  
  2110.             RGB2YCrCb_i<ushort> rgb2ycrcb(scn, bidx, coeffs_i);  
  2111.   
  2112.             for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2113.                 rgb2ycrcb((const ushort*)yS, (ushort*)yD, src.cols);  
  2114.             }  
  2115.         }  
  2116.   
  2117.     }  
  2118.   
  2119.     return 0;  
  2120. }  
  2121.   
  2122. template<typename _Tp, int chs1, int chs2>  
  2123. static int CvtColorLoop_YCrCb2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs_f, const int* coeffs_i)  
  2124. {  
  2125.     Range range(0, src.rows);  
  2126.     const uchar* yS = src.ptr(range.start);  
  2127.     uchar* yD = (uchar*)dst.ptr(range.start);  
  2128.     int scn = src.channels, dcn = dst.channels;  
  2129.   
  2130.     if (sizeof(_Tp) == 4) {  
  2131.         YCrCb2RGB_f<_Tp> ycrcb2rgb(dcn, bidx, coeffs_f);  
  2132.   
  2133.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2134.             ycrcb2rgb((const _Tp*)yS, (_Tp*)yD, src.cols);  
  2135.         }  
  2136.     } else {  
  2137.         if (sizeof(_Tp) == 1) {  
  2138.             YCrCb2RGB_i<uchar> ycrcb2rgb(dcn, bidx, coeffs_i);  
  2139.   
  2140.             for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2141.                 ycrcb2rgb((const uchar*)yS, (uchar*)yD, src.cols);  
  2142.             }  
  2143.         }  
  2144.         else {  
  2145.             YCrCb2RGB_i<ushort> ycrcb2rgb(dcn, bidx, coeffs_i);  
  2146.   
  2147.             for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2148.                 ycrcb2rgb((const ushort*)yS, (ushort*)yD, src.cols);  
  2149.             }  
  2150.         }  
  2151.   
  2152.     }  
  2153.   
  2154.     return 0;  
  2155. }  
  2156.   
  2157. template<typename _Tp, int chs1, int chs2>  
  2158. static int CvtColorLoop_RGB2XYZ(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx)  
  2159. {  
  2160.     Range range(0, src.rows);  
  2161.     const uchar* yS = src.ptr(range.start);  
  2162.     uchar* yD = (uchar*)dst.ptr(range.start);  
  2163.     int scn = src.channels, dcn = dst.channels;  
  2164.   
  2165.     if (sizeof(_Tp) == 4) {  
  2166.         RGB2XYZ_f<_Tp> rgb2xyz(scn, bidx, 0);  
  2167.   
  2168.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2169.             rgb2xyz((const _Tp*)yS, (_Tp*)yD, src.cols);  
  2170.         }  
  2171.     } else {  
  2172.         if (sizeof(_Tp) == 1) {  
  2173.             RGB2XYZ_i<uchar> rgb2xyz(scn, bidx, 0);  
  2174.   
  2175.             for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2176.                 rgb2xyz((const uchar*)yS, (uchar*)yD, src.cols);  
  2177.             }  
  2178.         } else {  
  2179.             RGB2XYZ_i<ushort> rgb2xyz(scn, bidx, 0);  
  2180.   
  2181.             for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2182.                 rgb2xyz((const ushort*)yS, (ushort*)yD, src.cols);  
  2183.             }  
  2184.         }  
  2185.     }  
  2186.   
  2187.     return 0;  
  2188. }  
  2189.   
  2190. template<typename _Tp, int chs1, int chs2>  
  2191. static int CvtColorLoop_XYZ2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx)  
  2192. {  
  2193.     Range range(0, src.rows);  
  2194.     const uchar* yS = src.ptr(range.start);  
  2195.     uchar* yD = (uchar*)dst.ptr(range.start);  
  2196.     int scn = src.channels, dcn = dst.channels;  
  2197.   
  2198.     if (sizeof(_Tp) == 4) {  
  2199.         XYZ2RGB_f<_Tp> xyz2rgb(dcn, bidx, 0);  
  2200.   
  2201.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2202.             xyz2rgb((const _Tp*)yS, (_Tp*)yD, src.cols);  
  2203.         }  
  2204.     } else {  
  2205.         if (sizeof(_Tp) == 1) {  
  2206.             XYZ2RGB_i<uchar> xyz2rgb(dcn, bidx, 0);  
  2207.   
  2208.             for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2209.                 xyz2rgb((const uchar*)yS, (uchar*)yD, src.cols);  
  2210.             }  
  2211.         } else {  
  2212.             XYZ2RGB_i<ushort> xyz2rgb(dcn, bidx, 0);  
  2213.   
  2214.             for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2215.                 xyz2rgb((const ushort*)yS, (ushort*)yD, src.cols);  
  2216.             }  
  2217.         }  
  2218.     }  
  2219.   
  2220.     return 0;  
  2221. }  
  2222.   
  2223. template<typename _Tp, int chs1, int chs2>  
  2224. static int CvtColorLoop_RGB2HSV(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, int hrange)  
  2225. {  
  2226.     Range range(0, src.rows);  
  2227.     const uchar* yS = src.ptr(range.start);  
  2228.     uchar* yD = (uchar*)dst.ptr(range.start);  
  2229.     int scn = src.channels, dcn = dst.channels;  
  2230.   
  2231.     if (sizeof(_Tp) == 1) {  
  2232.         RGB2HSV_b rgb2hsv(scn, bidx, hrange);  
  2233.   
  2234.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2235.             rgb2hsv((const uchar*)yS, (uchar*)yD, src.cols);  
  2236.         }  
  2237.     } else {  
  2238.         RGB2HSV_f rgb2hsv(scn, bidx, (float)hrange);  
  2239.   
  2240.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2241.             rgb2hsv((const float*)yS, (float*)yD, src.cols);  
  2242.         }  
  2243.     }  
  2244.   
  2245.     return 0;  
  2246. }  
  2247.   
  2248. template<typename _Tp, int chs1, int chs2>  
  2249. static int CvtColorLoop_RGB2HLS(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, int hrange)  
  2250. {  
  2251.     Range range(0, src.rows);  
  2252.     const uchar* yS = src.ptr(range.start);  
  2253.     uchar* yD = (uchar*)dst.ptr(range.start);  
  2254.     int scn = src.channels, dcn = dst.channels;  
  2255.   
  2256.     if (sizeof(_Tp) == 1) {  
  2257.         RGB2HLS_b rgb2hls(scn, bidx, hrange);  
  2258.   
  2259.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2260.             rgb2hls((const uchar*)yS, (uchar*)yD, src.cols);  
  2261.         }  
  2262.     } else {  
  2263.         RGB2HLS_f rgb2hls(scn, bidx, (float)hrange);  
  2264.   
  2265.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2266.             rgb2hls((const float*)yS, (float*)yD, src.cols);  
  2267.         }  
  2268.     }  
  2269.   
  2270.     return 0;  
  2271. }  
  2272.   
  2273. template<typename _Tp, int chs1, int chs2>  
  2274. static int CvtColorLoop_HSV2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, int hrange)  
  2275. {  
  2276.     Range range(0, src.rows);  
  2277.     const uchar* yS = src.ptr(range.start);  
  2278.     uchar* yD = (uchar*)dst.ptr(range.start);  
  2279.     int scn = src.channels, dcn = dst.channels;  
  2280.   
  2281.     if (sizeof(_Tp) == 1) {  
  2282.         HSV2RGB_b hsv2rgb(dcn, bidx, hrange);  
  2283.   
  2284.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2285.             hsv2rgb((const uchar*)yS, (uchar*)yD, src.cols);  
  2286.         }  
  2287.     } else {  
  2288.         HSV2RGB_f hsv2rgb(dcn, bidx, (float)hrange);  
  2289.   
  2290.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2291.             hsv2rgb((const float*)yS, (float*)yD, src.cols);  
  2292.         }  
  2293.     }  
  2294.   
  2295.     return 0;  
  2296. }  
  2297.   
  2298. template<typename _Tp, int chs1, int chs2>  
  2299. static int CvtColorLoop_HLS2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, int hrange)  
  2300. {  
  2301.     Range range(0, src.rows);  
  2302.     const uchar* yS = src.ptr(range.start);  
  2303.     uchar* yD = (uchar*)dst.ptr(range.start);  
  2304.     int scn = src.channels, dcn = dst.channels;  
  2305.   
  2306.     if (sizeof(_Tp) == 1) {  
  2307.         HLS2RGB_b hls2rgb(dcn, bidx, hrange);  
  2308.   
  2309.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2310.             hls2rgb((const uchar*)yS, (uchar*)yD, src.cols);  
  2311.         }  
  2312.     } else {  
  2313.         HLS2RGB_f hls2rgb(dcn, bidx, (float)hrange);  
  2314.   
  2315.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2316.             hls2rgb((const float*)yS, (float*)yD, src.cols);  
  2317.         }  
  2318.     }  
  2319.   
  2320.     return 0;  
  2321. }  
  2322.   
  2323. template<typename _Tp, int chs1, int chs2>  
  2324. static int CvtColorLoop_RGB2Lab(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs, const float* whitept, bool srgb)  
  2325. {  
  2326.     Range range(0, src.rows);  
  2327.     const uchar* yS = src.ptr(range.start);  
  2328.     uchar* yD = (uchar*)dst.ptr(range.start);  
  2329.     int scn = src.channels, dcn = dst.channels;  
  2330.   
  2331.     if (sizeof(_Tp) == 1) {  
  2332.         RGB2Lab_b rgb2lab(scn, bidx, coeffs, whitept, srgb);  
  2333.   
  2334.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2335.             rgb2lab((const uchar*)yS, (uchar*)yD, src.cols);  
  2336.         }  
  2337.     }  
  2338.     else {  
  2339.         RGB2Lab_f rgb2lab(scn, bidx, coeffs, whitept, srgb);  
  2340.   
  2341.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2342.             rgb2lab((const float*)yS, (float*)yD, src.cols);  
  2343.         }  
  2344.     }  
  2345.   
  2346.     return 0;  
  2347. }  
  2348.   
  2349. template<typename _Tp, int chs1, int chs2>  
  2350. static int CvtColorLoop_RGB2Luv(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs, const float* whitept, bool srgb)  
  2351. {  
  2352.     Range range(0, src.rows);  
  2353.     const uchar* yS = src.ptr(range.start);  
  2354.     uchar* yD = (uchar*)dst.ptr(range.start);  
  2355.     int scn = src.channels, dcn = dst.channels;  
  2356.   
  2357.     if (sizeof(_Tp) == 1) {  
  2358.         RGB2Luv_b rgb2luv(scn, bidx, coeffs, whitept, srgb);  
  2359.   
  2360.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2361.             rgb2luv((const uchar*)yS, (uchar*)yD, src.cols);  
  2362.         }  
  2363.     }  
  2364.     else {  
  2365.         RGB2Luv_f rgb2luv(scn, bidx, coeffs, whitept, srgb);  
  2366.   
  2367.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2368.             rgb2luv((const float*)yS, (float*)yD, src.cols);  
  2369.         }  
  2370.     }  
  2371.   
  2372.     return 0;  
  2373. }  
  2374.   
  2375. template<typename _Tp, int chs1, int chs2>  
  2376. static int CvtColorLoop_Lab2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs, const float* whitept, bool srgb)  
  2377. {  
  2378.     Range range(0, src.rows);  
  2379.     const uchar* yS = src.ptr(range.start);  
  2380.     uchar* yD = (uchar*)dst.ptr(range.start);  
  2381.     int scn = src.channels, dcn = dst.channels;  
  2382.   
  2383.     if (sizeof(_Tp) == 1) {  
  2384.         Lab2RGB_b lab2rgb(dcn, bidx, coeffs, whitept, srgb);  
  2385.   
  2386.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2387.             lab2rgb((const uchar*)yS, (uchar*)yD, src.cols);  
  2388.         }  
  2389.     }  
  2390.     else {  
  2391.         Lab2RGB_f lab2rgb(dcn, bidx, coeffs, whitept, srgb);  
  2392.   
  2393.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2394.             lab2rgb((const float*)yS, (float*)yD, src.cols);  
  2395.         }  
  2396.     }  
  2397.   
  2398.     return 0;  
  2399. }  
  2400.   
  2401. template<typename _Tp, int chs1, int chs2>  
  2402. static int CvtColorLoop_Luv2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs, const float* whitept, bool srgb)  
  2403. {  
  2404.     Range range(0, src.rows);  
  2405.     const uchar* yS = src.ptr(range.start);  
  2406.     uchar* yD = (uchar*)dst.ptr(range.start);  
  2407.     int scn = src.channels, dcn = dst.channels;  
  2408.   
  2409.     if (sizeof(_Tp) == 1) {  
  2410.         Luv2RGB_b luv2rgb(dcn, bidx, coeffs, whitept, srgb);  
  2411.   
  2412.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2413.             luv2rgb((const uchar*)yS, (uchar*)yD, src.cols);  
  2414.         }  
  2415.     }  
  2416.     else {  
  2417.         Luv2RGB_f luv2rgb(dcn, bidx, coeffs, whitept, srgb);  
  2418.   
  2419.         for (int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step) {  
  2420.             luv2rgb((const float*)yS, (float*)yD, src.cols);  
  2421.         }  
  2422.     }  
  2423.   
  2424.     return 0;  
  2425. }  
  2426.   
  2427.   
  2428. // 命名空间fbc
  2429. #endif // FBC_CV_CVTCOLOR_HPP_  
 

除特别注明外,本站所有文章均为 人工智能学习网 原创,转载请注明出处来自OpenCV代码提取:cvtColor函数的实现

留言与评论(共有 0 条评论)
   
验证码:
[lianlun]1[/lianlun]