Merge pull request #3104 from dkanafeev:new_ipp_func_master
[profile/ivi/opencv.git] / modules / imgproc / src / color.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                           License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009-2010, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
16 //
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
19 //
20 //   * Redistribution's of source code must retain the above copyright notice,
21 //     this list of conditions and the following disclaimer.
22 //
23 //   * Redistribution's in binary form must reproduce the above copyright notice,
24 //     this list of conditions and the following disclaimer in the documentation
25 //     and/or other materials provided with the distribution.
26 //
27 //   * The name of the copyright holders may not be used to endorse or promote products
28 //     derived from this software without specific prior written permission.
29 //
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
40 //
41 //M*/
42
43 /********************************* COPYRIGHT NOTICE *******************************\
44   The function for RGB to Lab conversion is based on the MATLAB script
45   RGB2Lab.m translated by Mark Ruzon from C code by Yossi Rubner, 23 September 1997.
46   See the page [http://vision.stanford.edu/~ruzon/software/rgblab.html]
47 \**********************************************************************************/
48
49 /********************************* COPYRIGHT NOTICE *******************************\
50   Original code for Bayer->BGR/RGB conversion is provided by Dirk Schaefer
51   from MD-Mathematische Dienste GmbH. Below is the copyright notice:
52
53     IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
54     By downloading, copying, installing or using the software you agree
55     to this license. If you do not agree to this license, do not download,
56     install, copy or use the software.
57
58     Contributors License Agreement:
59
60       Copyright (c) 2002,
61       MD-Mathematische Dienste GmbH
62       Im Defdahl 5-10
63       44141 Dortmund
64       Germany
65       www.md-it.de
66
67     Redistribution and use in source and binary forms,
68     with or without modification, are permitted provided
69     that the following conditions are met:
70
71     Redistributions of source code must retain
72     the above copyright notice, this list of conditions and the following disclaimer.
73     Redistributions in binary form must reproduce the above copyright notice,
74     this list of conditions and the following disclaimer in the documentation
75     and/or other materials provided with the distribution.
76     The name of Contributor may not be used to endorse or promote products
77     derived from this software without specific prior written permission.
78
79     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
80     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
81     THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
82     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
83     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
84     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
85     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
86     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
87     STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
88     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
89     THE POSSIBILITY OF SUCH DAMAGE.
90 \**********************************************************************************/
91
92 #include "precomp.hpp"
93 #include "opencl_kernels_imgproc.hpp"
94 #include <limits>
95
96 #define  CV_DESCALE(x,n)     (((x) + (1 << ((n)-1))) >> (n))
97
98 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
99 #define MAX_IPP8u   255
100 #define MAX_IPP16u  65535
101 #define MAX_IPP32f  1.0
102 static IppStatus sts = ippInit();
103 #endif
104
105 namespace cv
106 {
107
108 // computes cubic spline coefficients for a function: (xi=i, yi=f[i]), i=0..n
109 template<typename _Tp> static void splineBuild(const _Tp* f, int n, _Tp* tab)
110 {
111     _Tp cn = 0;
112     int i;
113     tab[0] = tab[1] = (_Tp)0;
114
115     for(i = 1; i < n-1; i++)
116     {
117         _Tp t = 3*(f[i+1] - 2*f[i] + f[i-1]);
118         _Tp l = 1/(4 - tab[(i-1)*4]);
119         tab[i*4] = l; tab[i*4+1] = (t - tab[(i-1)*4+1])*l;
120     }
121
122     for(i = n-1; i >= 0; i--)
123     {
124         _Tp c = tab[i*4+1] - tab[i*4]*cn;
125         _Tp b = f[i+1] - f[i] - (cn + c*2)*(_Tp)0.3333333333333333;
126         _Tp d = (cn - c)*(_Tp)0.3333333333333333;
127         tab[i*4] = f[i]; tab[i*4+1] = b;
128         tab[i*4+2] = c; tab[i*4+3] = d;
129         cn = c;
130     }
131 }
132
133 // interpolates value of a function at x, 0 <= x <= n using a cubic spline.
134 template<typename _Tp> static inline _Tp splineInterpolate(_Tp x, const _Tp* tab, int n)
135 {
136     // don't touch this function without urgent need - some versions of gcc fail to inline it correctly
137     int ix = std::min(std::max(int(x), 0), n-1);
138     x -= ix;
139     tab += ix*4;
140     return ((tab[3]*x + tab[2])*x + tab[1])*x + tab[0];
141 }
142
143
144 template<typename _Tp> struct ColorChannel
145 {
146     typedef float worktype_f;
147     static _Tp max() { return std::numeric_limits<_Tp>::max(); }
148     static _Tp half() { return (_Tp)(max()/2 + 1); }
149 };
150
151 template<> struct ColorChannel<float>
152 {
153     typedef float worktype_f;
154     static float max() { return 1.f; }
155     static float half() { return 0.5f; }
156 };
157
158 /*template<> struct ColorChannel<double>
159 {
160     typedef double worktype_f;
161     static double max() { return 1.; }
162     static double half() { return 0.5; }
163 };*/
164
165
166 ///////////////////////////// Top-level template function ////////////////////////////////
167
168 template <typename Cvt>
169 class CvtColorLoop_Invoker : public ParallelLoopBody
170 {
171     typedef typename Cvt::channel_type _Tp;
172 public:
173
174     CvtColorLoop_Invoker(const Mat& _src, Mat& _dst, const Cvt& _cvt) :
175         ParallelLoopBody(), src(_src), dst(_dst), cvt(_cvt)
176     {
177     }
178
179     virtual void operator()(const Range& range) const
180     {
181         const uchar* yS = src.ptr<uchar>(range.start);
182         uchar* yD = dst.ptr<uchar>(range.start);
183
184         for( int i = range.start; i < range.end; ++i, yS += src.step, yD += dst.step )
185             cvt((const _Tp*)yS, (_Tp*)yD, src.cols);
186     }
187
188 private:
189     const Mat& src;
190     Mat& dst;
191     const Cvt& cvt;
192
193     const CvtColorLoop_Invoker& operator= (const CvtColorLoop_Invoker&);
194 };
195
196 template <typename Cvt>
197 void CvtColorLoop(const Mat& src, Mat& dst, const Cvt& cvt)
198 {
199     parallel_for_(Range(0, src.rows), CvtColorLoop_Invoker<Cvt>(src, dst, cvt), src.total()/(double)(1<<16) );
200 }
201
202 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
203
204 typedef IppStatus (CV_STDCALL* ippiReorderFunc)(const void *, int, void *, int, IppiSize, const int *);
205 typedef IppStatus (CV_STDCALL* ippiGeneralFunc)(const void *, int, void *, int, IppiSize);
206 typedef IppStatus (CV_STDCALL* ippiColor2GrayFunc)(const void *, int, void *, int, IppiSize, const Ipp32f *);
207
208 template <typename Cvt>
209 class CvtColorIPPLoop_Invoker :
210         public ParallelLoopBody
211 {
212 public:
213
214     CvtColorIPPLoop_Invoker(const Mat& _src, Mat& _dst, const Cvt& _cvt, bool *_ok) :
215         ParallelLoopBody(), src(_src), dst(_dst), cvt(_cvt), ok(_ok)
216     {
217         *ok = true;
218     }
219
220     virtual void operator()(const Range& range) const
221     {
222         const void *yS = src.ptr<uchar>(range.start);
223         void *yD = dst.ptr<uchar>(range.start);
224         if( !cvt(yS, (int)src.step[0], yD, (int)dst.step[0], src.cols, range.end - range.start) )
225             *ok = false;
226     }
227
228 private:
229     const Mat& src;
230     Mat& dst;
231     const Cvt& cvt;
232     bool *ok;
233
234     const CvtColorIPPLoop_Invoker& operator= (const CvtColorIPPLoop_Invoker&);
235 };
236
237 template <typename Cvt>
238 bool CvtColorIPPLoop(const Mat& src, Mat& dst, const Cvt& cvt)
239 {
240     bool ok;
241     parallel_for_(Range(0, src.rows), CvtColorIPPLoop_Invoker<Cvt>(src, dst, cvt, &ok), src.total()/(double)(1<<16) );
242     return ok;
243 }
244
245 template <typename Cvt>
246 bool CvtColorIPPLoopCopy(Mat& src, Mat& dst, const Cvt& cvt)
247 {
248     Mat temp;
249     Mat &source = src;
250     if( src.data == dst.data )
251     {
252         src.copyTo(temp);
253         source = temp;
254     }
255     bool ok;
256     parallel_for_(Range(0, source.rows), CvtColorIPPLoop_Invoker<Cvt>(source, dst, cvt, &ok),
257                   source.total()/(double)(1<<16) );
258     return ok;
259 }
260
261 static IppStatus CV_STDCALL ippiSwapChannels_8u_C3C4Rf(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep,
262          IppiSize roiSize, const int *dstOrder)
263 {
264     return ippiSwapChannels_8u_C3C4R(pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP8u);
265 }
266
267 static IppStatus CV_STDCALL ippiSwapChannels_16u_C3C4Rf(const Ipp16u* pSrc, int srcStep, Ipp16u* pDst, int dstStep,
268          IppiSize roiSize, const int *dstOrder)
269 {
270     return ippiSwapChannels_16u_C3C4R(pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP16u);
271 }
272
273 static IppStatus CV_STDCALL ippiSwapChannels_32f_C3C4Rf(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep,
274          IppiSize roiSize, const int *dstOrder)
275 {
276     return ippiSwapChannels_32f_C3C4R(pSrc, srcStep, pDst, dstStep, roiSize, dstOrder, MAX_IPP32f);
277 }
278
279 static ippiReorderFunc ippiSwapChannelsC3C4RTab[] =
280 {
281     (ippiReorderFunc)ippiSwapChannels_8u_C3C4Rf, 0, (ippiReorderFunc)ippiSwapChannels_16u_C3C4Rf, 0,
282     0, (ippiReorderFunc)ippiSwapChannels_32f_C3C4Rf, 0, 0
283 };
284
285 static ippiGeneralFunc ippiCopyAC4C3RTab[] =
286 {
287     (ippiGeneralFunc)ippiCopy_8u_AC4C3R, 0, (ippiGeneralFunc)ippiCopy_16u_AC4C3R, 0,
288     0, (ippiGeneralFunc)ippiCopy_32f_AC4C3R, 0, 0
289 };
290
291 static ippiReorderFunc ippiSwapChannelsC4C3RTab[] =
292 {
293     (ippiReorderFunc)ippiSwapChannels_8u_C4C3R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C4C3R, 0,
294     0, (ippiReorderFunc)ippiSwapChannels_32f_C4C3R, 0, 0
295 };
296
297 static ippiReorderFunc ippiSwapChannelsC3RTab[] =
298 {
299     (ippiReorderFunc)ippiSwapChannels_8u_C3R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C3R, 0,
300     0, (ippiReorderFunc)ippiSwapChannels_32f_C3R, 0, 0
301 };
302
303 #if IPP_VERSION_X100 >= 801
304 static ippiReorderFunc ippiSwapChannelsC4RTab[] =
305 {
306     (ippiReorderFunc)ippiSwapChannels_8u_C4R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C4R, 0,
307     0, (ippiReorderFunc)ippiSwapChannels_32f_C4R, 0, 0
308 };
309 #endif
310
311 static ippiColor2GrayFunc ippiColor2GrayC3Tab[] =
312 {
313     (ippiColor2GrayFunc)ippiColorToGray_8u_C3C1R, 0, (ippiColor2GrayFunc)ippiColorToGray_16u_C3C1R, 0,
314     0, (ippiColor2GrayFunc)ippiColorToGray_32f_C3C1R, 0, 0
315 };
316
317 static ippiColor2GrayFunc ippiColor2GrayC4Tab[] =
318 {
319     (ippiColor2GrayFunc)ippiColorToGray_8u_AC4C1R, 0, (ippiColor2GrayFunc)ippiColorToGray_16u_AC4C1R, 0,
320     0, (ippiColor2GrayFunc)ippiColorToGray_32f_AC4C1R, 0, 0
321 };
322
323 static ippiGeneralFunc ippiRGB2GrayC3Tab[] =
324 {
325     (ippiGeneralFunc)ippiRGBToGray_8u_C3C1R, 0, (ippiGeneralFunc)ippiRGBToGray_16u_C3C1R, 0,
326     0, (ippiGeneralFunc)ippiRGBToGray_32f_C3C1R, 0, 0
327 };
328
329 static ippiGeneralFunc ippiRGB2GrayC4Tab[] =
330 {
331     (ippiGeneralFunc)ippiRGBToGray_8u_AC4C1R, 0, (ippiGeneralFunc)ippiRGBToGray_16u_AC4C1R, 0,
332     0, (ippiGeneralFunc)ippiRGBToGray_32f_AC4C1R, 0, 0
333 };
334
335 static ippiGeneralFunc ippiCopyP3C3RTab[] =
336 {
337     (ippiGeneralFunc)ippiCopy_8u_P3C3R, 0, (ippiGeneralFunc)ippiCopy_16u_P3C3R, 0,
338     0, (ippiGeneralFunc)ippiCopy_32f_P3C3R, 0, 0
339 };
340
341 static ippiGeneralFunc ippiRGB2XYZTab[] =
342 {
343     (ippiGeneralFunc)ippiRGBToXYZ_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToXYZ_16u_C3R, 0,
344     0, (ippiGeneralFunc)ippiRGBToXYZ_32f_C3R, 0, 0
345 };
346
347 static ippiGeneralFunc ippiXYZ2RGBTab[] =
348 {
349     (ippiGeneralFunc)ippiXYZToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiXYZToRGB_16u_C3R, 0,
350     0, (ippiGeneralFunc)ippiXYZToRGB_32f_C3R, 0, 0
351 };
352
353 static ippiGeneralFunc ippiRGB2HSVTab[] =
354 {
355     (ippiGeneralFunc)ippiRGBToHSV_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToHSV_16u_C3R, 0,
356     0, 0, 0, 0
357 };
358
359 static ippiGeneralFunc ippiHSV2RGBTab[] =
360 {
361     (ippiGeneralFunc)ippiHSVToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiHSVToRGB_16u_C3R, 0,
362     0, 0, 0, 0
363 };
364
365 static ippiGeneralFunc ippiRGB2HLSTab[] =
366 {
367     (ippiGeneralFunc)ippiRGBToHLS_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToHLS_16u_C3R, 0,
368     0, (ippiGeneralFunc)ippiRGBToHLS_32f_C3R, 0, 0
369 };
370
371 static ippiGeneralFunc ippiHLS2RGBTab[] =
372 {
373     (ippiGeneralFunc)ippiHLSToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiHLSToRGB_16u_C3R, 0,
374     0, (ippiGeneralFunc)ippiHLSToRGB_32f_C3R, 0, 0
375 };
376
377 #if !defined(HAVE_IPP_ICV_ONLY) && 0
378 static ippiGeneralFunc ippiRGBToLUVTab[] =
379 {
380     (ippiGeneralFunc)ippiRGBToLUV_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToLUV_16u_C3R, 0,
381     0, (ippiGeneralFunc)ippiRGBToLUV_32f_C3R, 0, 0
382 };
383
384 static ippiGeneralFunc ippiLUVToRGBTab[] =
385 {
386     (ippiGeneralFunc)ippiLUVToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiLUVToRGB_16u_C3R, 0,
387     0, (ippiGeneralFunc)ippiLUVToRGB_32f_C3R, 0, 0
388 };
389 #endif
390
391 struct IPPGeneralFunctor
392 {
393     IPPGeneralFunctor(ippiGeneralFunc _func) : func(_func){}
394     bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
395     {
396         return func ? func(src, srcStep, dst, dstStep, ippiSize(cols, rows)) >= 0 : false;
397     }
398 private:
399     ippiGeneralFunc func;
400 };
401
402 struct IPPReorderFunctor
403 {
404     IPPReorderFunctor(ippiReorderFunc _func, int _order0, int _order1, int _order2) : func(_func)
405     {
406         order[0] = _order0;
407         order[1] = _order1;
408         order[2] = _order2;
409         order[3] = 3;
410     }
411     bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
412     {
413         return func ? func(src, srcStep, dst, dstStep, ippiSize(cols, rows), order) >= 0 : false;
414     }
415 private:
416     ippiReorderFunc func;
417     int order[4];
418 };
419
420 struct IPPColor2GrayFunctor
421 {
422     IPPColor2GrayFunctor(ippiColor2GrayFunc _func) :
423         func(_func)
424     {
425         coeffs[0] = 0.114f;
426         coeffs[1] = 0.587f;
427         coeffs[2] = 0.299f;
428     }
429     bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
430     {
431         return func ? func(src, srcStep, dst, dstStep, ippiSize(cols, rows), coeffs) >= 0 : false;
432     }
433 private:
434     ippiColor2GrayFunc func;
435     Ipp32f coeffs[3];
436 };
437
438 struct IPPGray2BGRFunctor
439 {
440     IPPGray2BGRFunctor(ippiGeneralFunc _func) :
441         func(_func)
442     {
443     }
444
445     bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
446     {
447         if (func == 0)
448             return false;
449
450         const void* srcarray[3] = { src, src, src };
451         return func(srcarray, srcStep, dst, dstStep, ippiSize(cols, rows)) >= 0;
452     }
453 private:
454     ippiGeneralFunc func;
455 };
456
457 struct IPPGray2BGRAFunctor
458 {
459     IPPGray2BGRAFunctor(ippiGeneralFunc _func1, ippiReorderFunc _func2, int _depth) :
460         func1(_func1), func2(_func2), depth(_depth)
461     {
462     }
463
464     bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
465     {
466         if (func1 == 0 || func2 == 0)
467             return false;
468
469         const void* srcarray[3] = { src, src, src };
470         Mat temp(rows, cols, CV_MAKETYPE(depth, 3));
471         if(func1(srcarray, srcStep, temp.ptr(), (int)temp.step[0], ippiSize(cols, rows)) < 0)
472             return false;
473         int order[4] = {0, 1, 2, 3};
474         return func2(temp.ptr(), (int)temp.step[0], dst, dstStep, ippiSize(cols, rows), order) >= 0;
475     }
476 private:
477     ippiGeneralFunc func1;
478     ippiReorderFunc func2;
479     int depth;
480 };
481
482 struct IPPReorderGeneralFunctor
483 {
484     IPPReorderGeneralFunctor(ippiReorderFunc _func1, ippiGeneralFunc _func2, int _order0, int _order1, int _order2, int _depth) :
485         func1(_func1), func2(_func2), depth(_depth)
486     {
487         order[0] = _order0;
488         order[1] = _order1;
489         order[2] = _order2;
490         order[3] = 3;
491     }
492     bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
493     {
494         if (func1 == 0 || func2 == 0)
495             return false;
496
497         Mat temp;
498         temp.create(rows, cols, CV_MAKETYPE(depth, 3));
499         if(func1(src, srcStep, temp.ptr(), (int)temp.step[0], ippiSize(cols, rows), order) < 0)
500             return false;
501         return func2(temp.ptr(), (int)temp.step[0], dst, dstStep, ippiSize(cols, rows)) >= 0;
502     }
503 private:
504     ippiReorderFunc func1;
505     ippiGeneralFunc func2;
506     int order[4];
507     int depth;
508 };
509
510 struct IPPGeneralReorderFunctor
511 {
512     IPPGeneralReorderFunctor(ippiGeneralFunc _func1, ippiReorderFunc _func2, int _order0, int _order1, int _order2, int _depth) :
513         func1(_func1), func2(_func2), depth(_depth)
514     {
515         order[0] = _order0;
516         order[1] = _order1;
517         order[2] = _order2;
518         order[3] = 3;
519     }
520     bool operator()(const void *src, int srcStep, void *dst, int dstStep, int cols, int rows) const
521     {
522         if (func1 == 0 || func2 == 0)
523             return false;
524
525         Mat temp;
526         temp.create(rows, cols, CV_MAKETYPE(depth, 3));
527         if(func1(src, srcStep, temp.ptr(), (int)temp.step[0], ippiSize(cols, rows)) < 0)
528             return false;
529         return func2(temp.ptr(), (int)temp.step[0], dst, dstStep, ippiSize(cols, rows), order) >= 0;
530     }
531 private:
532     ippiGeneralFunc func1;
533     ippiReorderFunc func2;
534     int order[4];
535     int depth;
536 };
537
538 #endif
539
540 ////////////////// Various 3/4-channel to 3/4-channel RGB transformations /////////////////
541
542 template<typename _Tp> struct RGB2RGB
543 {
544     typedef _Tp channel_type;
545
546     RGB2RGB(int _srccn, int _dstcn, int _blueIdx) : srccn(_srccn), dstcn(_dstcn), blueIdx(_blueIdx) {}
547     void operator()(const _Tp* src, _Tp* dst, int n) const
548     {
549         int scn = srccn, dcn = dstcn, bidx = blueIdx;
550         if( dcn == 3 )
551         {
552             n *= 3;
553             for( int i = 0; i < n; i += 3, src += scn )
554             {
555                 _Tp t0 = src[bidx], t1 = src[1], t2 = src[bidx ^ 2];
556                 dst[i] = t0; dst[i+1] = t1; dst[i+2] = t2;
557             }
558         }
559         else if( scn == 3 )
560         {
561             n *= 3;
562             _Tp alpha = ColorChannel<_Tp>::max();
563             for( int i = 0; i < n; i += 3, dst += 4 )
564             {
565                 _Tp t0 = src[i], t1 = src[i+1], t2 = src[i+2];
566                 dst[bidx] = t0; dst[1] = t1; dst[bidx^2] = t2; dst[3] = alpha;
567             }
568         }
569         else
570         {
571             n *= 4;
572             for( int i = 0; i < n; i += 4 )
573             {
574                 _Tp t0 = src[i], t1 = src[i+1], t2 = src[i+2], t3 = src[i+3];
575                 dst[i] = t2; dst[i+1] = t1; dst[i+2] = t0; dst[i+3] = t3;
576             }
577         }
578     }
579
580     int srccn, dstcn, blueIdx;
581 };
582
583 /////////// Transforming 16-bit (565 or 555) RGB to/from 24/32-bit (888[8]) RGB //////////
584
585 struct RGB5x52RGB
586 {
587     typedef uchar channel_type;
588
589     RGB5x52RGB(int _dstcn, int _blueIdx, int _greenBits)
590         : dstcn(_dstcn), blueIdx(_blueIdx), greenBits(_greenBits) {}
591
592     void operator()(const uchar* src, uchar* dst, int n) const
593     {
594         int dcn = dstcn, bidx = blueIdx;
595         if( greenBits == 6 )
596             for( int i = 0; i < n; i++, dst += dcn )
597             {
598                 unsigned t = ((const ushort*)src)[i];
599                 dst[bidx] = (uchar)(t << 3);
600                 dst[1] = (uchar)((t >> 3) & ~3);
601                 dst[bidx ^ 2] = (uchar)((t >> 8) & ~7);
602                 if( dcn == 4 )
603                     dst[3] = 255;
604             }
605         else
606             for( int i = 0; i < n; i++, dst += dcn )
607             {
608                 unsigned t = ((const ushort*)src)[i];
609                 dst[bidx] = (uchar)(t << 3);
610                 dst[1] = (uchar)((t >> 2) & ~7);
611                 dst[bidx ^ 2] = (uchar)((t >> 7) & ~7);
612                 if( dcn == 4 )
613                     dst[3] = t & 0x8000 ? 255 : 0;
614             }
615     }
616
617     int dstcn, blueIdx, greenBits;
618 };
619
620
621 struct RGB2RGB5x5
622 {
623     typedef uchar channel_type;
624
625     RGB2RGB5x5(int _srccn, int _blueIdx, int _greenBits)
626         : srccn(_srccn), blueIdx(_blueIdx), greenBits(_greenBits) {}
627
628     void operator()(const uchar* src, uchar* dst, int n) const
629     {
630         int scn = srccn, bidx = blueIdx;
631         if( greenBits == 6 )
632             for( int i = 0; i < n; i++, src += scn )
633             {
634                 ((ushort*)dst)[i] = (ushort)((src[bidx] >> 3)|((src[1]&~3) << 3)|((src[bidx^2]&~7) << 8));
635             }
636         else if( scn == 3 )
637             for( int i = 0; i < n; i++, src += 3 )
638             {
639                 ((ushort*)dst)[i] = (ushort)((src[bidx] >> 3)|((src[1]&~7) << 2)|((src[bidx^2]&~7) << 7));
640             }
641         else
642             for( int i = 0; i < n; i++, src += 4 )
643             {
644                 ((ushort*)dst)[i] = (ushort)((src[bidx] >> 3)|((src[1]&~7) << 2)|
645                     ((src[bidx^2]&~7) << 7)|(src[3] ? 0x8000 : 0));
646             }
647     }
648
649     int srccn, blueIdx, greenBits;
650 };
651
652 ///////////////////////////////// Color to/from Grayscale ////////////////////////////////
653
654 template<typename _Tp>
655 struct Gray2RGB
656 {
657     typedef _Tp channel_type;
658
659     Gray2RGB(int _dstcn) : dstcn(_dstcn) {}
660     void operator()(const _Tp* src, _Tp* dst, int n) const
661     {
662         if( dstcn == 3 )
663             for( int i = 0; i < n; i++, dst += 3 )
664             {
665                 dst[0] = dst[1] = dst[2] = src[i];
666             }
667         else
668         {
669             _Tp alpha = ColorChannel<_Tp>::max();
670             for( int i = 0; i < n; i++, dst += 4 )
671             {
672                 dst[0] = dst[1] = dst[2] = src[i];
673                 dst[3] = alpha;
674             }
675         }
676     }
677
678     int dstcn;
679 };
680
681
682 struct Gray2RGB5x5
683 {
684     typedef uchar channel_type;
685
686     Gray2RGB5x5(int _greenBits) : greenBits(_greenBits) {}
687     void operator()(const uchar* src, uchar* dst, int n) const
688     {
689         if( greenBits == 6 )
690             for( int i = 0; i < n; i++ )
691             {
692                 int t = src[i];
693                 ((ushort*)dst)[i] = (ushort)((t >> 3)|((t & ~3) << 3)|((t & ~7) << 8));
694             }
695         else
696             for( int i = 0; i < n; i++ )
697             {
698                 int t = src[i] >> 3;
699                 ((ushort*)dst)[i] = (ushort)(t|(t << 5)|(t << 10));
700             }
701     }
702     int greenBits;
703 };
704
705
706 #undef R2Y
707 #undef G2Y
708 #undef B2Y
709
710 enum
711 {
712     yuv_shift = 14,
713     xyz_shift = 12,
714     R2Y = 4899,
715     G2Y = 9617,
716     B2Y = 1868,
717     BLOCK_SIZE = 256
718 };
719
720
721 struct RGB5x52Gray
722 {
723     typedef uchar channel_type;
724
725     RGB5x52Gray(int _greenBits) : greenBits(_greenBits) {}
726     void operator()(const uchar* src, uchar* dst, int n) const
727     {
728         if( greenBits == 6 )
729             for( int i = 0; i < n; i++ )
730             {
731                 int t = ((ushort*)src)[i];
732                 dst[i] = (uchar)CV_DESCALE(((t << 3) & 0xf8)*B2Y +
733                                            ((t >> 3) & 0xfc)*G2Y +
734                                            ((t >> 8) & 0xf8)*R2Y, yuv_shift);
735             }
736         else
737             for( int i = 0; i < n; i++ )
738             {
739                 int t = ((ushort*)src)[i];
740                 dst[i] = (uchar)CV_DESCALE(((t << 3) & 0xf8)*B2Y +
741                                            ((t >> 2) & 0xf8)*G2Y +
742                                            ((t >> 7) & 0xf8)*R2Y, yuv_shift);
743             }
744     }
745     int greenBits;
746 };
747
748
749 template<typename _Tp> struct RGB2Gray
750 {
751     typedef _Tp channel_type;
752
753     RGB2Gray(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)
754     {
755         static const float coeffs0[] = { 0.299f, 0.587f, 0.114f };
756         memcpy( coeffs, _coeffs ? _coeffs : coeffs0, 3*sizeof(coeffs[0]) );
757         if(blueIdx == 0)
758             std::swap(coeffs[0], coeffs[2]);
759     }
760
761     void operator()(const _Tp* src, _Tp* dst, int n) const
762     {
763         int scn = srccn;
764         float cb = coeffs[0], cg = coeffs[1], cr = coeffs[2];
765         for(int i = 0; i < n; i++, src += scn)
766             dst[i] = saturate_cast<_Tp>(src[0]*cb + src[1]*cg + src[2]*cr);
767     }
768     int srccn;
769     float coeffs[3];
770 };
771
772
773 template<> struct RGB2Gray<uchar>
774 {
775     typedef uchar channel_type;
776
777     RGB2Gray(int _srccn, int blueIdx, const int* coeffs) : srccn(_srccn)
778     {
779         const int coeffs0[] = { R2Y, G2Y, B2Y };
780         if(!coeffs) coeffs = coeffs0;
781
782         int b = 0, g = 0, r = (1 << (yuv_shift-1));
783         int db = coeffs[blueIdx^2], dg = coeffs[1], dr = coeffs[blueIdx];
784
785         for( int i = 0; i < 256; i++, b += db, g += dg, r += dr )
786         {
787             tab[i] = b;
788             tab[i+256] = g;
789             tab[i+512] = r;
790         }
791     }
792     void operator()(const uchar* src, uchar* dst, int n) const
793     {
794         int scn = srccn;
795         const int* _tab = tab;
796         for(int i = 0; i < n; i++, src += scn)
797             dst[i] = (uchar)((_tab[src[0]] + _tab[src[1]+256] + _tab[src[2]+512]) >> yuv_shift);
798     }
799     int srccn;
800     int tab[256*3];
801 };
802
803
804 template<> struct RGB2Gray<ushort>
805 {
806     typedef ushort channel_type;
807
808     RGB2Gray(int _srccn, int blueIdx, const int* _coeffs) : srccn(_srccn)
809     {
810         static const int coeffs0[] = { R2Y, G2Y, B2Y };
811         memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 3*sizeof(coeffs[0]));
812         if( blueIdx == 0 )
813             std::swap(coeffs[0], coeffs[2]);
814     }
815
816     void operator()(const ushort* src, ushort* dst, int n) const
817     {
818         int scn = srccn, cb = coeffs[0], cg = coeffs[1], cr = coeffs[2];
819         for(int i = 0; i < n; i++, src += scn)
820             dst[i] = (ushort)CV_DESCALE((unsigned)(src[0]*cb + src[1]*cg + src[2]*cr), yuv_shift);
821     }
822     int srccn;
823     int coeffs[3];
824 };
825
826
827 ///////////////////////////////////// RGB <-> YCrCb //////////////////////////////////////
828
829 template<typename _Tp> struct RGB2YCrCb_f
830 {
831     typedef _Tp channel_type;
832
833     RGB2YCrCb_f(int _srccn, int _blueIdx, const float* _coeffs) : srccn(_srccn), blueIdx(_blueIdx)
834     {
835         static const float coeffs0[] = {0.299f, 0.587f, 0.114f, 0.713f, 0.564f};
836         memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 5*sizeof(coeffs[0]));
837         if(blueIdx==0) std::swap(coeffs[0], coeffs[2]);
838     }
839
840     void operator()(const _Tp* src, _Tp* dst, int n) const
841     {
842         int scn = srccn, bidx = blueIdx;
843         const _Tp delta = ColorChannel<_Tp>::half();
844         float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3], C4 = coeffs[4];
845         n *= 3;
846         for(int i = 0; i < n; i += 3, src += scn)
847         {
848             _Tp Y = saturate_cast<_Tp>(src[0]*C0 + src[1]*C1 + src[2]*C2);
849             _Tp Cr = saturate_cast<_Tp>((src[bidx^2] - Y)*C3 + delta);
850             _Tp Cb = saturate_cast<_Tp>((src[bidx] - Y)*C4 + delta);
851             dst[i] = Y; dst[i+1] = Cr; dst[i+2] = Cb;
852         }
853     }
854     int srccn, blueIdx;
855     float coeffs[5];
856 };
857
858
859 template<typename _Tp> struct RGB2YCrCb_i
860 {
861     typedef _Tp channel_type;
862
863     RGB2YCrCb_i(int _srccn, int _blueIdx, const int* _coeffs)
864         : srccn(_srccn), blueIdx(_blueIdx)
865     {
866         static const int coeffs0[] = {R2Y, G2Y, B2Y, 11682, 9241};
867         memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 5*sizeof(coeffs[0]));
868         if(blueIdx==0) std::swap(coeffs[0], coeffs[2]);
869     }
870     void operator()(const _Tp* src, _Tp* dst, int n) const
871     {
872         int scn = srccn, bidx = blueIdx;
873         int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3], C4 = coeffs[4];
874         int delta = ColorChannel<_Tp>::half()*(1 << yuv_shift);
875         n *= 3;
876         for(int i = 0; i < n; i += 3, src += scn)
877         {
878             int Y = CV_DESCALE(src[0]*C0 + src[1]*C1 + src[2]*C2, yuv_shift);
879             int Cr = CV_DESCALE((src[bidx^2] - Y)*C3 + delta, yuv_shift);
880             int Cb = CV_DESCALE((src[bidx] - Y)*C4 + delta, yuv_shift);
881             dst[i] = saturate_cast<_Tp>(Y);
882             dst[i+1] = saturate_cast<_Tp>(Cr);
883             dst[i+2] = saturate_cast<_Tp>(Cb);
884         }
885     }
886     int srccn, blueIdx;
887     int coeffs[5];
888 };
889
890
891 template<typename _Tp> struct YCrCb2RGB_f
892 {
893     typedef _Tp channel_type;
894
895     YCrCb2RGB_f(int _dstcn, int _blueIdx, const float* _coeffs)
896         : dstcn(_dstcn), blueIdx(_blueIdx)
897     {
898         static const float coeffs0[] = {1.403f, -0.714f, -0.344f, 1.773f};
899         memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 4*sizeof(coeffs[0]));
900     }
901     void operator()(const _Tp* src, _Tp* dst, int n) const
902     {
903         int dcn = dstcn, bidx = blueIdx;
904         const _Tp delta = ColorChannel<_Tp>::half(), alpha = ColorChannel<_Tp>::max();
905         float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3];
906         n *= 3;
907         for(int i = 0; i < n; i += 3, dst += dcn)
908         {
909             _Tp Y = src[i];
910             _Tp Cr = src[i+1];
911             _Tp Cb = src[i+2];
912
913             _Tp b = saturate_cast<_Tp>(Y + (Cb - delta)*C3);
914             _Tp g = saturate_cast<_Tp>(Y + (Cb - delta)*C2 + (Cr - delta)*C1);
915             _Tp r = saturate_cast<_Tp>(Y + (Cr - delta)*C0);
916
917             dst[bidx] = b; dst[1] = g; dst[bidx^2] = r;
918             if( dcn == 4 )
919                 dst[3] = alpha;
920         }
921     }
922     int dstcn, blueIdx;
923     float coeffs[4];
924 };
925
926
927 template<typename _Tp> struct YCrCb2RGB_i
928 {
929     typedef _Tp channel_type;
930
931     YCrCb2RGB_i(int _dstcn, int _blueIdx, const int* _coeffs)
932         : dstcn(_dstcn), blueIdx(_blueIdx)
933     {
934         static const int coeffs0[] = {22987, -11698, -5636, 29049};
935         memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 4*sizeof(coeffs[0]));
936     }
937
938     void operator()(const _Tp* src, _Tp* dst, int n) const
939     {
940         int dcn = dstcn, bidx = blueIdx;
941         const _Tp delta = ColorChannel<_Tp>::half(), alpha = ColorChannel<_Tp>::max();
942         int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3];
943         n *= 3;
944         for(int i = 0; i < n; i += 3, dst += dcn)
945         {
946             _Tp Y = src[i];
947             _Tp Cr = src[i+1];
948             _Tp Cb = src[i+2];
949
950             int b = Y + CV_DESCALE((Cb - delta)*C3, yuv_shift);
951             int g = Y + CV_DESCALE((Cb - delta)*C2 + (Cr - delta)*C1, yuv_shift);
952             int r = Y + CV_DESCALE((Cr - delta)*C0, yuv_shift);
953
954             dst[bidx] = saturate_cast<_Tp>(b);
955             dst[1] = saturate_cast<_Tp>(g);
956             dst[bidx^2] = saturate_cast<_Tp>(r);
957             if( dcn == 4 )
958                 dst[3] = alpha;
959         }
960     }
961     int dstcn, blueIdx;
962     int coeffs[4];
963 };
964
965
966 ////////////////////////////////////// RGB <-> XYZ ///////////////////////////////////////
967
968 static const float sRGB2XYZ_D65[] =
969 {
970     0.412453f, 0.357580f, 0.180423f,
971     0.212671f, 0.715160f, 0.072169f,
972     0.019334f, 0.119193f, 0.950227f
973 };
974
975 static const float XYZ2sRGB_D65[] =
976 {
977     3.240479f, -1.53715f, -0.498535f,
978     -0.969256f, 1.875991f, 0.041556f,
979     0.055648f, -0.204043f, 1.057311f
980 };
981
982 template<typename _Tp> struct RGB2XYZ_f
983 {
984     typedef _Tp channel_type;
985
986     RGB2XYZ_f(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)
987     {
988         memcpy(coeffs, _coeffs ? _coeffs : sRGB2XYZ_D65, 9*sizeof(coeffs[0]));
989         if(blueIdx == 0)
990         {
991             std::swap(coeffs[0], coeffs[2]);
992             std::swap(coeffs[3], coeffs[5]);
993             std::swap(coeffs[6], coeffs[8]);
994         }
995     }
996     void operator()(const _Tp* src, _Tp* dst, int n) const
997     {
998         int scn = srccn;
999         float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1000               C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1001               C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1002
1003         n *= 3;
1004         for(int i = 0; i < n; i += 3, src += scn)
1005         {
1006             _Tp X = saturate_cast<_Tp>(src[0]*C0 + src[1]*C1 + src[2]*C2);
1007             _Tp Y = saturate_cast<_Tp>(src[0]*C3 + src[1]*C4 + src[2]*C5);
1008             _Tp Z = saturate_cast<_Tp>(src[0]*C6 + src[1]*C7 + src[2]*C8);
1009             dst[i] = X; dst[i+1] = Y; dst[i+2] = Z;
1010         }
1011     }
1012     int srccn;
1013     float coeffs[9];
1014 };
1015
1016
1017 template<typename _Tp> struct RGB2XYZ_i
1018 {
1019     typedef _Tp channel_type;
1020
1021     RGB2XYZ_i(int _srccn, int blueIdx, const float* _coeffs) : srccn(_srccn)
1022     {
1023         static const int coeffs0[] =
1024         {
1025             1689,    1465,    739,
1026             871,     2929,    296,
1027             79,      488,     3892
1028         };
1029         for( int i = 0; i < 9; i++ )
1030             coeffs[i] = _coeffs ? cvRound(_coeffs[i]*(1 << xyz_shift)) : coeffs0[i];
1031         if(blueIdx == 0)
1032         {
1033             std::swap(coeffs[0], coeffs[2]);
1034             std::swap(coeffs[3], coeffs[5]);
1035             std::swap(coeffs[6], coeffs[8]);
1036         }
1037     }
1038     void operator()(const _Tp* src, _Tp* dst, int n) const
1039     {
1040         int scn = srccn;
1041         int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1042             C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1043             C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1044         n *= 3;
1045         for(int i = 0; i < n; i += 3, src += scn)
1046         {
1047             int X = CV_DESCALE(src[0]*C0 + src[1]*C1 + src[2]*C2, xyz_shift);
1048             int Y = CV_DESCALE(src[0]*C3 + src[1]*C4 + src[2]*C5, xyz_shift);
1049             int Z = CV_DESCALE(src[0]*C6 + src[1]*C7 + src[2]*C8, xyz_shift);
1050             dst[i] = saturate_cast<_Tp>(X); dst[i+1] = saturate_cast<_Tp>(Y);
1051             dst[i+2] = saturate_cast<_Tp>(Z);
1052         }
1053     }
1054     int srccn;
1055     int coeffs[9];
1056 };
1057
1058
1059 template<typename _Tp> struct XYZ2RGB_f
1060 {
1061     typedef _Tp channel_type;
1062
1063     XYZ2RGB_f(int _dstcn, int _blueIdx, const float* _coeffs)
1064     : dstcn(_dstcn), blueIdx(_blueIdx)
1065     {
1066         memcpy(coeffs, _coeffs ? _coeffs : XYZ2sRGB_D65, 9*sizeof(coeffs[0]));
1067         if(blueIdx == 0)
1068         {
1069             std::swap(coeffs[0], coeffs[6]);
1070             std::swap(coeffs[1], coeffs[7]);
1071             std::swap(coeffs[2], coeffs[8]);
1072         }
1073     }
1074
1075     void operator()(const _Tp* src, _Tp* dst, int n) const
1076     {
1077         int dcn = dstcn;
1078         _Tp alpha = ColorChannel<_Tp>::max();
1079         float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1080               C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1081               C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1082         n *= 3;
1083         for(int i = 0; i < n; i += 3, dst += dcn)
1084         {
1085             _Tp B = saturate_cast<_Tp>(src[i]*C0 + src[i+1]*C1 + src[i+2]*C2);
1086             _Tp G = saturate_cast<_Tp>(src[i]*C3 + src[i+1]*C4 + src[i+2]*C5);
1087             _Tp R = saturate_cast<_Tp>(src[i]*C6 + src[i+1]*C7 + src[i+2]*C8);
1088             dst[0] = B; dst[1] = G; dst[2] = R;
1089             if( dcn == 4 )
1090                 dst[3] = alpha;
1091         }
1092     }
1093     int dstcn, blueIdx;
1094     float coeffs[9];
1095 };
1096
1097
1098 template<typename _Tp> struct XYZ2RGB_i
1099 {
1100     typedef _Tp channel_type;
1101
1102     XYZ2RGB_i(int _dstcn, int _blueIdx, const int* _coeffs)
1103     : dstcn(_dstcn), blueIdx(_blueIdx)
1104     {
1105         static const int coeffs0[] =
1106         {
1107             13273,  -6296,  -2042,
1108             -3970,   7684,    170,
1109               228,   -836,   4331
1110         };
1111         for(int i = 0; i < 9; i++)
1112             coeffs[i] = _coeffs ? cvRound(_coeffs[i]*(1 << xyz_shift)) : coeffs0[i];
1113
1114         if(blueIdx == 0)
1115         {
1116             std::swap(coeffs[0], coeffs[6]);
1117             std::swap(coeffs[1], coeffs[7]);
1118             std::swap(coeffs[2], coeffs[8]);
1119         }
1120     }
1121     void operator()(const _Tp* src, _Tp* dst, int n) const
1122     {
1123         int dcn = dstcn;
1124         _Tp alpha = ColorChannel<_Tp>::max();
1125         int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1126             C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1127             C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1128         n *= 3;
1129         for(int i = 0; i < n; i += 3, dst += dcn)
1130         {
1131             int B = CV_DESCALE(src[i]*C0 + src[i+1]*C1 + src[i+2]*C2, xyz_shift);
1132             int G = CV_DESCALE(src[i]*C3 + src[i+1]*C4 + src[i+2]*C5, xyz_shift);
1133             int R = CV_DESCALE(src[i]*C6 + src[i+1]*C7 + src[i+2]*C8, xyz_shift);
1134             dst[0] = saturate_cast<_Tp>(B); dst[1] = saturate_cast<_Tp>(G);
1135             dst[2] = saturate_cast<_Tp>(R);
1136             if( dcn == 4 )
1137                 dst[3] = alpha;
1138         }
1139     }
1140     int dstcn, blueIdx;
1141     int coeffs[9];
1142 };
1143
1144
1145 ////////////////////////////////////// RGB <-> HSV ///////////////////////////////////////
1146
1147
1148 struct RGB2HSV_b
1149 {
1150     typedef uchar channel_type;
1151
1152     RGB2HSV_b(int _srccn, int _blueIdx, int _hrange)
1153     : srccn(_srccn), blueIdx(_blueIdx), hrange(_hrange)
1154     {
1155         CV_Assert( hrange == 180 || hrange == 256 );
1156     }
1157
1158     void operator()(const uchar* src, uchar* dst, int n) const
1159     {
1160         int i, bidx = blueIdx, scn = srccn;
1161         const int hsv_shift = 12;
1162
1163         static int sdiv_table[256];
1164         static int hdiv_table180[256];
1165         static int hdiv_table256[256];
1166         static volatile bool initialized = false;
1167
1168         int hr = hrange;
1169         const int* hdiv_table = hr == 180 ? hdiv_table180 : hdiv_table256;
1170         n *= 3;
1171
1172         if( !initialized )
1173         {
1174             sdiv_table[0] = hdiv_table180[0] = hdiv_table256[0] = 0;
1175             for( i = 1; i < 256; i++ )
1176             {
1177                 sdiv_table[i] = saturate_cast<int>((255 << hsv_shift)/(1.*i));
1178                 hdiv_table180[i] = saturate_cast<int>((180 << hsv_shift)/(6.*i));
1179                 hdiv_table256[i] = saturate_cast<int>((256 << hsv_shift)/(6.*i));
1180             }
1181             initialized = true;
1182         }
1183
1184         for( i = 0; i < n; i += 3, src += scn )
1185         {
1186             int b = src[bidx], g = src[1], r = src[bidx^2];
1187             int h, s, v = b;
1188             int vmin = b, diff;
1189             int vr, vg;
1190
1191             CV_CALC_MAX_8U( v, g );
1192             CV_CALC_MAX_8U( v, r );
1193             CV_CALC_MIN_8U( vmin, g );
1194             CV_CALC_MIN_8U( vmin, r );
1195
1196             diff = v - vmin;
1197             vr = v == r ? -1 : 0;
1198             vg = v == g ? -1 : 0;
1199
1200             s = (diff * sdiv_table[v] + (1 << (hsv_shift-1))) >> hsv_shift;
1201             h = (vr & (g - b)) +
1202                 (~vr & ((vg & (b - r + 2 * diff)) + ((~vg) & (r - g + 4 * diff))));
1203             h = (h * hdiv_table[diff] + (1 << (hsv_shift-1))) >> hsv_shift;
1204             h += h < 0 ? hr : 0;
1205
1206             dst[i] = saturate_cast<uchar>(h);
1207             dst[i+1] = (uchar)s;
1208             dst[i+2] = (uchar)v;
1209         }
1210     }
1211
1212     int srccn, blueIdx, hrange;
1213 };
1214
1215
1216 struct RGB2HSV_f
1217 {
1218     typedef float channel_type;
1219
1220     RGB2HSV_f(int _srccn, int _blueIdx, float _hrange)
1221     : srccn(_srccn), blueIdx(_blueIdx), hrange(_hrange) {}
1222
1223     void operator()(const float* src, float* dst, int n) const
1224     {
1225         int i, bidx = blueIdx, scn = srccn;
1226         float hscale = hrange*(1.f/360.f);
1227         n *= 3;
1228
1229         for( i = 0; i < n; i += 3, src += scn )
1230         {
1231             float b = src[bidx], g = src[1], r = src[bidx^2];
1232             float h, s, v;
1233
1234             float vmin, diff;
1235
1236             v = vmin = r;
1237             if( v < g ) v = g;
1238             if( v < b ) v = b;
1239             if( vmin > g ) vmin = g;
1240             if( vmin > b ) vmin = b;
1241
1242             diff = v - vmin;
1243             s = diff/(float)(fabs(v) + FLT_EPSILON);
1244             diff = (float)(60./(diff + FLT_EPSILON));
1245             if( v == r )
1246                 h = (g - b)*diff;
1247             else if( v == g )
1248                 h = (b - r)*diff + 120.f;
1249             else
1250                 h = (r - g)*diff + 240.f;
1251
1252             if( h < 0 ) h += 360.f;
1253
1254             dst[i] = h*hscale;
1255             dst[i+1] = s;
1256             dst[i+2] = v;
1257         }
1258     }
1259
1260     int srccn, blueIdx;
1261     float hrange;
1262 };
1263
1264
1265 struct HSV2RGB_f
1266 {
1267     typedef float channel_type;
1268
1269     HSV2RGB_f(int _dstcn, int _blueIdx, float _hrange)
1270     : dstcn(_dstcn), blueIdx(_blueIdx), hscale(6.f/_hrange) {}
1271
1272     void operator()(const float* src, float* dst, int n) const
1273     {
1274         int i, bidx = blueIdx, dcn = dstcn;
1275         float _hscale = hscale;
1276         float alpha = ColorChannel<float>::max();
1277         n *= 3;
1278
1279         for( i = 0; i < n; i += 3, dst += dcn )
1280         {
1281             float h = src[i], s = src[i+1], v = src[i+2];
1282             float b, g, r;
1283
1284             if( s == 0 )
1285                 b = g = r = v;
1286             else
1287             {
1288                 static const int sector_data[][3]=
1289                     {{1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0}};
1290                 float tab[4];
1291                 int sector;
1292                 h *= _hscale;
1293                 if( h < 0 )
1294                     do h += 6; while( h < 0 );
1295                 else if( h >= 6 )
1296                     do h -= 6; while( h >= 6 );
1297                 sector = cvFloor(h);
1298                 h -= sector;
1299                 if( (unsigned)sector >= 6u )
1300                 {
1301                     sector = 0;
1302                     h = 0.f;
1303                 }
1304
1305                 tab[0] = v;
1306                 tab[1] = v*(1.f - s);
1307                 tab[2] = v*(1.f - s*h);
1308                 tab[3] = v*(1.f - s*(1.f - h));
1309
1310                 b = tab[sector_data[sector][0]];
1311                 g = tab[sector_data[sector][1]];
1312                 r = tab[sector_data[sector][2]];
1313             }
1314
1315             dst[bidx] = b;
1316             dst[1] = g;
1317             dst[bidx^2] = r;
1318             if( dcn == 4 )
1319                 dst[3] = alpha;
1320         }
1321     }
1322
1323     int dstcn, blueIdx;
1324     float hscale;
1325 };
1326
1327
1328 struct HSV2RGB_b
1329 {
1330     typedef uchar channel_type;
1331
1332     HSV2RGB_b(int _dstcn, int _blueIdx, int _hrange)
1333     : dstcn(_dstcn), cvt(3, _blueIdx, (float)_hrange)
1334     {}
1335
1336     void operator()(const uchar* src, uchar* dst, int n) const
1337     {
1338         int i, j, dcn = dstcn;
1339         uchar alpha = ColorChannel<uchar>::max();
1340         float buf[3*BLOCK_SIZE];
1341
1342         for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
1343         {
1344             int dn = std::min(n - i, (int)BLOCK_SIZE);
1345
1346             for( j = 0; j < dn*3; j += 3 )
1347             {
1348                 buf[j] = src[j];
1349                 buf[j+1] = src[j+1]*(1.f/255.f);
1350                 buf[j+2] = src[j+2]*(1.f/255.f);
1351             }
1352             cvt(buf, buf, dn);
1353
1354             for( j = 0; j < dn*3; j += 3, dst += dcn )
1355             {
1356                 dst[0] = saturate_cast<uchar>(buf[j]*255.f);
1357                 dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
1358                 dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
1359                 if( dcn == 4 )
1360                     dst[3] = alpha;
1361             }
1362         }
1363     }
1364
1365     int dstcn;
1366     HSV2RGB_f cvt;
1367 };
1368
1369
1370 ///////////////////////////////////// RGB <-> HLS ////////////////////////////////////////
1371
1372 struct RGB2HLS_f
1373 {
1374     typedef float channel_type;
1375
1376     RGB2HLS_f(int _srccn, int _blueIdx, float _hrange)
1377     : srccn(_srccn), blueIdx(_blueIdx), hrange(_hrange) {}
1378
1379     void operator()(const float* src, float* dst, int n) const
1380     {
1381         int i, bidx = blueIdx, scn = srccn;
1382         float hscale = hrange*(1.f/360.f);
1383         n *= 3;
1384
1385         for( i = 0; i < n; i += 3, src += scn )
1386         {
1387             float b = src[bidx], g = src[1], r = src[bidx^2];
1388             float h = 0.f, s = 0.f, l;
1389             float vmin, vmax, diff;
1390
1391             vmax = vmin = r;
1392             if( vmax < g ) vmax = g;
1393             if( vmax < b ) vmax = b;
1394             if( vmin > g ) vmin = g;
1395             if( vmin > b ) vmin = b;
1396
1397             diff = vmax - vmin;
1398             l = (vmax + vmin)*0.5f;
1399
1400             if( diff > FLT_EPSILON )
1401             {
1402                 s = l < 0.5f ? diff/(vmax + vmin) : diff/(2 - vmax - vmin);
1403                 diff = 60.f/diff;
1404
1405                 if( vmax == r )
1406                     h = (g - b)*diff;
1407                 else if( vmax == g )
1408                     h = (b - r)*diff + 120.f;
1409                 else
1410                     h = (r - g)*diff + 240.f;
1411
1412                 if( h < 0.f ) h += 360.f;
1413             }
1414
1415             dst[i] = h*hscale;
1416             dst[i+1] = l;
1417             dst[i+2] = s;
1418         }
1419     }
1420
1421     int srccn, blueIdx;
1422     float hrange;
1423 };
1424
1425
1426 struct RGB2HLS_b
1427 {
1428     typedef uchar channel_type;
1429
1430     RGB2HLS_b(int _srccn, int _blueIdx, int _hrange)
1431     : srccn(_srccn), cvt(3, _blueIdx, (float)_hrange) {}
1432
1433     void operator()(const uchar* src, uchar* dst, int n) const
1434     {
1435         int i, j, scn = srccn;
1436         float buf[3*BLOCK_SIZE];
1437
1438         for( i = 0; i < n; i += BLOCK_SIZE, dst += BLOCK_SIZE*3 )
1439         {
1440             int dn = std::min(n - i, (int)BLOCK_SIZE);
1441
1442             for( j = 0; j < dn*3; j += 3, src += scn )
1443             {
1444                 buf[j] = src[0]*(1.f/255.f);
1445                 buf[j+1] = src[1]*(1.f/255.f);
1446                 buf[j+2] = src[2]*(1.f/255.f);
1447             }
1448             cvt(buf, buf, dn);
1449
1450             for( j = 0; j < dn*3; j += 3 )
1451             {
1452                 dst[j] = saturate_cast<uchar>(buf[j]);
1453                 dst[j+1] = saturate_cast<uchar>(buf[j+1]*255.f);
1454                 dst[j+2] = saturate_cast<uchar>(buf[j+2]*255.f);
1455             }
1456         }
1457     }
1458
1459     int srccn;
1460     RGB2HLS_f cvt;
1461 };
1462
1463
1464 struct HLS2RGB_f
1465 {
1466     typedef float channel_type;
1467
1468     HLS2RGB_f(int _dstcn, int _blueIdx, float _hrange)
1469     : dstcn(_dstcn), blueIdx(_blueIdx), hscale(6.f/_hrange) {}
1470
1471     void operator()(const float* src, float* dst, int n) const
1472     {
1473         int i, bidx = blueIdx, dcn = dstcn;
1474         float _hscale = hscale;
1475         float alpha = ColorChannel<float>::max();
1476         n *= 3;
1477
1478         for( i = 0; i < n; i += 3, dst += dcn )
1479         {
1480             float h = src[i], l = src[i+1], s = src[i+2];
1481             float b, g, r;
1482
1483             if( s == 0 )
1484                 b = g = r = l;
1485             else
1486             {
1487                 static const int sector_data[][3]=
1488                 {{1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0}};
1489                 float tab[4];
1490                 int sector;
1491
1492                 float p2 = l <= 0.5f ? l*(1 + s) : l + s - l*s;
1493                 float p1 = 2*l - p2;
1494
1495                 h *= _hscale;
1496                 if( h < 0 )
1497                     do h += 6; while( h < 0 );
1498                 else if( h >= 6 )
1499                     do h -= 6; while( h >= 6 );
1500
1501                 assert( 0 <= h && h < 6 );
1502                 sector = cvFloor(h);
1503                 h -= sector;
1504
1505                 tab[0] = p2;
1506                 tab[1] = p1;
1507                 tab[2] = p1 + (p2 - p1)*(1-h);
1508                 tab[3] = p1 + (p2 - p1)*h;
1509
1510                 b = tab[sector_data[sector][0]];
1511                 g = tab[sector_data[sector][1]];
1512                 r = tab[sector_data[sector][2]];
1513             }
1514
1515             dst[bidx] = b;
1516             dst[1] = g;
1517             dst[bidx^2] = r;
1518             if( dcn == 4 )
1519                 dst[3] = alpha;
1520         }
1521     }
1522
1523     int dstcn, blueIdx;
1524     float hscale;
1525 };
1526
1527
1528 struct HLS2RGB_b
1529 {
1530     typedef uchar channel_type;
1531
1532     HLS2RGB_b(int _dstcn, int _blueIdx, int _hrange)
1533     : dstcn(_dstcn), cvt(3, _blueIdx, (float)_hrange)
1534     {}
1535
1536     void operator()(const uchar* src, uchar* dst, int n) const
1537     {
1538         int i, j, dcn = dstcn;
1539         uchar alpha = ColorChannel<uchar>::max();
1540         float buf[3*BLOCK_SIZE];
1541
1542         for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
1543         {
1544             int dn = std::min(n - i, (int)BLOCK_SIZE);
1545
1546             for( j = 0; j < dn*3; j += 3 )
1547             {
1548                 buf[j] = src[j];
1549                 buf[j+1] = src[j+1]*(1.f/255.f);
1550                 buf[j+2] = src[j+2]*(1.f/255.f);
1551             }
1552             cvt(buf, buf, dn);
1553
1554             for( j = 0; j < dn*3; j += 3, dst += dcn )
1555             {
1556                 dst[0] = saturate_cast<uchar>(buf[j]*255.f);
1557                 dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
1558                 dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
1559                 if( dcn == 4 )
1560                     dst[3] = alpha;
1561             }
1562         }
1563     }
1564
1565     int dstcn;
1566     HLS2RGB_f cvt;
1567 };
1568
1569
1570 ///////////////////////////////////// RGB <-> L*a*b* /////////////////////////////////////
1571
1572 static const float D65[] = { 0.950456f, 1.f, 1.088754f };
1573
1574 enum { LAB_CBRT_TAB_SIZE = 1024, GAMMA_TAB_SIZE = 1024 };
1575 static float LabCbrtTab[LAB_CBRT_TAB_SIZE*4];
1576 static const float LabCbrtTabScale = LAB_CBRT_TAB_SIZE/1.5f;
1577
1578 static float sRGBGammaTab[GAMMA_TAB_SIZE*4], sRGBInvGammaTab[GAMMA_TAB_SIZE*4];
1579 static const float GammaTabScale = (float)GAMMA_TAB_SIZE;
1580
1581 static ushort sRGBGammaTab_b[256], linearGammaTab_b[256];
1582 #undef lab_shift
1583 #define lab_shift xyz_shift
1584 #define gamma_shift 3
1585 #define lab_shift2 (lab_shift + gamma_shift)
1586 #define LAB_CBRT_TAB_SIZE_B (256*3/2*(1<<gamma_shift))
1587 static ushort LabCbrtTab_b[LAB_CBRT_TAB_SIZE_B];
1588
1589 static void initLabTabs()
1590 {
1591     static bool initialized = false;
1592     if(!initialized)
1593     {
1594         float f[LAB_CBRT_TAB_SIZE+1], g[GAMMA_TAB_SIZE+1], ig[GAMMA_TAB_SIZE+1], scale = 1.f/LabCbrtTabScale;
1595         int i;
1596         for(i = 0; i <= LAB_CBRT_TAB_SIZE; i++)
1597         {
1598             float x = i*scale;
1599             f[i] = x < 0.008856f ? x*7.787f + 0.13793103448275862f : cvCbrt(x);
1600         }
1601         splineBuild(f, LAB_CBRT_TAB_SIZE, LabCbrtTab);
1602
1603         scale = 1.f/GammaTabScale;
1604         for(i = 0; i <= GAMMA_TAB_SIZE; i++)
1605         {
1606             float x = i*scale;
1607             g[i] = x <= 0.04045f ? x*(1.f/12.92f) : (float)std::pow((double)(x + 0.055)*(1./1.055), 2.4);
1608             ig[i] = x <= 0.0031308 ? x*12.92f : (float)(1.055*std::pow((double)x, 1./2.4) - 0.055);
1609         }
1610         splineBuild(g, GAMMA_TAB_SIZE, sRGBGammaTab);
1611         splineBuild(ig, GAMMA_TAB_SIZE, sRGBInvGammaTab);
1612
1613         for(i = 0; i < 256; i++)
1614         {
1615             float x = i*(1.f/255.f);
1616             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)));
1617             linearGammaTab_b[i] = (ushort)(i*(1 << gamma_shift));
1618         }
1619
1620         for(i = 0; i < LAB_CBRT_TAB_SIZE_B; i++)
1621         {
1622             float x = i*(1.f/(255.f*(1 << gamma_shift)));
1623             LabCbrtTab_b[i] = saturate_cast<ushort>((1 << lab_shift2)*(x < 0.008856f ? x*7.787f + 0.13793103448275862f : cvCbrt(x)));
1624         }
1625         initialized = true;
1626     }
1627 }
1628
1629 struct RGB2Lab_b
1630 {
1631     typedef uchar channel_type;
1632
1633     RGB2Lab_b(int _srccn, int blueIdx, const float* _coeffs,
1634               const float* _whitept, bool _srgb)
1635     : srccn(_srccn), srgb(_srgb)
1636     {
1637         static volatile int _3 = 3;
1638         initLabTabs();
1639
1640         if (!_coeffs)
1641             _coeffs = sRGB2XYZ_D65;
1642         if (!_whitept)
1643             _whitept = D65;
1644
1645         float scale[] =
1646         {
1647             (1 << lab_shift)/_whitept[0],
1648             (float)(1 << lab_shift),
1649             (1 << lab_shift)/_whitept[2]
1650         };
1651
1652         for( int i = 0; i < _3; i++ )
1653         {
1654             coeffs[i*3+(blueIdx^2)] = cvRound(_coeffs[i*3]*scale[i]);
1655             coeffs[i*3+1] = cvRound(_coeffs[i*3+1]*scale[i]);
1656             coeffs[i*3+blueIdx] = cvRound(_coeffs[i*3+2]*scale[i]);
1657
1658             CV_Assert( coeffs[i] >= 0 && coeffs[i*3+1] >= 0 && coeffs[i*3+2] >= 0 &&
1659                       coeffs[i*3] + coeffs[i*3+1] + coeffs[i*3+2] < 2*(1 << lab_shift) );
1660         }
1661     }
1662
1663     void operator()(const uchar* src, uchar* dst, int n) const
1664     {
1665         const int Lscale = (116*255+50)/100;
1666         const int Lshift = -((16*255*(1 << lab_shift2) + 50)/100);
1667         const ushort* tab = srgb ? sRGBGammaTab_b : linearGammaTab_b;
1668         int i, scn = srccn;
1669         int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1670             C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1671             C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1672         n *= 3;
1673
1674         for( i = 0; i < n; i += 3, src += scn )
1675         {
1676             int R = tab[src[0]], G = tab[src[1]], B = tab[src[2]];
1677             int fX = LabCbrtTab_b[CV_DESCALE(R*C0 + G*C1 + B*C2, lab_shift)];
1678             int fY = LabCbrtTab_b[CV_DESCALE(R*C3 + G*C4 + B*C5, lab_shift)];
1679             int fZ = LabCbrtTab_b[CV_DESCALE(R*C6 + G*C7 + B*C8, lab_shift)];
1680
1681             int L = CV_DESCALE( Lscale*fY + Lshift, lab_shift2 );
1682             int a = CV_DESCALE( 500*(fX - fY) + 128*(1 << lab_shift2), lab_shift2 );
1683             int b = CV_DESCALE( 200*(fY - fZ) + 128*(1 << lab_shift2), lab_shift2 );
1684
1685             dst[i] = saturate_cast<uchar>(L);
1686             dst[i+1] = saturate_cast<uchar>(a);
1687             dst[i+2] = saturate_cast<uchar>(b);
1688         }
1689     }
1690
1691     int srccn;
1692     int coeffs[9];
1693     bool srgb;
1694 };
1695
1696
1697 #define clip(value) \
1698     value < 0.0f ? 0.0f : value > 1.0f ? 1.0f : value;
1699
1700 struct RGB2Lab_f
1701 {
1702     typedef float channel_type;
1703
1704     RGB2Lab_f(int _srccn, int blueIdx, const float* _coeffs,
1705               const float* _whitept, bool _srgb)
1706     : srccn(_srccn), srgb(_srgb)
1707     {
1708         volatile int _3 = 3;
1709         initLabTabs();
1710
1711         if (!_coeffs)
1712             _coeffs = sRGB2XYZ_D65;
1713         if (!_whitept)
1714             _whitept = D65;
1715
1716         float scale[] = { 1.0f / _whitept[0], 1.0f, 1.0f / _whitept[2] };
1717
1718         for( int i = 0; i < _3; i++ )
1719         {
1720             int j = i * 3;
1721             coeffs[j + (blueIdx ^ 2)] = _coeffs[j] * scale[i];
1722             coeffs[j + 1] = _coeffs[j + 1] * scale[i];
1723             coeffs[j + blueIdx] = _coeffs[j + 2] * scale[i];
1724
1725             CV_Assert( coeffs[j] >= 0 && coeffs[j + 1] >= 0 && coeffs[j + 2] >= 0 &&
1726                        coeffs[j] + coeffs[j + 1] + coeffs[j + 2] < 1.5f*LabCbrtTabScale );
1727         }
1728     }
1729
1730     void operator()(const float* src, float* dst, int n) const
1731     {
1732         int i, scn = srccn;
1733         float gscale = GammaTabScale;
1734         const float* gammaTab = srgb ? sRGBGammaTab : 0;
1735         float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1736               C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1737               C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1738         n *= 3;
1739
1740         static const float _1_3 = 1.0f / 3.0f;
1741         static const float _a = 16.0f / 116.0f;
1742         for (i = 0; i < n; i += 3, src += scn )
1743         {
1744             float R = clip(src[0]);
1745             float G = clip(src[1]);
1746             float B = clip(src[2]);
1747
1748             if (gammaTab)
1749             {
1750                 R = splineInterpolate(R * gscale, gammaTab, GAMMA_TAB_SIZE);
1751                 G = splineInterpolate(G * gscale, gammaTab, GAMMA_TAB_SIZE);
1752                 B = splineInterpolate(B * gscale, gammaTab, GAMMA_TAB_SIZE);
1753             }
1754             float X = R*C0 + G*C1 + B*C2;
1755             float Y = R*C3 + G*C4 + B*C5;
1756             float Z = R*C6 + G*C7 + B*C8;
1757
1758             float FX = X > 0.008856f ? std::pow(X, _1_3) : (7.787f * X + _a);
1759             float FY = Y > 0.008856f ? std::pow(Y, _1_3) : (7.787f * Y + _a);
1760             float FZ = Z > 0.008856f ? std::pow(Z, _1_3) : (7.787f * Z + _a);
1761
1762             float L = Y > 0.008856f ? (116.f * FY - 16.f) : (903.3f * Y);
1763             float a = 500.f * (FX - FY);
1764             float b = 200.f * (FY - FZ);
1765
1766             dst[i] = L;
1767             dst[i + 1] = a;
1768             dst[i + 2] = b;
1769         }
1770     }
1771
1772     int srccn;
1773     float coeffs[9];
1774     bool srgb;
1775 };
1776
1777 struct Lab2RGB_f
1778 {
1779     typedef float channel_type;
1780
1781     Lab2RGB_f( int _dstcn, int blueIdx, const float* _coeffs,
1782               const float* _whitept, bool _srgb )
1783     : dstcn(_dstcn), srgb(_srgb)
1784     {
1785         initLabTabs();
1786
1787         if(!_coeffs)
1788             _coeffs = XYZ2sRGB_D65;
1789         if(!_whitept)
1790             _whitept = D65;
1791
1792         for( int i = 0; i < 3; i++ )
1793         {
1794             coeffs[i+(blueIdx^2)*3] = _coeffs[i]*_whitept[i];
1795             coeffs[i+3] = _coeffs[i+3]*_whitept[i];
1796             coeffs[i+blueIdx*3] = _coeffs[i+6]*_whitept[i];
1797         }
1798     }
1799
1800     void operator()(const float* src, float* dst, int n) const
1801     {
1802         int i, dcn = dstcn;
1803         const float* gammaTab = srgb ? sRGBInvGammaTab : 0;
1804         float gscale = GammaTabScale;
1805         float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1806         C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1807         C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1808         float alpha = ColorChannel<float>::max();
1809         n *= 3;
1810
1811         static const float lThresh = 0.008856f * 903.3f;
1812         static const float fThresh = 7.787f * 0.008856f + 16.0f / 116.0f;
1813         for (i = 0; i < n; i += 3, dst += dcn)
1814         {
1815             float li = src[i];
1816             float ai = src[i + 1];
1817             float bi = src[i + 2];
1818
1819             float y, fy;
1820             if (li <= lThresh)
1821             {
1822                 y = li / 903.3f;
1823                 fy = 7.787f * y + 16.0f / 116.0f;
1824             }
1825             else
1826             {
1827                 fy = (li + 16.0f) / 116.0f;
1828                 y = fy * fy * fy;
1829             }
1830
1831             float fxz[] = { ai / 500.0f + fy, fy - bi / 200.0f };
1832
1833             for (int j = 0; j < 2; j++)
1834                 if (fxz[j] <= fThresh)
1835                     fxz[j] = (fxz[j] - 16.0f / 116.0f) / 7.787f;
1836                 else
1837                     fxz[j] = fxz[j] * fxz[j] * fxz[j];
1838
1839
1840             float x = fxz[0], z = fxz[1];
1841             float ro = C0 * x + C1 * y + C2 * z;
1842             float go = C3 * x + C4 * y + C5 * z;
1843             float bo = C6 * x + C7 * y + C8 * z;
1844             ro = clip(ro);
1845             go = clip(go);
1846             bo = clip(bo);
1847
1848             if (gammaTab)
1849             {
1850                 ro = splineInterpolate(ro * gscale, gammaTab, GAMMA_TAB_SIZE);
1851                 go = splineInterpolate(go * gscale, gammaTab, GAMMA_TAB_SIZE);
1852                 bo = splineInterpolate(bo * gscale, gammaTab, GAMMA_TAB_SIZE);
1853             }
1854
1855             dst[0] = ro, dst[1] = go, dst[2] = bo;
1856             if( dcn == 4 )
1857                 dst[3] = alpha;
1858         }
1859     }
1860
1861     int dstcn;
1862     float coeffs[9];
1863     bool srgb;
1864 };
1865
1866 #undef clip
1867
1868 struct Lab2RGB_b
1869 {
1870     typedef uchar channel_type;
1871
1872     Lab2RGB_b( int _dstcn, int blueIdx, const float* _coeffs,
1873                const float* _whitept, bool _srgb )
1874     : dstcn(_dstcn), cvt(3, blueIdx, _coeffs, _whitept, _srgb ) {}
1875
1876     void operator()(const uchar* src, uchar* dst, int n) const
1877     {
1878         int i, j, dcn = dstcn;
1879         uchar alpha = ColorChannel<uchar>::max();
1880         float buf[3*BLOCK_SIZE];
1881
1882         for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
1883         {
1884             int dn = std::min(n - i, (int)BLOCK_SIZE);
1885
1886             for( j = 0; j < dn*3; j += 3 )
1887             {
1888                 buf[j] = src[j]*(100.f/255.f);
1889                 buf[j+1] = (float)(src[j+1] - 128);
1890                 buf[j+2] = (float)(src[j+2] - 128);
1891             }
1892             cvt(buf, buf, dn);
1893
1894             for( j = 0; j < dn*3; j += 3, dst += dcn )
1895             {
1896                 dst[0] = saturate_cast<uchar>(buf[j]*255.f);
1897                 dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
1898                 dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
1899                 if( dcn == 4 )
1900                     dst[3] = alpha;
1901             }
1902         }
1903     }
1904
1905     int dstcn;
1906     Lab2RGB_f cvt;
1907 };
1908
1909
1910 ///////////////////////////////////// RGB <-> L*u*v* /////////////////////////////////////
1911
1912 struct RGB2Luv_f
1913 {
1914     typedef float channel_type;
1915
1916     RGB2Luv_f( int _srccn, int blueIdx, const float* _coeffs,
1917                const float* whitept, bool _srgb )
1918     : srccn(_srccn), srgb(_srgb)
1919     {
1920         volatile int i;
1921         initLabTabs();
1922
1923         if(!_coeffs) _coeffs = sRGB2XYZ_D65;
1924         if(!whitept) whitept = D65;
1925
1926         for( i = 0; i < 3; i++ )
1927         {
1928             coeffs[i*3] = _coeffs[i*3];
1929             coeffs[i*3+1] = _coeffs[i*3+1];
1930             coeffs[i*3+2] = _coeffs[i*3+2];
1931             if( blueIdx == 0 )
1932                 std::swap(coeffs[i*3], coeffs[i*3+2]);
1933             CV_Assert( coeffs[i*3] >= 0 && coeffs[i*3+1] >= 0 && coeffs[i*3+2] >= 0 &&
1934                       coeffs[i*3] + coeffs[i*3+1] + coeffs[i*3+2] < 1.5f );
1935         }
1936
1937         float d = 1.f/(whitept[0] + whitept[1]*15 + whitept[2]*3);
1938         un = 4*whitept[0]*d;
1939         vn = 9*whitept[1]*d;
1940
1941         CV_Assert(whitept[1] == 1.f);
1942     }
1943
1944     void operator()(const float* src, float* dst, int n) const
1945     {
1946         int i, scn = srccn;
1947         float gscale = GammaTabScale;
1948         const float* gammaTab = srgb ? sRGBGammaTab : 0;
1949         float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
1950               C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
1951               C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
1952         float _un = 13*un, _vn = 13*vn;
1953         n *= 3;
1954
1955         for( i = 0; i < n; i += 3, src += scn )
1956         {
1957             float R = src[0], G = src[1], B = src[2];
1958             if( gammaTab )
1959             {
1960                 R = splineInterpolate(R*gscale, gammaTab, GAMMA_TAB_SIZE);
1961                 G = splineInterpolate(G*gscale, gammaTab, GAMMA_TAB_SIZE);
1962                 B = splineInterpolate(B*gscale, gammaTab, GAMMA_TAB_SIZE);
1963             }
1964
1965             float X = R*C0 + G*C1 + B*C2;
1966             float Y = R*C3 + G*C4 + B*C5;
1967             float Z = R*C6 + G*C7 + B*C8;
1968
1969             float L = splineInterpolate(Y*LabCbrtTabScale, LabCbrtTab, LAB_CBRT_TAB_SIZE);
1970             L = 116.f*L - 16.f;
1971
1972             float d = (4*13) / std::max(X + 15 * Y + 3 * Z, FLT_EPSILON);
1973             float u = L*(X*d - _un);
1974             float v = L*((9*0.25f)*Y*d - _vn);
1975
1976             dst[i] = L; dst[i+1] = u; dst[i+2] = v;
1977         }
1978     }
1979
1980     int srccn;
1981     float coeffs[9], un, vn;
1982     bool srgb;
1983 };
1984
1985
1986 struct Luv2RGB_f
1987 {
1988     typedef float channel_type;
1989
1990     Luv2RGB_f( int _dstcn, int blueIdx, const float* _coeffs,
1991               const float* whitept, bool _srgb )
1992     : dstcn(_dstcn), srgb(_srgb)
1993     {
1994         initLabTabs();
1995
1996         if(!_coeffs) _coeffs = XYZ2sRGB_D65;
1997         if(!whitept) whitept = D65;
1998
1999         for( int i = 0; i < 3; i++ )
2000         {
2001             coeffs[i+(blueIdx^2)*3] = _coeffs[i];
2002             coeffs[i+3] = _coeffs[i+3];
2003             coeffs[i+blueIdx*3] = _coeffs[i+6];
2004         }
2005
2006         float d = 1.f/(whitept[0] + whitept[1]*15 + whitept[2]*3);
2007         un = 4*whitept[0]*d;
2008         vn = 9*whitept[1]*d;
2009
2010         CV_Assert(whitept[1] == 1.f);
2011     }
2012
2013     void operator()(const float* src, float* dst, int n) const
2014     {
2015         int i, dcn = dstcn;
2016         const float* gammaTab = srgb ? sRGBInvGammaTab : 0;
2017         float gscale = GammaTabScale;
2018         float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2],
2019               C3 = coeffs[3], C4 = coeffs[4], C5 = coeffs[5],
2020               C6 = coeffs[6], C7 = coeffs[7], C8 = coeffs[8];
2021         float alpha = ColorChannel<float>::max();
2022         float _un = un, _vn = vn;
2023         n *= 3;
2024
2025         for( i = 0; i < n; i += 3, dst += dcn )
2026         {
2027             float L = src[i], u = src[i+1], v = src[i+2], d, X, Y, Z;
2028             Y = (L + 16.f) * (1.f/116.f);
2029             Y = Y*Y*Y;
2030             d = (1.f/13.f)/L;
2031             u = u*d + _un;
2032             v = v*d + _vn;
2033             float iv = 1.f/v;
2034             X = 2.25f * u * Y * iv ;
2035             Z = (12 - 3 * u - 20 * v) * Y * 0.25f * iv;
2036
2037             float R = X*C0 + Y*C1 + Z*C2;
2038             float G = X*C3 + Y*C4 + Z*C5;
2039             float B = X*C6 + Y*C7 + Z*C8;
2040
2041             R = std::min(std::max(R, 0.f), 1.f);
2042             G = std::min(std::max(G, 0.f), 1.f);
2043             B = std::min(std::max(B, 0.f), 1.f);
2044
2045             if( gammaTab )
2046             {
2047                 R = splineInterpolate(R*gscale, gammaTab, GAMMA_TAB_SIZE);
2048                 G = splineInterpolate(G*gscale, gammaTab, GAMMA_TAB_SIZE);
2049                 B = splineInterpolate(B*gscale, gammaTab, GAMMA_TAB_SIZE);
2050             }
2051
2052             dst[0] = R; dst[1] = G; dst[2] = B;
2053             if( dcn == 4 )
2054                 dst[3] = alpha;
2055         }
2056     }
2057
2058     int dstcn;
2059     float coeffs[9], un, vn;
2060     bool srgb;
2061 };
2062
2063
2064 struct RGB2Luv_b
2065 {
2066     typedef uchar channel_type;
2067
2068     RGB2Luv_b( int _srccn, int blueIdx, const float* _coeffs,
2069                const float* _whitept, bool _srgb )
2070     : srccn(_srccn), cvt(3, blueIdx, _coeffs, _whitept, _srgb) {}
2071
2072     void operator()(const uchar* src, uchar* dst, int n) const
2073     {
2074         int i, j, scn = srccn;
2075         float buf[3*BLOCK_SIZE];
2076
2077         for( i = 0; i < n; i += BLOCK_SIZE, dst += BLOCK_SIZE*3 )
2078         {
2079             int dn = std::min(n - i, (int)BLOCK_SIZE);
2080
2081             for( j = 0; j < dn*3; j += 3, src += scn )
2082             {
2083                 buf[j] = src[0]*(1.f/255.f);
2084                 buf[j+1] = (float)(src[1]*(1.f/255.f));
2085                 buf[j+2] = (float)(src[2]*(1.f/255.f));
2086             }
2087             cvt(buf, buf, dn);
2088
2089             for( j = 0; j < dn*3; j += 3 )
2090             {
2091                 dst[j] = saturate_cast<uchar>(buf[j]*2.55f);
2092                 dst[j+1] = saturate_cast<uchar>(buf[j+1]*0.72033898305084743f + 96.525423728813564f);
2093                 dst[j+2] = saturate_cast<uchar>(buf[j+2]*0.99609375f + 139.453125f);
2094             }
2095         }
2096     }
2097
2098     int srccn;
2099     RGB2Luv_f cvt;
2100 };
2101
2102
2103 struct Luv2RGB_b
2104 {
2105     typedef uchar channel_type;
2106
2107     Luv2RGB_b( int _dstcn, int blueIdx, const float* _coeffs,
2108                const float* _whitept, bool _srgb )
2109     : dstcn(_dstcn), cvt(3, blueIdx, _coeffs, _whitept, _srgb ) {}
2110
2111     void operator()(const uchar* src, uchar* dst, int n) const
2112     {
2113         int i, j, dcn = dstcn;
2114         uchar alpha = ColorChannel<uchar>::max();
2115         float buf[3*BLOCK_SIZE];
2116
2117         for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
2118         {
2119             int dn = std::min(n - i, (int)BLOCK_SIZE);
2120
2121             for( j = 0; j < dn*3; j += 3 )
2122             {
2123                 buf[j] = src[j]*(100.f/255.f);
2124                 buf[j+1] = (float)(src[j+1]*1.388235294117647f - 134.f);
2125                 buf[j+2] = (float)(src[j+2]*1.003921568627451f - 140.f);
2126             }
2127             cvt(buf, buf, dn);
2128
2129             for( j = 0; j < dn*3; j += 3, dst += dcn )
2130             {
2131                 dst[0] = saturate_cast<uchar>(buf[j]*255.f);
2132                 dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
2133                 dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
2134                 if( dcn == 4 )
2135                     dst[3] = alpha;
2136             }
2137         }
2138     }
2139
2140     int dstcn;
2141     Luv2RGB_f cvt;
2142 };
2143
2144
2145 ///////////////////////////////////// YUV420 -> RGB /////////////////////////////////////
2146
2147 const int ITUR_BT_601_CY = 1220542;
2148 const int ITUR_BT_601_CUB = 2116026;
2149 const int ITUR_BT_601_CUG = -409993;
2150 const int ITUR_BT_601_CVG = -852492;
2151 const int ITUR_BT_601_CVR = 1673527;
2152 const int ITUR_BT_601_SHIFT = 20;
2153
2154 // Coefficients for RGB to YUV420p conversion
2155 const int ITUR_BT_601_CRY =  269484;
2156 const int ITUR_BT_601_CGY =  528482;
2157 const int ITUR_BT_601_CBY =  102760;
2158 const int ITUR_BT_601_CRU = -155188;
2159 const int ITUR_BT_601_CGU = -305135;
2160 const int ITUR_BT_601_CBU =  460324;
2161 const int ITUR_BT_601_CGV = -385875;
2162 const int ITUR_BT_601_CBV = -74448;
2163
2164 template<int bIdx, int uIdx>
2165 struct YUV420sp2RGB888Invoker : ParallelLoopBody
2166 {
2167     Mat* dst;
2168     const uchar* my1, *muv;
2169     int width, stride;
2170
2171     YUV420sp2RGB888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _uv)
2172         : dst(_dst), my1(_y1), muv(_uv), width(_dst->cols), stride(_stride) {}
2173
2174     void operator()(const Range& range) const
2175     {
2176         int rangeBegin = range.start * 2;
2177         int rangeEnd = range.end * 2;
2178
2179         //R = 1.164(Y - 16) + 1.596(V - 128)
2180         //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
2181         //B = 1.164(Y - 16)                  + 2.018(U - 128)
2182
2183         //R = (1220542(Y - 16) + 1673527(V - 128)                  + (1 << 19)) >> 20
2184         //G = (1220542(Y - 16) - 852492(V - 128) - 409993(U - 128) + (1 << 19)) >> 20
2185         //B = (1220542(Y - 16)                  + 2116026(U - 128) + (1 << 19)) >> 20
2186
2187         const uchar* y1 = my1 + rangeBegin * stride, *uv = muv + rangeBegin * stride / 2;
2188
2189 #ifdef HAVE_TEGRA_OPTIMIZATION
2190         if(tegra::cvtYUV4202RGB(bIdx, uIdx, 3, y1, uv, stride, dst->ptr<uchar>(rangeBegin), dst->step, rangeEnd - rangeBegin, dst->cols))
2191             return;
2192 #endif
2193
2194         for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, uv += stride)
2195         {
2196             uchar* row1 = dst->ptr<uchar>(j);
2197             uchar* row2 = dst->ptr<uchar>(j + 1);
2198             const uchar* y2 = y1 + stride;
2199
2200             for (int i = 0; i < width; i += 2, row1 += 6, row2 += 6)
2201             {
2202                 int u = int(uv[i + 0 + uIdx]) - 128;
2203                 int v = int(uv[i + 1 - uIdx]) - 128;
2204
2205                 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2206                 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2207                 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2208
2209                 int y00 = std::max(0, int(y1[i]) - 16) * ITUR_BT_601_CY;
2210                 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2211                 row1[1]      = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2212                 row1[bIdx]   = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2213
2214                 int y01 = std::max(0, int(y1[i + 1]) - 16) * ITUR_BT_601_CY;
2215                 row1[5-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2216                 row1[4]      = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2217                 row1[3+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2218
2219                 int y10 = std::max(0, int(y2[i]) - 16) * ITUR_BT_601_CY;
2220                 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2221                 row2[1]      = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2222                 row2[bIdx]   = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2223
2224                 int y11 = std::max(0, int(y2[i + 1]) - 16) * ITUR_BT_601_CY;
2225                 row2[5-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2226                 row2[4]      = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2227                 row2[3+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2228             }
2229         }
2230     }
2231 };
2232
2233 template<int bIdx, int uIdx>
2234 struct YUV420sp2RGBA8888Invoker : ParallelLoopBody
2235 {
2236     Mat* dst;
2237     const uchar* my1, *muv;
2238     int width, stride;
2239
2240     YUV420sp2RGBA8888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _uv)
2241         : dst(_dst), my1(_y1), muv(_uv), width(_dst->cols), stride(_stride) {}
2242
2243     void operator()(const Range& range) const
2244     {
2245         int rangeBegin = range.start * 2;
2246         int rangeEnd = range.end * 2;
2247
2248         //R = 1.164(Y - 16) + 1.596(V - 128)
2249         //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
2250         //B = 1.164(Y - 16)                  + 2.018(U - 128)
2251
2252         //R = (1220542(Y - 16) + 1673527(V - 128)                  + (1 << 19)) >> 20
2253         //G = (1220542(Y - 16) - 852492(V - 128) - 409993(U - 128) + (1 << 19)) >> 20
2254         //B = (1220542(Y - 16)                  + 2116026(U - 128) + (1 << 19)) >> 20
2255
2256         const uchar* y1 = my1 + rangeBegin * stride, *uv = muv + rangeBegin * stride / 2;
2257
2258 #ifdef HAVE_TEGRA_OPTIMIZATION
2259         if(tegra::cvtYUV4202RGB(bIdx, uIdx, 4, y1, uv, stride, dst->ptr<uchar>(rangeBegin), dst->step, rangeEnd - rangeBegin, dst->cols))
2260             return;
2261 #endif
2262
2263         for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, uv += stride)
2264         {
2265             uchar* row1 = dst->ptr<uchar>(j);
2266             uchar* row2 = dst->ptr<uchar>(j + 1);
2267             const uchar* y2 = y1 + stride;
2268
2269             for (int i = 0; i < width; i += 2, row1 += 8, row2 += 8)
2270             {
2271                 int u = int(uv[i + 0 + uIdx]) - 128;
2272                 int v = int(uv[i + 1 - uIdx]) - 128;
2273
2274                 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2275                 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2276                 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2277
2278                 int y00 = std::max(0, int(y1[i]) - 16) * ITUR_BT_601_CY;
2279                 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2280                 row1[1]      = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2281                 row1[bIdx]   = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2282                 row1[3]      = uchar(0xff);
2283
2284                 int y01 = std::max(0, int(y1[i + 1]) - 16) * ITUR_BT_601_CY;
2285                 row1[6-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2286                 row1[5]      = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2287                 row1[4+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2288                 row1[7]      = uchar(0xff);
2289
2290                 int y10 = std::max(0, int(y2[i]) - 16) * ITUR_BT_601_CY;
2291                 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2292                 row2[1]      = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2293                 row2[bIdx]   = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2294                 row2[3]      = uchar(0xff);
2295
2296                 int y11 = std::max(0, int(y2[i + 1]) - 16) * ITUR_BT_601_CY;
2297                 row2[6-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2298                 row2[5]      = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2299                 row2[4+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2300                 row2[7]      = uchar(0xff);
2301             }
2302         }
2303     }
2304 };
2305
2306 template<int bIdx>
2307 struct YUV420p2RGB888Invoker : ParallelLoopBody
2308 {
2309     Mat* dst;
2310     const uchar* my1, *mu, *mv;
2311     int width, stride;
2312     int ustepIdx, vstepIdx;
2313
2314     YUV420p2RGB888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int _ustepIdx, int _vstepIdx)
2315         : dst(_dst), my1(_y1), mu(_u), mv(_v), width(_dst->cols), stride(_stride), ustepIdx(_ustepIdx), vstepIdx(_vstepIdx) {}
2316
2317     void operator()(const Range& range) const
2318     {
2319         const int rangeBegin = range.start * 2;
2320         const int rangeEnd = range.end * 2;
2321
2322         int uvsteps[2] = {width/2, stride - width/2};
2323         int usIdx = ustepIdx, vsIdx = vstepIdx;
2324
2325         const uchar* y1 = my1 + rangeBegin * stride;
2326         const uchar* u1 = mu + (range.start / 2) * stride;
2327         const uchar* v1 = mv + (range.start / 2) * stride;
2328
2329         if(range.start % 2 == 1)
2330         {
2331             u1 += uvsteps[(usIdx++) & 1];
2332             v1 += uvsteps[(vsIdx++) & 1];
2333         }
2334
2335         for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, u1 += uvsteps[(usIdx++) & 1], v1 += uvsteps[(vsIdx++) & 1])
2336         {
2337             uchar* row1 = dst->ptr<uchar>(j);
2338             uchar* row2 = dst->ptr<uchar>(j + 1);
2339             const uchar* y2 = y1 + stride;
2340
2341             for (int i = 0; i < width / 2; i += 1, row1 += 6, row2 += 6)
2342             {
2343                 int u = int(u1[i]) - 128;
2344                 int v = int(v1[i]) - 128;
2345
2346                 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2347                 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2348                 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2349
2350                 int y00 = std::max(0, int(y1[2 * i]) - 16) * ITUR_BT_601_CY;
2351                 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2352                 row1[1]      = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2353                 row1[bIdx]   = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2354
2355                 int y01 = std::max(0, int(y1[2 * i + 1]) - 16) * ITUR_BT_601_CY;
2356                 row1[5-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2357                 row1[4]      = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2358                 row1[3+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2359
2360                 int y10 = std::max(0, int(y2[2 * i]) - 16) * ITUR_BT_601_CY;
2361                 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2362                 row2[1]      = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2363                 row2[bIdx]   = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2364
2365                 int y11 = std::max(0, int(y2[2 * i + 1]) - 16) * ITUR_BT_601_CY;
2366                 row2[5-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2367                 row2[4]      = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2368                 row2[3+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2369             }
2370         }
2371     }
2372 };
2373
2374 template<int bIdx>
2375 struct YUV420p2RGBA8888Invoker : ParallelLoopBody
2376 {
2377     Mat* dst;
2378     const uchar* my1, *mu, *mv;
2379     int width, stride;
2380     int ustepIdx, vstepIdx;
2381
2382     YUV420p2RGBA8888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int _ustepIdx, int _vstepIdx)
2383         : dst(_dst), my1(_y1), mu(_u), mv(_v), width(_dst->cols), stride(_stride), ustepIdx(_ustepIdx), vstepIdx(_vstepIdx) {}
2384
2385     void operator()(const Range& range) const
2386     {
2387         int rangeBegin = range.start * 2;
2388         int rangeEnd = range.end * 2;
2389
2390         int uvsteps[2] = {width/2, stride - width/2};
2391         int usIdx = ustepIdx, vsIdx = vstepIdx;
2392
2393         const uchar* y1 = my1 + rangeBegin * stride;
2394         const uchar* u1 = mu + (range.start / 2) * stride;
2395         const uchar* v1 = mv + (range.start / 2) * stride;
2396
2397         if(range.start % 2 == 1)
2398         {
2399             u1 += uvsteps[(usIdx++) & 1];
2400             v1 += uvsteps[(vsIdx++) & 1];
2401         }
2402
2403         for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, u1 += uvsteps[(usIdx++) & 1], v1 += uvsteps[(vsIdx++) & 1])
2404         {
2405             uchar* row1 = dst->ptr<uchar>(j);
2406             uchar* row2 = dst->ptr<uchar>(j + 1);
2407             const uchar* y2 = y1 + stride;
2408
2409             for (int i = 0; i < width / 2; i += 1, row1 += 8, row2 += 8)
2410             {
2411                 int u = int(u1[i]) - 128;
2412                 int v = int(v1[i]) - 128;
2413
2414                 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2415                 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2416                 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2417
2418                 int y00 = std::max(0, int(y1[2 * i]) - 16) * ITUR_BT_601_CY;
2419                 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2420                 row1[1]      = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2421                 row1[bIdx]   = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2422                 row1[3]      = uchar(0xff);
2423
2424                 int y01 = std::max(0, int(y1[2 * i + 1]) - 16) * ITUR_BT_601_CY;
2425                 row1[6-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2426                 row1[5]      = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2427                 row1[4+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2428                 row1[7]      = uchar(0xff);
2429
2430                 int y10 = std::max(0, int(y2[2 * i]) - 16) * ITUR_BT_601_CY;
2431                 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2432                 row2[1]      = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2433                 row2[bIdx]   = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2434                 row2[3]      = uchar(0xff);
2435
2436                 int y11 = std::max(0, int(y2[2 * i + 1]) - 16) * ITUR_BT_601_CY;
2437                 row2[6-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2438                 row2[5]      = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2439                 row2[4+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2440                 row2[7]      = uchar(0xff);
2441             }
2442         }
2443     }
2444 };
2445
2446 #define MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION (320*240)
2447
2448 template<int bIdx, int uIdx>
2449 inline void cvtYUV420sp2RGB(Mat& _dst, int _stride, const uchar* _y1, const uchar* _uv)
2450 {
2451     YUV420sp2RGB888Invoker<bIdx, uIdx> converter(&_dst, _stride, _y1,  _uv);
2452     if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
2453         parallel_for_(Range(0, _dst.rows/2), converter);
2454     else
2455         converter(Range(0, _dst.rows/2));
2456 }
2457
2458 template<int bIdx, int uIdx>
2459 inline void cvtYUV420sp2RGBA(Mat& _dst, int _stride, const uchar* _y1, const uchar* _uv)
2460 {
2461     YUV420sp2RGBA8888Invoker<bIdx, uIdx> converter(&_dst, _stride, _y1,  _uv);
2462     if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
2463         parallel_for_(Range(0, _dst.rows/2), converter);
2464     else
2465         converter(Range(0, _dst.rows/2));
2466 }
2467
2468 template<int bIdx>
2469 inline void cvtYUV420p2RGB(Mat& _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int ustepIdx, int vstepIdx)
2470 {
2471     YUV420p2RGB888Invoker<bIdx> converter(&_dst, _stride, _y1,  _u, _v, ustepIdx, vstepIdx);
2472     if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
2473         parallel_for_(Range(0, _dst.rows/2), converter);
2474     else
2475         converter(Range(0, _dst.rows/2));
2476 }
2477
2478 template<int bIdx>
2479 inline void cvtYUV420p2RGBA(Mat& _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int ustepIdx, int vstepIdx)
2480 {
2481     YUV420p2RGBA8888Invoker<bIdx> converter(&_dst, _stride, _y1,  _u, _v, ustepIdx, vstepIdx);
2482     if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
2483         parallel_for_(Range(0, _dst.rows/2), converter);
2484     else
2485         converter(Range(0, _dst.rows/2));
2486 }
2487
2488 ///////////////////////////////////// RGB -> YUV420p /////////////////////////////////////
2489
2490 template<int bIdx>
2491 struct RGB888toYUV420pInvoker: public ParallelLoopBody
2492 {
2493     RGB888toYUV420pInvoker( const Mat& src, Mat* dst, const int uIdx )
2494         : src_(src),
2495           dst_(dst),
2496           uIdx_(uIdx) { }
2497
2498     void operator()(const Range& rowRange) const
2499     {
2500         const int w = src_.cols;
2501         const int h = src_.rows;
2502
2503         const int cn = src_.channels();
2504         for( int i = rowRange.start; i < rowRange.end; i++ )
2505         {
2506             const uchar* row0 = src_.ptr<uchar>(2 * i);
2507             const uchar* row1 = src_.ptr<uchar>(2 * i + 1);
2508
2509             uchar* y = dst_->ptr<uchar>(2*i);
2510             uchar* u = dst_->ptr<uchar>(h + i/2) + (i % 2) * (w/2);
2511             uchar* v = dst_->ptr<uchar>(h + (i + h/2)/2) + ((i + h/2) % 2) * (w/2);
2512             if( uIdx_ == 2 ) std::swap(u, v);
2513
2514             for( int j = 0, k = 0; j < w * cn; j += 2 * cn, k++ )
2515             {
2516                 int r00 = row0[2-bIdx + j];      int g00 = row0[1 + j];      int b00 = row0[bIdx + j];
2517                 int r01 = row0[2-bIdx + cn + j]; int g01 = row0[1 + cn + j]; int b01 = row0[bIdx + cn + j];
2518                 int r10 = row1[2-bIdx + j];      int g10 = row1[1 + j];      int b10 = row1[bIdx + j];
2519                 int r11 = row1[2-bIdx + cn + j]; int g11 = row1[1 + cn + j]; int b11 = row1[bIdx + cn + j];
2520
2521                 const int shifted16 = (16 << ITUR_BT_601_SHIFT);
2522                 const int halfShift = (1 << (ITUR_BT_601_SHIFT - 1));
2523                 int y00 = ITUR_BT_601_CRY * r00 + ITUR_BT_601_CGY * g00 + ITUR_BT_601_CBY * b00 + halfShift + shifted16;
2524                 int y01 = ITUR_BT_601_CRY * r01 + ITUR_BT_601_CGY * g01 + ITUR_BT_601_CBY * b01 + halfShift + shifted16;
2525                 int y10 = ITUR_BT_601_CRY * r10 + ITUR_BT_601_CGY * g10 + ITUR_BT_601_CBY * b10 + halfShift + shifted16;
2526                 int y11 = ITUR_BT_601_CRY * r11 + ITUR_BT_601_CGY * g11 + ITUR_BT_601_CBY * b11 + halfShift + shifted16;
2527
2528                 y[2*k + 0]            = saturate_cast<uchar>(y00 >> ITUR_BT_601_SHIFT);
2529                 y[2*k + 1]            = saturate_cast<uchar>(y01 >> ITUR_BT_601_SHIFT);
2530                 y[2*k + dst_->step + 0] = saturate_cast<uchar>(y10 >> ITUR_BT_601_SHIFT);
2531                 y[2*k + dst_->step + 1] = saturate_cast<uchar>(y11 >> ITUR_BT_601_SHIFT);
2532
2533                 const int shifted128 = (128 << ITUR_BT_601_SHIFT);
2534                 int u00 = ITUR_BT_601_CRU * r00 + ITUR_BT_601_CGU * g00 + ITUR_BT_601_CBU * b00 + halfShift + shifted128;
2535                 int v00 = ITUR_BT_601_CBU * r00 + ITUR_BT_601_CGV * g00 + ITUR_BT_601_CBV * b00 + halfShift + shifted128;
2536
2537                 u[k] = saturate_cast<uchar>(u00 >> ITUR_BT_601_SHIFT);
2538                 v[k] = saturate_cast<uchar>(v00 >> ITUR_BT_601_SHIFT);
2539             }
2540         }
2541     }
2542
2543     static bool isFit( const Mat& src )
2544     {
2545         return (src.total() >= 320*240);
2546     }
2547
2548 private:
2549     RGB888toYUV420pInvoker& operator=(const RGB888toYUV420pInvoker&);
2550
2551     const Mat& src_;
2552     Mat* const dst_;
2553     const int uIdx_;
2554 };
2555
2556 template<int bIdx, int uIdx>
2557 static void cvtRGBtoYUV420p(const Mat& src, Mat& dst)
2558 {
2559     RGB888toYUV420pInvoker<bIdx> colorConverter(src, &dst, uIdx);
2560     if( RGB888toYUV420pInvoker<bIdx>::isFit(src) )
2561         parallel_for_(Range(0, src.rows/2), colorConverter);
2562     else
2563         colorConverter(Range(0, src.rows/2));
2564 }
2565
2566 ///////////////////////////////////// YUV422 -> RGB /////////////////////////////////////
2567
2568 template<int bIdx, int uIdx, int yIdx>
2569 struct YUV422toRGB888Invoker : ParallelLoopBody
2570 {
2571     Mat* dst;
2572     const uchar* src;
2573     int width, stride;
2574
2575     YUV422toRGB888Invoker(Mat* _dst, int _stride, const uchar* _yuv)
2576         : dst(_dst), src(_yuv), width(_dst->cols), stride(_stride) {}
2577
2578     void operator()(const Range& range) const
2579     {
2580         int rangeBegin = range.start;
2581         int rangeEnd = range.end;
2582
2583         const int uidx = 1 - yIdx + uIdx * 2;
2584         const int vidx = (2 + uidx) % 4;
2585         const uchar* yuv_src = src + rangeBegin * stride;
2586
2587         for (int j = rangeBegin; j < rangeEnd; j++, yuv_src += stride)
2588         {
2589             uchar* row = dst->ptr<uchar>(j);
2590
2591             for (int i = 0; i < 2 * width; i += 4, row += 6)
2592             {
2593                 int u = int(yuv_src[i + uidx]) - 128;
2594                 int v = int(yuv_src[i + vidx]) - 128;
2595
2596                 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2597                 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2598                 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2599
2600                 int y00 = std::max(0, int(yuv_src[i + yIdx]) - 16) * ITUR_BT_601_CY;
2601                 row[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2602                 row[1]      = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2603                 row[bIdx]   = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2604
2605                 int y01 = std::max(0, int(yuv_src[i + yIdx + 2]) - 16) * ITUR_BT_601_CY;
2606                 row[5-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2607                 row[4]      = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2608                 row[3+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2609             }
2610         }
2611     }
2612 };
2613
2614 template<int bIdx, int uIdx, int yIdx>
2615 struct YUV422toRGBA8888Invoker : ParallelLoopBody
2616 {
2617     Mat* dst;
2618     const uchar* src;
2619     int width, stride;
2620
2621     YUV422toRGBA8888Invoker(Mat* _dst, int _stride, const uchar* _yuv)
2622         : dst(_dst), src(_yuv), width(_dst->cols), stride(_stride) {}
2623
2624     void operator()(const Range& range) const
2625     {
2626         int rangeBegin = range.start;
2627         int rangeEnd = range.end;
2628
2629         const int uidx = 1 - yIdx + uIdx * 2;
2630         const int vidx = (2 + uidx) % 4;
2631         const uchar* yuv_src = src + rangeBegin * stride;
2632
2633         for (int j = rangeBegin; j < rangeEnd; j++, yuv_src += stride)
2634         {
2635             uchar* row = dst->ptr<uchar>(j);
2636
2637             for (int i = 0; i < 2 * width; i += 4, row += 8)
2638             {
2639                 int u = int(yuv_src[i + uidx]) - 128;
2640                 int v = int(yuv_src[i + vidx]) - 128;
2641
2642                 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2643                 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2644                 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2645
2646                 int y00 = std::max(0, int(yuv_src[i + yIdx]) - 16) * ITUR_BT_601_CY;
2647                 row[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2648                 row[1]      = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2649                 row[bIdx]   = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2650                 row[3]      = uchar(0xff);
2651
2652                 int y01 = std::max(0, int(yuv_src[i + yIdx + 2]) - 16) * ITUR_BT_601_CY;
2653                 row[6-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2654                 row[5]      = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2655                 row[4+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2656                 row[7]      = uchar(0xff);
2657             }
2658         }
2659     }
2660 };
2661
2662 #define MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION (320*240)
2663
2664 template<int bIdx, int uIdx, int yIdx>
2665 inline void cvtYUV422toRGB(Mat& _dst, int _stride, const uchar* _yuv)
2666 {
2667     YUV422toRGB888Invoker<bIdx, uIdx, yIdx> converter(&_dst, _stride, _yuv);
2668     if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION)
2669         parallel_for_(Range(0, _dst.rows), converter);
2670     else
2671         converter(Range(0, _dst.rows));
2672 }
2673
2674 template<int bIdx, int uIdx, int yIdx>
2675 inline void cvtYUV422toRGBA(Mat& _dst, int _stride, const uchar* _yuv)
2676 {
2677     YUV422toRGBA8888Invoker<bIdx, uIdx, yIdx> converter(&_dst, _stride, _yuv);
2678     if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION)
2679         parallel_for_(Range(0, _dst.rows), converter);
2680     else
2681         converter(Range(0, _dst.rows));
2682 }
2683
2684 /////////////////////////// RGBA <-> mRGBA (alpha premultiplied) //////////////
2685
2686 template<typename _Tp>
2687 struct RGBA2mRGBA
2688 {
2689     typedef _Tp channel_type;
2690
2691     void operator()(const _Tp* src, _Tp* dst, int n) const
2692     {
2693         _Tp max_val  = ColorChannel<_Tp>::max();
2694         _Tp half_val = ColorChannel<_Tp>::half();
2695         for( int i = 0; i < n; i++ )
2696         {
2697             _Tp v0 = *src++;
2698             _Tp v1 = *src++;
2699             _Tp v2 = *src++;
2700             _Tp v3 = *src++;
2701
2702             *dst++ = (v0 * v3 + half_val) / max_val;
2703             *dst++ = (v1 * v3 + half_val) / max_val;
2704             *dst++ = (v2 * v3 + half_val) / max_val;
2705             *dst++ = v3;
2706         }
2707     }
2708 };
2709
2710
2711 template<typename _Tp>
2712 struct mRGBA2RGBA
2713 {
2714     typedef _Tp channel_type;
2715
2716     void operator()(const _Tp* src, _Tp* dst, int n) const
2717     {
2718         _Tp max_val = ColorChannel<_Tp>::max();
2719         for( int i = 0; i < n; i++ )
2720         {
2721             _Tp v0 = *src++;
2722             _Tp v1 = *src++;
2723             _Tp v2 = *src++;
2724             _Tp v3 = *src++;
2725             _Tp v3_half = v3 / 2;
2726
2727             *dst++ = (v3==0)? 0 : (v0 * max_val + v3_half) / v3;
2728             *dst++ = (v3==0)? 0 : (v1 * max_val + v3_half) / v3;
2729             *dst++ = (v3==0)? 0 : (v2 * max_val + v3_half) / v3;
2730             *dst++ = v3;
2731         }
2732     }
2733 };
2734
2735 #ifdef HAVE_OPENCL
2736
2737 static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
2738 {
2739     bool ok = false;
2740     UMat src = _src.getUMat(), dst;
2741     Size sz = src.size(), dstSz = sz;
2742     int scn = src.channels(), depth = src.depth(), bidx;
2743     int dims = 2, stripeSize = 1;
2744     ocl::Kernel k;
2745
2746     if (depth != CV_8U && depth != CV_16U && depth != CV_32F)
2747         return false;
2748
2749     ocl::Device dev = ocl::Device::getDefault();
2750     int pxPerWIy = dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU) ? 4 : 1;
2751
2752     size_t globalsize[] = { src.cols, (src.rows + pxPerWIy - 1) / pxPerWIy };
2753     cv::String opts = format("-D depth=%d -D scn=%d -D PIX_PER_WI_Y=%d ",
2754                              depth, scn, pxPerWIy);
2755
2756     switch (code)
2757     {
2758     case COLOR_BGR2BGRA: case COLOR_RGB2BGRA: case COLOR_BGRA2BGR:
2759     case COLOR_RGBA2BGR: case COLOR_RGB2BGR: case COLOR_BGRA2RGBA:
2760     {
2761         CV_Assert(scn == 3 || scn == 4);
2762         dcn = code == COLOR_BGR2BGRA || code == COLOR_RGB2BGRA || code == COLOR_BGRA2RGBA ? 4 : 3;
2763         bool reverse = !(code == COLOR_BGR2BGRA || code == COLOR_BGRA2BGR);
2764         k.create("RGB", ocl::imgproc::cvtcolor_oclsrc,
2765                  opts + format("-D dcn=%d -D bidx=0 -D %s", dcn,
2766                         reverse ? "REVERSE" : "ORDER"));
2767         break;
2768     }
2769     case COLOR_BGR5652BGR: case COLOR_BGR5552BGR: case COLOR_BGR5652RGB: case COLOR_BGR5552RGB:
2770     case COLOR_BGR5652BGRA: case COLOR_BGR5552BGRA: case COLOR_BGR5652RGBA: case COLOR_BGR5552RGBA:
2771     {
2772         dcn = code == COLOR_BGR5652BGRA || code == COLOR_BGR5552BGRA || code == COLOR_BGR5652RGBA || code == COLOR_BGR5552RGBA ? 4 : 3;
2773         CV_Assert((dcn == 3 || dcn == 4) && scn == 2 && depth == CV_8U);
2774         bidx = code == COLOR_BGR5652BGR || code == COLOR_BGR5552BGR ||
2775             code == COLOR_BGR5652BGRA || code == COLOR_BGR5552BGRA ? 0 : 2;
2776         int greenbits = code == COLOR_BGR5652BGR || code == COLOR_BGR5652RGB ||
2777             code == COLOR_BGR5652BGRA || code == COLOR_BGR5652RGBA ? 6 : 5;
2778         k.create("RGB5x52RGB", ocl::imgproc::cvtcolor_oclsrc,
2779                  opts + format("-D dcn=%d -D bidx=%d -D greenbits=%d", dcn, bidx, greenbits));
2780         break;
2781     }
2782     case COLOR_BGR2BGR565: case COLOR_BGR2BGR555: case COLOR_RGB2BGR565: case COLOR_RGB2BGR555:
2783     case COLOR_BGRA2BGR565: case COLOR_BGRA2BGR555: case COLOR_RGBA2BGR565: case COLOR_RGBA2BGR555:
2784     {
2785         CV_Assert((scn == 3 || scn == 4) && depth == CV_8U );
2786         bidx = code == COLOR_BGR2BGR565 || code == COLOR_BGR2BGR555 ||
2787             code == COLOR_BGRA2BGR565 || code == COLOR_BGRA2BGR555 ? 0 : 2;
2788         int greenbits = code == COLOR_BGR2BGR565 || code == COLOR_RGB2BGR565 ||
2789             code == COLOR_BGRA2BGR565 || code == COLOR_RGBA2BGR565 ? 6 : 5;
2790         dcn = 2;
2791         k.create("RGB2RGB5x5", ocl::imgproc::cvtcolor_oclsrc,
2792                  opts + format("-D dcn=2 -D bidx=%d -D greenbits=%d", bidx, greenbits));
2793         break;
2794     }
2795     case COLOR_BGR5652GRAY: case COLOR_BGR5552GRAY:
2796     {
2797         CV_Assert(scn == 2 && depth == CV_8U);
2798         dcn = 1;
2799         int greenbits = code == COLOR_BGR5652GRAY ? 6 : 5;
2800         k.create("BGR5x52Gray", ocl::imgproc::cvtcolor_oclsrc,
2801                  opts + format("-D dcn=1 -D bidx=0 -D greenbits=%d", greenbits));
2802         break;
2803     }
2804     case COLOR_GRAY2BGR565: case COLOR_GRAY2BGR555:
2805     {
2806         CV_Assert(scn == 1 && depth == CV_8U);
2807         dcn = 2;
2808         int greenbits = code == COLOR_GRAY2BGR565 ? 6 : 5;
2809         k.create("Gray2BGR5x5", ocl::imgproc::cvtcolor_oclsrc,
2810                  opts + format("-D dcn=2 -D bidx=0 -D greenbits=%d", greenbits));
2811         break;
2812     }
2813     case COLOR_BGR2GRAY: case COLOR_BGRA2GRAY:
2814     case COLOR_RGB2GRAY: case COLOR_RGBA2GRAY:
2815     {
2816         CV_Assert(scn == 3 || scn == 4);
2817         bidx = code == COLOR_BGR2GRAY || code == COLOR_BGRA2GRAY ? 0 : 2;
2818         dcn = 1;
2819         k.create("RGB2Gray", ocl::imgproc::cvtcolor_oclsrc,
2820                  opts + format("-D dcn=1 -D bidx=%d -D STRIPE_SIZE=%d",
2821                                bidx, stripeSize));
2822         globalsize[0] = (src.cols + stripeSize-1)/stripeSize;
2823         break;
2824     }
2825     case COLOR_GRAY2BGR:
2826     case COLOR_GRAY2BGRA:
2827     {
2828         CV_Assert(scn == 1);
2829         dcn = code == COLOR_GRAY2BGRA ? 4 : 3;
2830         k.create("Gray2RGB", ocl::imgproc::cvtcolor_oclsrc,
2831                  opts + format("-D bidx=0 -D dcn=%d", dcn));
2832         break;
2833     }
2834     case COLOR_BGR2YUV:
2835     case COLOR_RGB2YUV:
2836     {
2837         CV_Assert(scn == 3 || scn == 4);
2838         bidx = code == COLOR_RGB2YUV ? 0 : 2;
2839         dcn = 3;
2840         k.create("RGB2YUV", ocl::imgproc::cvtcolor_oclsrc,
2841                  opts + format("-D dcn=3 -D bidx=%d", bidx));
2842         break;
2843     }
2844     case COLOR_YUV2BGR:
2845     case COLOR_YUV2RGB:
2846     {
2847         if(dcn < 0) dcn = 3;
2848         CV_Assert(dcn == 3 || dcn == 4);
2849         bidx = code == COLOR_YUV2RGB ? 0 : 2;
2850         k.create("YUV2RGB", ocl::imgproc::cvtcolor_oclsrc,
2851                  opts + format("-D dcn=%d -D bidx=%d", dcn, bidx));
2852         break;
2853     }
2854     case COLOR_YUV2RGB_NV12: case COLOR_YUV2BGR_NV12:
2855     case COLOR_YUV2RGBA_NV12: case COLOR_YUV2BGRA_NV12:
2856     {
2857         CV_Assert( scn == 1 );
2858         CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
2859         dcn  = code == COLOR_YUV2BGRA_NV12 || code == COLOR_YUV2RGBA_NV12 ? 4 : 3;
2860         bidx = code == COLOR_YUV2BGRA_NV12 || code == COLOR_YUV2BGR_NV12 ? 0 : 2;
2861
2862         dstSz = Size(sz.width, sz.height * 2 / 3);
2863         k.create("YUV2RGB_NV12", ocl::imgproc::cvtcolor_oclsrc,
2864                  opts + format("-D dcn=%d -D bidx=%d", dcn, bidx));
2865         break;
2866     }
2867     case COLOR_BGR2YCrCb:
2868     case COLOR_RGB2YCrCb:
2869     {
2870         CV_Assert(scn == 3 || scn == 4);
2871         bidx = code == COLOR_BGR2YCrCb ? 0 : 2;
2872         dcn = 3;
2873         k.create("RGB2YCrCb", ocl::imgproc::cvtcolor_oclsrc,
2874                  opts + format("-D dcn=3 -D bidx=%d", bidx));
2875         break;
2876     }
2877     case COLOR_YCrCb2BGR:
2878     case COLOR_YCrCb2RGB:
2879     {
2880         if( dcn <= 0 )
2881             dcn = 3;
2882         CV_Assert(scn == 3 && (dcn == 3 || dcn == 4));
2883         bidx = code == COLOR_YCrCb2BGR ? 0 : 2;
2884         k.create("YCrCb2RGB", ocl::imgproc::cvtcolor_oclsrc,
2885                  opts + format("-D dcn=%d -D bidx=%d", dcn, bidx));
2886         break;
2887     }
2888     case COLOR_BGR2XYZ: case COLOR_RGB2XYZ:
2889     {
2890         CV_Assert(scn == 3 || scn == 4);
2891         bidx = code == COLOR_BGR2XYZ ? 0 : 2;
2892
2893         UMat c;
2894         if (depth == CV_32F)
2895         {
2896             float coeffs[] =
2897             {
2898                 0.412453f, 0.357580f, 0.180423f,
2899                 0.212671f, 0.715160f, 0.072169f,
2900                 0.019334f, 0.119193f, 0.950227f
2901             };
2902             if (bidx == 0)
2903             {
2904                 std::swap(coeffs[0], coeffs[2]);
2905                 std::swap(coeffs[3], coeffs[5]);
2906                 std::swap(coeffs[6], coeffs[8]);
2907             }
2908             Mat(1, 9, CV_32FC1, &coeffs[0]).copyTo(c);
2909         }
2910         else
2911         {
2912             int coeffs[] =
2913             {
2914                 1689,    1465,    739,
2915                 871,     2929,    296,
2916                 79,      488,     3892
2917             };
2918             if (bidx == 0)
2919             {
2920                 std::swap(coeffs[0], coeffs[2]);
2921                 std::swap(coeffs[3], coeffs[5]);
2922                 std::swap(coeffs[6], coeffs[8]);
2923             }
2924             Mat(1, 9, CV_32SC1, &coeffs[0]).copyTo(c);
2925         }
2926
2927         _dst.create(dstSz, CV_MAKETYPE(depth, 3));
2928         dst = _dst.getUMat();
2929
2930         k.create("RGB2XYZ", ocl::imgproc::cvtcolor_oclsrc,
2931                  opts + format("-D dcn=3 -D bidx=%d", bidx));
2932         if (k.empty())
2933             return false;
2934         k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst), ocl::KernelArg::PtrReadOnly(c));
2935         return k.run(2, globalsize, 0, false);
2936     }
2937     case COLOR_XYZ2BGR: case COLOR_XYZ2RGB:
2938     {
2939         if (dcn <= 0)
2940             dcn = 3;
2941         CV_Assert(scn == 3 && (dcn == 3 || dcn == 4));
2942         bidx = code == COLOR_XYZ2BGR ? 0 : 2;
2943
2944         UMat c;
2945         if (depth == CV_32F)
2946         {
2947             float coeffs[] =
2948             {
2949                 3.240479f, -1.53715f, -0.498535f,
2950                 -0.969256f, 1.875991f, 0.041556f,
2951                 0.055648f, -0.204043f, 1.057311f
2952             };
2953             if (bidx == 0)
2954             {
2955                 std::swap(coeffs[0], coeffs[6]);
2956                 std::swap(coeffs[1], coeffs[7]);
2957                 std::swap(coeffs[2], coeffs[8]);
2958             }
2959             Mat(1, 9, CV_32FC1, &coeffs[0]).copyTo(c);
2960         }
2961         else
2962         {
2963             int coeffs[] =
2964             {
2965                 13273,  -6296,  -2042,
2966                 -3970,   7684,    170,
2967                   228,   -836,   4331
2968             };
2969             if (bidx == 0)
2970             {
2971                 std::swap(coeffs[0], coeffs[6]);
2972                 std::swap(coeffs[1], coeffs[7]);
2973                 std::swap(coeffs[2], coeffs[8]);
2974             }
2975             Mat(1, 9, CV_32SC1, &coeffs[0]).copyTo(c);
2976         }
2977
2978         _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
2979         dst = _dst.getUMat();
2980
2981         k.create("XYZ2RGB", ocl::imgproc::cvtcolor_oclsrc,
2982                  opts + format("-D dcn=%d -D bidx=%d", dcn, bidx));
2983         if (k.empty())
2984             return false;
2985         k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst), ocl::KernelArg::PtrReadOnly(c));
2986         return k.run(2, globalsize, 0, false);
2987     }
2988     case COLOR_BGR2HSV: case COLOR_RGB2HSV: case COLOR_BGR2HSV_FULL: case COLOR_RGB2HSV_FULL:
2989     case COLOR_BGR2HLS: case COLOR_RGB2HLS: case COLOR_BGR2HLS_FULL: case COLOR_RGB2HLS_FULL:
2990     {
2991         CV_Assert((scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F));
2992         bidx = code == COLOR_BGR2HSV || code == COLOR_BGR2HLS ||
2993             code == COLOR_BGR2HSV_FULL || code == COLOR_BGR2HLS_FULL ? 0 : 2;
2994         int hrange = depth == CV_32F ? 360 : code == COLOR_BGR2HSV || code == COLOR_RGB2HSV ||
2995             code == COLOR_BGR2HLS || code == COLOR_RGB2HLS ? 180 : 256;
2996         bool is_hsv = code == COLOR_BGR2HSV || code == COLOR_RGB2HSV || code == COLOR_BGR2HSV_FULL || code == COLOR_RGB2HSV_FULL;
2997         String kernelName = String("RGB2") + (is_hsv ? "HSV" : "HLS");
2998         dcn = 3;
2999
3000         if (is_hsv && depth == CV_8U)
3001         {
3002             static UMat sdiv_data;
3003             static UMat hdiv_data180;
3004             static UMat hdiv_data256;
3005             static int sdiv_table[256];
3006             static int hdiv_table180[256];
3007             static int hdiv_table256[256];
3008             static volatile bool initialized180 = false, initialized256 = false;
3009             volatile bool & initialized = hrange == 180 ? initialized180 : initialized256;
3010
3011             if (!initialized)
3012             {
3013                 int * const hdiv_table = hrange == 180 ? hdiv_table180 : hdiv_table256, hsv_shift = 12;
3014                 UMat & hdiv_data = hrange == 180 ? hdiv_data180 : hdiv_data256;
3015
3016                 sdiv_table[0] = hdiv_table180[0] = hdiv_table256[0] = 0;
3017
3018                 int v = 255 << hsv_shift;
3019                 if (!initialized180 && !initialized256)
3020                 {
3021                     for(int i = 1; i < 256; i++ )
3022                         sdiv_table[i] = saturate_cast<int>(v/(1.*i));
3023                     Mat(1, 256, CV_32SC1, sdiv_table).copyTo(sdiv_data);
3024                 }
3025
3026                 v = hrange << hsv_shift;
3027                 for (int i = 1; i < 256; i++ )
3028                     hdiv_table[i] = saturate_cast<int>(v/(6.*i));
3029
3030                 Mat(1, 256, CV_32SC1, hdiv_table).copyTo(hdiv_data);
3031                 initialized = true;
3032             }
3033
3034             _dst.create(dstSz, CV_8UC3);
3035             dst = _dst.getUMat();
3036
3037             k.create("RGB2HSV", ocl::imgproc::cvtcolor_oclsrc,
3038                      opts + format("-D hrange=%d -D bidx=%d -D dcn=3",
3039                                    hrange, bidx));
3040             if (k.empty())
3041                 return false;
3042
3043             k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst),
3044                    ocl::KernelArg::PtrReadOnly(sdiv_data), hrange == 256 ? ocl::KernelArg::PtrReadOnly(hdiv_data256) :
3045                                                                        ocl::KernelArg::PtrReadOnly(hdiv_data180));
3046
3047             return k.run(2, globalsize, NULL, false);
3048         }
3049         else
3050             k.create(kernelName.c_str(), ocl::imgproc::cvtcolor_oclsrc,
3051                      opts + format("-D hscale=%ff -D bidx=%d -D dcn=3",
3052                                    hrange*(1.f/360.f), bidx));
3053         break;
3054     }
3055     case COLOR_HSV2BGR: case COLOR_HSV2RGB: case COLOR_HSV2BGR_FULL: case COLOR_HSV2RGB_FULL:
3056     case COLOR_HLS2BGR: case COLOR_HLS2RGB: case COLOR_HLS2BGR_FULL: case COLOR_HLS2RGB_FULL:
3057     {
3058         if (dcn <= 0)
3059             dcn = 3;
3060         CV_Assert(scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F));
3061         bidx = code == COLOR_HSV2BGR || code == COLOR_HLS2BGR ||
3062             code == COLOR_HSV2BGR_FULL || code == COLOR_HLS2BGR_FULL ? 0 : 2;
3063         int hrange = depth == CV_32F ? 360 : code == COLOR_HSV2BGR || code == COLOR_HSV2RGB ||
3064             code == COLOR_HLS2BGR || code == COLOR_HLS2RGB ? 180 : 255;
3065         bool is_hsv = code == COLOR_HSV2BGR || code == COLOR_HSV2RGB ||
3066                 code == COLOR_HSV2BGR_FULL || code == COLOR_HSV2RGB_FULL;
3067
3068         String kernelName = String(is_hsv ? "HSV" : "HLS") + "2RGB";
3069         k.create(kernelName.c_str(), ocl::imgproc::cvtcolor_oclsrc,
3070                  opts + format("-D dcn=%d -D bidx=%d -D hrange=%d -D hscale=%ff",
3071                                dcn, bidx, hrange, 6.f/hrange));
3072         break;
3073     }
3074     case COLOR_RGBA2mRGBA: case COLOR_mRGBA2RGBA:
3075     {
3076         CV_Assert(scn == 4 && depth == CV_8U);
3077         dcn = 4;
3078
3079         k.create(code == COLOR_RGBA2mRGBA ? "RGBA2mRGBA" : "mRGBA2RGBA", ocl::imgproc::cvtcolor_oclsrc,
3080                  opts + "-D dcn=4 -D bidx=3");
3081         break;
3082     }
3083     case CV_BGR2Lab: case CV_RGB2Lab: case CV_LBGR2Lab: case CV_LRGB2Lab:
3084     case CV_BGR2Luv: case CV_RGB2Luv: case CV_LBGR2Luv: case CV_LRGB2Luv:
3085     {
3086         CV_Assert( (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) );
3087
3088         bidx = code == CV_BGR2Lab || code == CV_LBGR2Lab || code == CV_BGR2Luv || code == CV_LBGR2Luv ? 0 : 2;
3089         bool srgb = code == CV_BGR2Lab || code == CV_RGB2Lab || code == CV_RGB2Luv || code == CV_BGR2Luv;
3090         bool lab = code == CV_BGR2Lab || code == CV_RGB2Lab || code == CV_LBGR2Lab || code == CV_LRGB2Lab;
3091         float un, vn;
3092         dcn = 3;
3093
3094         k.create(format("BGR2%s", lab ? "Lab" : "Luv").c_str(),
3095                  ocl::imgproc::cvtcolor_oclsrc,
3096                  opts + format("-D dcn=%d -D bidx=%d%s",
3097                                dcn, bidx, srgb ? " -D SRGB" : ""));
3098         if (k.empty())
3099             return false;
3100
3101         initLabTabs();
3102
3103         _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
3104         dst = _dst.getUMat();
3105
3106         ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
3107                 dstarg = ocl::KernelArg::WriteOnly(dst);
3108
3109         if (depth == CV_8U && lab)
3110         {
3111             static UMat usRGBGammaTab, ulinearGammaTab, uLabCbrtTab, ucoeffs;
3112
3113             if (srgb && usRGBGammaTab.empty())
3114                 Mat(1, 256, CV_16UC1, sRGBGammaTab_b).copyTo(usRGBGammaTab);
3115             else if (ulinearGammaTab.empty())
3116                 Mat(1, 256, CV_16UC1, linearGammaTab_b).copyTo(ulinearGammaTab);
3117             if (uLabCbrtTab.empty())
3118                 Mat(1, LAB_CBRT_TAB_SIZE_B, CV_16UC1, LabCbrtTab_b).copyTo(uLabCbrtTab);
3119
3120             {
3121                 int coeffs[9];
3122                 const float * const _coeffs = sRGB2XYZ_D65, * const _whitept = D65;
3123                 const float scale[] =
3124                 {
3125                     (1 << lab_shift)/_whitept[0],
3126                     (float)(1 << lab_shift),
3127                     (1 << lab_shift)/_whitept[2]
3128                 };
3129
3130                 for (int i = 0; i < 3; i++ )
3131                 {
3132                     coeffs[i*3+(bidx^2)] = cvRound(_coeffs[i*3]*scale[i]);
3133                     coeffs[i*3+1] = cvRound(_coeffs[i*3+1]*scale[i]);
3134                     coeffs[i*3+bidx] = cvRound(_coeffs[i*3+2]*scale[i]);
3135
3136                     CV_Assert( coeffs[i] >= 0 && coeffs[i*3+1] >= 0 && coeffs[i*3+2] >= 0 &&
3137                               coeffs[i*3] + coeffs[i*3+1] + coeffs[i*3+2] < 2*(1 << lab_shift) );
3138                 }
3139                 Mat(1, 9, CV_32SC1, coeffs).copyTo(ucoeffs);
3140             }
3141
3142             const int Lscale = (116*255+50)/100;
3143             const int Lshift = -((16*255*(1 << lab_shift2) + 50)/100);
3144
3145             k.args(srcarg, dstarg,
3146                    ocl::KernelArg::PtrReadOnly(srgb ? usRGBGammaTab : ulinearGammaTab),
3147                    ocl::KernelArg::PtrReadOnly(uLabCbrtTab), ocl::KernelArg::PtrReadOnly(ucoeffs),
3148                    Lscale, Lshift);
3149         }
3150         else
3151         {
3152             static UMat usRGBGammaTab, ucoeffs, uLabCbrtTab;
3153
3154             if (srgb && usRGBGammaTab.empty())
3155                 Mat(1, GAMMA_TAB_SIZE * 4, CV_32FC1, sRGBGammaTab).copyTo(usRGBGammaTab);
3156             if (!lab && uLabCbrtTab.empty())
3157                 Mat(1, LAB_CBRT_TAB_SIZE * 4, CV_32FC1, LabCbrtTab).copyTo(uLabCbrtTab);
3158
3159             {
3160                 float coeffs[9];
3161                 const float * const _coeffs = sRGB2XYZ_D65, * const _whitept = D65;
3162                 float scale[] = { 1.0f / _whitept[0], 1.0f, 1.0f / _whitept[2] };
3163
3164                 for (int i = 0; i < 3; i++)
3165                 {
3166                     int j = i * 3;
3167                     coeffs[j + (bidx ^ 2)] = _coeffs[j] * (lab ? scale[i] : 1);
3168                     coeffs[j + 1] = _coeffs[j + 1] * (lab ? scale[i] : 1);
3169                     coeffs[j + bidx] = _coeffs[j + 2] * (lab ? scale[i] : 1);
3170
3171                     CV_Assert( coeffs[j] >= 0 && coeffs[j + 1] >= 0 && coeffs[j + 2] >= 0 &&
3172                                coeffs[j] + coeffs[j + 1] + coeffs[j + 2] < 1.5f*(lab ? LabCbrtTabScale : 1) );
3173                 }
3174
3175                 float d = 1.f/(_whitept[0] + _whitept[1]*15 + _whitept[2]*3);
3176                 un = 13*4*_whitept[0]*d;
3177                 vn = 13*9*_whitept[1]*d;
3178
3179                 Mat(1, 9, CV_32FC1, coeffs).copyTo(ucoeffs);
3180             }
3181
3182             float _1_3 = 1.0f / 3.0f, _a = 16.0f / 116.0f;
3183             ocl::KernelArg ucoeffsarg = ocl::KernelArg::PtrReadOnly(ucoeffs);
3184
3185             if (lab)
3186             {
3187                 if (srgb)
3188                     k.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(usRGBGammaTab),
3189                            ucoeffsarg, _1_3, _a);
3190                 else
3191                     k.args(srcarg, dstarg, ucoeffsarg, _1_3, _a);
3192             }
3193             else
3194             {
3195                 ocl::KernelArg LabCbrtTabarg = ocl::KernelArg::PtrReadOnly(uLabCbrtTab);
3196                 if (srgb)
3197                     k.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(usRGBGammaTab),
3198                            LabCbrtTabarg, ucoeffsarg, un, vn);
3199                 else
3200                     k.args(srcarg, dstarg, LabCbrtTabarg, ucoeffsarg, un, vn);
3201             }
3202         }
3203
3204         return k.run(dims, globalsize, NULL, false);
3205     }
3206     case CV_Lab2BGR: case CV_Lab2RGB: case CV_Lab2LBGR: case CV_Lab2LRGB:
3207     case CV_Luv2BGR: case CV_Luv2RGB: case CV_Luv2LBGR: case CV_Luv2LRGB:
3208     {
3209         if( dcn <= 0 )
3210             dcn = 3;
3211         CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) );
3212
3213         bidx = code == CV_Lab2BGR || code == CV_Lab2LBGR || code == CV_Luv2BGR || code == CV_Luv2LBGR ? 0 : 2;
3214         bool srgb = code == CV_Lab2BGR || code == CV_Lab2RGB || code == CV_Luv2BGR || code == CV_Luv2RGB;
3215         bool lab = code == CV_Lab2BGR || code == CV_Lab2RGB || code == CV_Lab2LBGR || code == CV_Lab2LRGB;
3216         float un, vn;
3217
3218         k.create(format("%s2BGR", lab ? "Lab" : "Luv").c_str(),
3219                  ocl::imgproc::cvtcolor_oclsrc,
3220                  opts + format("-D dcn=%d -D bidx=%d%s",
3221                                dcn, bidx, srgb ? " -D SRGB" : ""));
3222         if (k.empty())
3223             return false;
3224
3225         initLabTabs();
3226         static UMat ucoeffs, usRGBInvGammaTab;
3227
3228         if (srgb && usRGBInvGammaTab.empty())
3229             Mat(1, GAMMA_TAB_SIZE*4, CV_32FC1, sRGBInvGammaTab).copyTo(usRGBInvGammaTab);
3230
3231         {
3232             float coeffs[9];
3233             const float * const _coeffs = XYZ2sRGB_D65, * const _whitept = D65;
3234
3235             for( int i = 0; i < 3; i++ )
3236             {
3237                 coeffs[i+(bidx^2)*3] = _coeffs[i] * (lab ? _whitept[i] : 1);
3238                 coeffs[i+3] = _coeffs[i+3] * (lab ? _whitept[i] : 1);
3239                 coeffs[i+bidx*3] = _coeffs[i+6] * (lab ? _whitept[i] : 1);
3240             }
3241
3242             float d = 1.f/(_whitept[0] + _whitept[1]*15 + _whitept[2]*3);
3243             un = 4*_whitept[0]*d;
3244             vn = 9*_whitept[1]*d;
3245
3246             Mat(1, 9, CV_32FC1, coeffs).copyTo(ucoeffs);
3247         }
3248
3249         _dst.create(sz, CV_MAKETYPE(depth, dcn));
3250         dst = _dst.getUMat();
3251
3252         float lThresh = 0.008856f * 903.3f;
3253         float fThresh = 7.787f * 0.008856f + 16.0f / 116.0f;
3254
3255         ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
3256                 dstarg = ocl::KernelArg::WriteOnly(dst),
3257                 coeffsarg = ocl::KernelArg::PtrReadOnly(ucoeffs);
3258
3259         if (lab)
3260         {
3261             if (srgb)
3262                 k.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(usRGBInvGammaTab),
3263                        coeffsarg, lThresh, fThresh);
3264             else
3265                 k.args(srcarg, dstarg, coeffsarg, lThresh, fThresh);
3266         }
3267         else
3268         {
3269             if (srgb)
3270                 k.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(usRGBInvGammaTab),
3271                        coeffsarg, un, vn);
3272             else
3273                 k.args(srcarg, dstarg, coeffsarg, un, vn);
3274         }
3275
3276         return k.run(dims, globalsize, NULL, false);
3277     }
3278     default:
3279         break;
3280     }
3281
3282     if( !k.empty() )
3283     {
3284         _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
3285         dst = _dst.getUMat();
3286         k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst));
3287         ok = k.run(dims, globalsize, NULL, false);
3288     }
3289     return ok;
3290 }
3291
3292 #endif
3293
3294 }//namespace cv
3295
3296 //////////////////////////////////////////////////////////////////////////////////////////
3297 //                                   The main function                                  //
3298 //////////////////////////////////////////////////////////////////////////////////////////
3299
3300 void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
3301 {
3302     int stype = _src.type();
3303     int scn = CV_MAT_CN(stype), depth = CV_MAT_DEPTH(stype), bidx;
3304
3305     CV_OCL_RUN( _src.dims() <= 2 && _dst.isUMat() && !(depth == CV_8U && (code == CV_Luv2BGR || code == CV_Luv2RGB)),
3306                 ocl_cvtColor(_src, _dst, code, dcn) )
3307
3308     Mat src = _src.getMat(), dst;
3309     Size sz = src.size();
3310
3311     CV_Assert( depth == CV_8U || depth == CV_16U || depth == CV_32F );
3312
3313     switch( code )
3314     {
3315         case CV_BGR2BGRA: case CV_RGB2BGRA: case CV_BGRA2BGR:
3316         case CV_RGBA2BGR: case CV_RGB2BGR: case CV_BGRA2RGBA:
3317             CV_Assert( scn == 3 || scn == 4 );
3318             dcn = code == CV_BGR2BGRA || code == CV_RGB2BGRA || code == CV_BGRA2RGBA ? 4 : 3;
3319             bidx = code == CV_BGR2BGRA || code == CV_BGRA2BGR ? 0 : 2;
3320
3321             _dst.create( sz, CV_MAKETYPE(depth, dcn));
3322             dst = _dst.getMat();
3323
3324 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3325             if( code == CV_BGR2BGRA)
3326             {
3327                 if ( CvtColorIPPLoop(src, dst, IPPReorderFunctor(ippiSwapChannelsC3C4RTab[depth], 0, 1, 2)) )
3328                     return;
3329                 setIppErrorStatus();
3330             }
3331             else if( code == CV_BGRA2BGR )
3332             {
3333                 if ( CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiCopyAC4C3RTab[depth])) )
3334                     return;
3335                 setIppErrorStatus();
3336             }
3337             else if( code == CV_BGR2RGBA )
3338             {
3339                 if( CvtColorIPPLoop(src, dst, IPPReorderFunctor(ippiSwapChannelsC3C4RTab[depth], 2, 1, 0)) )
3340                     return;
3341                 setIppErrorStatus();
3342             }
3343             else if( code == CV_RGBA2BGR )
3344             {
3345                 if( CvtColorIPPLoop(src, dst, IPPReorderFunctor(ippiSwapChannelsC4C3RTab[depth], 2, 1, 0)) )
3346                     return;
3347                 setIppErrorStatus();
3348             }
3349             else if( code == CV_RGB2BGR )
3350             {
3351                 if( CvtColorIPPLoopCopy(src, dst, IPPReorderFunctor(ippiSwapChannelsC3RTab[depth], 2, 1, 0)) )
3352                     return;
3353                 setIppErrorStatus();
3354             }
3355 #if IPP_VERSION_X100 >= 801
3356             else if( code == CV_RGBA2BGRA )
3357             {
3358                 if( CvtColorIPPLoopCopy(src, dst, IPPReorderFunctor(ippiSwapChannelsC4RTab[depth], 2, 1, 0)) )
3359                     return;
3360                 setIppErrorStatus();
3361             }
3362 #endif
3363 #endif
3364
3365             if( depth == CV_8U )
3366             {
3367 #ifdef HAVE_TEGRA_OPTIMIZATION
3368                 if(!tegra::cvtBGR2RGB(src, dst, bidx))
3369 #endif
3370                     CvtColorLoop(src, dst, RGB2RGB<uchar>(scn, dcn, bidx));
3371             }
3372             else if( depth == CV_16U )
3373                 CvtColorLoop(src, dst, RGB2RGB<ushort>(scn, dcn, bidx));
3374             else
3375                 CvtColorLoop(src, dst, RGB2RGB<float>(scn, dcn, bidx));
3376             break;
3377
3378         case CV_BGR2BGR565: case CV_BGR2BGR555: case CV_RGB2BGR565: case CV_RGB2BGR555:
3379         case CV_BGRA2BGR565: case CV_BGRA2BGR555: case CV_RGBA2BGR565: case CV_RGBA2BGR555:
3380             CV_Assert( (scn == 3 || scn == 4) && depth == CV_8U );
3381             _dst.create(sz, CV_8UC2);
3382             dst = _dst.getMat();
3383
3384 #if defined(HAVE_IPP) && 0 // breaks OCL accuracy tests
3385             CV_SUPPRESS_DEPRECATED_START
3386
3387             if (code == CV_BGR2BGR565 && scn == 3)
3388             {
3389                 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R)))
3390                     return;
3391                 setIppErrorStatus();
3392             }
3393             else if (code == CV_BGRA2BGR565 && scn == 4)
3394             {
3395                 if (CvtColorIPPLoopCopy(src, dst,
3396                                         IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3397                                         (ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R, 0, 1, 2, depth)))
3398                     return;
3399                 setIppErrorStatus();
3400             }
3401             else if (code == CV_RGB2BGR565 && scn == 3)
3402             {
3403                 if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth],
3404                                                                            (ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R, 2, 1, 0, depth)) )
3405                     return;
3406                 setIppErrorStatus();
3407             }
3408             else if (code == CV_RGBA2BGR565 && scn == 4)
3409             {
3410                 if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3411                                                                            (ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R, 2, 1, 0, depth)) )
3412                     return;
3413                 setIppErrorStatus();
3414             }
3415             CV_SUPPRESS_DEPRECATED_END
3416 #endif
3417
3418 #ifdef HAVE_TEGRA_OPTIMIZATION
3419             if(code == CV_BGR2BGR565 || code == CV_BGRA2BGR565 || code == CV_RGB2BGR565  || code == CV_RGBA2BGR565)
3420                 if(tegra::cvtRGB2RGB565(src, dst, code == CV_RGB2BGR565 || code == CV_RGBA2BGR565 ? 0 : 2))
3421                     break;
3422 #endif
3423
3424             CvtColorLoop(src, dst, RGB2RGB5x5(scn,
3425                       code == CV_BGR2BGR565 || code == CV_BGR2BGR555 ||
3426                       code == CV_BGRA2BGR565 || code == CV_BGRA2BGR555 ? 0 : 2,
3427                       code == CV_BGR2BGR565 || code == CV_RGB2BGR565 ||
3428                       code == CV_BGRA2BGR565 || code == CV_RGBA2BGR565 ? 6 : 5 // green bits
3429                                               ));
3430             break;
3431
3432         case CV_BGR5652BGR: case CV_BGR5552BGR: case CV_BGR5652RGB: case CV_BGR5552RGB:
3433         case CV_BGR5652BGRA: case CV_BGR5552BGRA: case CV_BGR5652RGBA: case CV_BGR5552RGBA:
3434             if(dcn <= 0) dcn = (code==CV_BGR5652BGRA || code==CV_BGR5552BGRA || code==CV_BGR5652RGBA || code==CV_BGR5552RGBA) ? 4 : 3;
3435             CV_Assert( (dcn == 3 || dcn == 4) && scn == 2 && depth == CV_8U );
3436             _dst.create(sz, CV_MAKETYPE(depth, dcn));
3437             dst = _dst.getMat();
3438
3439 #ifdef HAVE_IPP
3440             CV_SUPPRESS_DEPRECATED_START
3441             if (code == CV_BGR5652BGR && dcn == 3)
3442             {
3443                 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R)))
3444                     return;
3445                 setIppErrorStatus();
3446             }
3447             else if (code == CV_BGR5652RGB && dcn == 3)
3448             {
3449                 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R,
3450                                                                        ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)))
3451                     return;
3452                 setIppErrorStatus();
3453             }
3454             else if (code == CV_BGR5652BGRA && dcn == 4)
3455             {
3456                 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R,
3457                                                                        ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)))
3458                     return;
3459                 setIppErrorStatus();
3460             }
3461             else if (code == CV_BGR5652RGBA && dcn == 4)
3462             {
3463                 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R,
3464                                                                        ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)))
3465                     return;
3466                 setIppErrorStatus();
3467             }
3468             CV_SUPPRESS_DEPRECATED_END
3469 #endif
3470
3471             CvtColorLoop(src, dst, RGB5x52RGB(dcn,
3472                       code == CV_BGR5652BGR || code == CV_BGR5552BGR ||
3473                       code == CV_BGR5652BGRA || code == CV_BGR5552BGRA ? 0 : 2, // blue idx
3474                       code == CV_BGR5652BGR || code == CV_BGR5652RGB ||
3475                       code == CV_BGR5652BGRA || code == CV_BGR5652RGBA ? 6 : 5 // green bits
3476                       ));
3477             break;
3478
3479         case CV_BGR2GRAY: case CV_BGRA2GRAY: case CV_RGB2GRAY: case CV_RGBA2GRAY:
3480             CV_Assert( scn == 3 || scn == 4 );
3481             _dst.create(sz, CV_MAKETYPE(depth, 1));
3482             dst = _dst.getMat();
3483
3484 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3485             if( code == CV_BGR2GRAY && depth == CV_32F )
3486             {
3487                 if( CvtColorIPPLoop(src, dst, IPPColor2GrayFunctor(ippiColor2GrayC3Tab[depth])) )
3488                     return;
3489                 setIppErrorStatus();
3490             }
3491             else if( code == CV_RGB2GRAY && depth == CV_32F )
3492             {
3493                 if( CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiRGB2GrayC3Tab[depth])) )
3494                     return;
3495                 setIppErrorStatus();
3496             }
3497             else if( code == CV_BGRA2GRAY && depth == CV_32F )
3498             {
3499                 if( CvtColorIPPLoop(src, dst, IPPColor2GrayFunctor(ippiColor2GrayC4Tab[depth])) )
3500                     return;
3501                 setIppErrorStatus();
3502             }
3503             else if( code == CV_RGBA2GRAY && depth == CV_32F )
3504             {
3505                 if( CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiRGB2GrayC4Tab[depth])) )
3506                     return;
3507                 setIppErrorStatus();
3508             }
3509 #endif
3510
3511             bidx = code == CV_BGR2GRAY || code == CV_BGRA2GRAY ? 0 : 2;
3512
3513             if( depth == CV_8U )
3514             {
3515 #ifdef HAVE_TEGRA_OPTIMIZATION
3516                 if(!tegra::cvtRGB2Gray(src, dst, bidx))
3517 #endif
3518                 CvtColorLoop(src, dst, RGB2Gray<uchar>(scn, bidx, 0));
3519             }
3520             else if( depth == CV_16U )
3521                 CvtColorLoop(src, dst, RGB2Gray<ushort>(scn, bidx, 0));
3522             else
3523                 CvtColorLoop(src, dst, RGB2Gray<float>(scn, bidx, 0));
3524             break;
3525
3526         case CV_BGR5652GRAY: case CV_BGR5552GRAY:
3527             CV_Assert( scn == 2 && depth == CV_8U );
3528             _dst.create(sz, CV_8UC1);
3529             dst = _dst.getMat();
3530
3531             CvtColorLoop(src, dst, RGB5x52Gray(code == CV_BGR5652GRAY ? 6 : 5));
3532             break;
3533
3534         case CV_GRAY2BGR: case CV_GRAY2BGRA:
3535             if( dcn <= 0 ) dcn = (code==CV_GRAY2BGRA) ? 4 : 3;
3536             CV_Assert( scn == 1 && (dcn == 3 || dcn == 4));
3537             _dst.create(sz, CV_MAKETYPE(depth, dcn));
3538             dst = _dst.getMat();
3539
3540 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3541             if( code == CV_GRAY2BGR )
3542             {
3543                 if( CvtColorIPPLoop(src, dst, IPPGray2BGRFunctor(ippiCopyP3C3RTab[depth])) )
3544                     return;
3545                 setIppErrorStatus();
3546             }
3547             else if( code == CV_GRAY2BGRA )
3548             {
3549                 if( CvtColorIPPLoop(src, dst, IPPGray2BGRAFunctor(ippiCopyP3C3RTab[depth], ippiSwapChannelsC3C4RTab[depth], depth)) )
3550                     return;
3551                 setIppErrorStatus();
3552             }
3553 #endif
3554
3555
3556             if( depth == CV_8U )
3557             {
3558 #ifdef HAVE_TEGRA_OPTIMIZATION
3559                 if(!tegra::cvtGray2RGB(src, dst))
3560 #endif
3561                 CvtColorLoop(src, dst, Gray2RGB<uchar>(dcn));
3562             }
3563             else if( depth == CV_16U )
3564                 CvtColorLoop(src, dst, Gray2RGB<ushort>(dcn));
3565             else
3566                 CvtColorLoop(src, dst, Gray2RGB<float>(dcn));
3567             break;
3568
3569         case CV_GRAY2BGR565: case CV_GRAY2BGR555:
3570             CV_Assert( scn == 1 && depth == CV_8U );
3571             _dst.create(sz, CV_8UC2);
3572             dst = _dst.getMat();
3573
3574             CvtColorLoop(src, dst, Gray2RGB5x5(code == CV_GRAY2BGR565 ? 6 : 5));
3575             break;
3576
3577         case CV_BGR2YCrCb: case CV_RGB2YCrCb:
3578         case CV_BGR2YUV: case CV_RGB2YUV:
3579             {
3580             CV_Assert( scn == 3 || scn == 4 );
3581             bidx = code == CV_BGR2YCrCb || code == CV_BGR2YUV ? 0 : 2;
3582             static const float yuv_f[] = { 0.114f, 0.587f, 0.299f, 0.492f, 0.877f };
3583             static const int yuv_i[] = { B2Y, G2Y, R2Y, 8061, 14369 };
3584             const float* coeffs_f = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_f;
3585             const int* coeffs_i = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_i;
3586
3587             _dst.create(sz, CV_MAKETYPE(depth, 3));
3588             dst = _dst.getMat();
3589
3590 #if defined HAVE_IPP && 0
3591             if (code == CV_RGB2YUV && scn == 3 && depth == CV_8U)
3592             {
3593                 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiRGBToYUV_8u_C3R)))
3594                     return;
3595                 setIppErrorStatus();
3596             }
3597             else if (code == CV_BGR2YUV && scn == 3 && depth == CV_8U)
3598             {
3599                 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth],
3600                                                                        (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth)))
3601                     return;
3602                 setIppErrorStatus();
3603             }
3604             else if (code == CV_RGB2YUV && scn == 4 && depth == CV_8U)
3605             {
3606                 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3607                                                                        (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 0, 1, 2, depth)))
3608                     return;
3609                 setIppErrorStatus();
3610             }
3611             else if (code == CV_BGR2YUV && scn == 4 && depth == CV_8U)
3612             {
3613                 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3614                                                                        (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth)))
3615                     return;
3616                 setIppErrorStatus();
3617             }
3618 #endif
3619
3620             if( depth == CV_8U )
3621             {
3622 #ifdef HAVE_TEGRA_OPTIMIZATION
3623                 if((code == CV_RGB2YCrCb || code == CV_BGR2YCrCb) && tegra::cvtRGB2YCrCb(src, dst, bidx))
3624                     break;
3625 #endif
3626                 CvtColorLoop(src, dst, RGB2YCrCb_i<uchar>(scn, bidx, coeffs_i));
3627             }
3628             else if( depth == CV_16U )
3629                 CvtColorLoop(src, dst, RGB2YCrCb_i<ushort>(scn, bidx, coeffs_i));
3630             else
3631                 CvtColorLoop(src, dst, RGB2YCrCb_f<float>(scn, bidx, coeffs_f));
3632             }
3633             break;
3634
3635         case CV_YCrCb2BGR: case CV_YCrCb2RGB:
3636         case CV_YUV2BGR: case CV_YUV2RGB:
3637             {
3638             if( dcn <= 0 ) dcn = 3;
3639             CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) );
3640             bidx = code == CV_YCrCb2BGR || code == CV_YUV2BGR ? 0 : 2;
3641             static const float yuv_f[] = { 2.032f, -0.395f, -0.581f, 1.140f };
3642             static const int yuv_i[] = { 33292, -6472, -9519, 18678 };
3643             const float* coeffs_f = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_f;
3644             const int* coeffs_i = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_i;
3645
3646             _dst.create(sz, CV_MAKETYPE(depth, dcn));
3647             dst = _dst.getMat();
3648
3649 #if defined HAVE_IPP && 0
3650             if (code == CV_YUV2RGB && dcn == 3 && depth == CV_8U)
3651             {
3652                 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R)))
3653                     return;
3654                 setIppErrorStatus();
3655             }
3656             else if (code == CV_YUV2BGR && dcn == 3 && depth == CV_8U)
3657             {
3658                 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R,
3659                                                                        ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)))
3660                     return;
3661                 setIppErrorStatus();
3662             }
3663             else if (code == CV_YUV2RGB && dcn == 4 && depth == CV_8U)
3664             {
3665                 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R,
3666                                                                        ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)))
3667                     return;
3668                 setIppErrorStatus();
3669             }
3670             else if (code == CV_YUV2BGR && dcn == 4 && depth == CV_8U)
3671             {
3672                 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R,
3673                                                                        ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)))
3674                     return;
3675                 setIppErrorStatus();
3676             }
3677 #endif
3678
3679             if( depth == CV_8U )
3680                 CvtColorLoop(src, dst, YCrCb2RGB_i<uchar>(dcn, bidx, coeffs_i));
3681             else if( depth == CV_16U )
3682                 CvtColorLoop(src, dst, YCrCb2RGB_i<ushort>(dcn, bidx, coeffs_i));
3683             else
3684                 CvtColorLoop(src, dst, YCrCb2RGB_f<float>(dcn, bidx, coeffs_f));
3685             }
3686             break;
3687
3688         case CV_BGR2XYZ: case CV_RGB2XYZ:
3689             CV_Assert( scn == 3 || scn == 4 );
3690             bidx = code == CV_BGR2XYZ ? 0 : 2;
3691
3692             _dst.create(sz, CV_MAKETYPE(depth, 3));
3693             dst = _dst.getMat();
3694
3695 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3696             if( code == CV_BGR2XYZ && scn == 3 && depth != CV_32F )
3697             {
3698                 if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2XYZTab[depth], 2, 1, 0, depth)) )
3699                     return;
3700                 setIppErrorStatus();
3701             }
3702             else if( code == CV_BGR2XYZ && scn == 4 && depth != CV_32F )
3703             {
3704                 if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2XYZTab[depth], 2, 1, 0, depth)) )
3705                     return;
3706                 setIppErrorStatus();
3707             }
3708             else if( code == CV_RGB2XYZ && scn == 3 && depth != CV_32F )
3709             {
3710                 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiRGB2XYZTab[depth])) )
3711                     return;
3712                 setIppErrorStatus();
3713             }
3714             else if( code == CV_RGB2XYZ && scn == 4 && depth != CV_32F )
3715             {
3716                 if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2XYZTab[depth], 0, 1, 2, depth)) )
3717                     return;
3718                 setIppErrorStatus();
3719             }
3720 #endif
3721
3722             if( depth == CV_8U )
3723                 CvtColorLoop(src, dst, RGB2XYZ_i<uchar>(scn, bidx, 0));
3724             else if( depth == CV_16U )
3725                 CvtColorLoop(src, dst, RGB2XYZ_i<ushort>(scn, bidx, 0));
3726             else
3727                 CvtColorLoop(src, dst, RGB2XYZ_f<float>(scn, bidx, 0));
3728             break;
3729
3730         case CV_XYZ2BGR: case CV_XYZ2RGB:
3731             if( dcn <= 0 ) dcn = 3;
3732             CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) );
3733             bidx = code == CV_XYZ2BGR ? 0 : 2;
3734
3735             _dst.create(sz, CV_MAKETYPE(depth, dcn));
3736             dst = _dst.getMat();
3737
3738 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3739             if( code == CV_XYZ2BGR && dcn == 3 && depth != CV_32F )
3740             {
3741                 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
3742                     return;
3743                 setIppErrorStatus();
3744             }
3745             else if( code == CV_XYZ2BGR && dcn == 4 && depth != CV_32F )
3746             {
3747                 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
3748                     return;
3749                 setIppErrorStatus();
3750             }
3751             if( code == CV_XYZ2RGB && dcn == 3 && depth != CV_32F )
3752             {
3753                 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiXYZ2RGBTab[depth])) )
3754                     return;
3755                 setIppErrorStatus();
3756             }
3757             else if( code == CV_XYZ2RGB && dcn == 4 && depth != CV_32F )
3758             {
3759                 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
3760                     return;
3761                 setIppErrorStatus();
3762             }
3763 #endif
3764
3765             if( depth == CV_8U )
3766                 CvtColorLoop(src, dst, XYZ2RGB_i<uchar>(dcn, bidx, 0));
3767             else if( depth == CV_16U )
3768                 CvtColorLoop(src, dst, XYZ2RGB_i<ushort>(dcn, bidx, 0));
3769             else
3770                 CvtColorLoop(src, dst, XYZ2RGB_f<float>(dcn, bidx, 0));
3771             break;
3772
3773         case CV_BGR2HSV: case CV_RGB2HSV: case CV_BGR2HSV_FULL: case CV_RGB2HSV_FULL:
3774         case CV_BGR2HLS: case CV_RGB2HLS: case CV_BGR2HLS_FULL: case CV_RGB2HLS_FULL:
3775             {
3776             CV_Assert( (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) );
3777             bidx = code == CV_BGR2HSV || code == CV_BGR2HLS ||
3778                 code == CV_BGR2HSV_FULL || code == CV_BGR2HLS_FULL ? 0 : 2;
3779             int hrange = depth == CV_32F ? 360 : code == CV_BGR2HSV || code == CV_RGB2HSV ||
3780                 code == CV_BGR2HLS || code == CV_RGB2HLS ? 180 : 256;
3781
3782             _dst.create(sz, CV_MAKETYPE(depth, 3));
3783             dst = _dst.getMat();
3784
3785 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3786             if( depth == CV_8U || depth == CV_16U )
3787             {
3788 #if 0 // breaks OCL accuracy tests
3789                 if( code == CV_BGR2HSV_FULL && scn == 3 )
3790                 {
3791                     if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) )
3792                         return;
3793                     setIppErrorStatus();
3794                 }
3795                 else if( code == CV_BGR2HSV_FULL && scn == 4 )
3796                 {
3797                     if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) )
3798                         return;
3799                     setIppErrorStatus();
3800                 }
3801                 else if( code == CV_RGB2HSV_FULL && scn == 4 )
3802                 {
3803                     if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 0, 1, 2, depth)) )
3804                         return;
3805                     setIppErrorStatus();
3806                 } else
3807 #endif
3808                 if( code == CV_RGB2HSV_FULL && scn == 3 && depth == CV_16U )
3809                 {
3810                     if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiRGB2HSVTab[depth])) )
3811                         return;
3812                     setIppErrorStatus();
3813                 }
3814                 else if( code == CV_BGR2HLS_FULL && scn == 3 )
3815                 {
3816                     if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) )
3817                         return;
3818                     setIppErrorStatus();
3819                 }
3820                 else if( code == CV_BGR2HLS_FULL && scn == 4 )
3821                 {
3822                     if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) )
3823                         return;
3824                     setIppErrorStatus();
3825                 }
3826                 else if( code == CV_RGB2HLS_FULL && scn == 3 )
3827                 {
3828                     if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiRGB2HLSTab[depth])) )
3829                         return;
3830                     setIppErrorStatus();
3831                 }
3832                 else if( code == CV_RGB2HLS_FULL && scn == 4 )
3833                 {
3834                     if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 0, 1, 2, depth)) )
3835                         return;
3836                     setIppErrorStatus();
3837                 }
3838             }
3839 #endif
3840
3841             if( code == CV_BGR2HSV || code == CV_RGB2HSV ||
3842                 code == CV_BGR2HSV_FULL || code == CV_RGB2HSV_FULL )
3843             {
3844 #ifdef HAVE_TEGRA_OPTIMIZATION
3845                 if(tegra::cvtRGB2HSV(src, dst, bidx, hrange))
3846                     break;
3847 #endif
3848                 if( depth == CV_8U )
3849                     CvtColorLoop(src, dst, RGB2HSV_b(scn, bidx, hrange));
3850                 else
3851                     CvtColorLoop(src, dst, RGB2HSV_f(scn, bidx, (float)hrange));
3852             }
3853             else
3854             {
3855                 if( depth == CV_8U )
3856                     CvtColorLoop(src, dst, RGB2HLS_b(scn, bidx, hrange));
3857                 else
3858                     CvtColorLoop(src, dst, RGB2HLS_f(scn, bidx, (float)hrange));
3859             }
3860             }
3861             break;
3862
3863         case CV_HSV2BGR: case CV_HSV2RGB: case CV_HSV2BGR_FULL: case CV_HSV2RGB_FULL:
3864         case CV_HLS2BGR: case CV_HLS2RGB: case CV_HLS2BGR_FULL: case CV_HLS2RGB_FULL:
3865             {
3866             if( dcn <= 0 ) dcn = 3;
3867             CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) );
3868             bidx = code == CV_HSV2BGR || code == CV_HLS2BGR ||
3869                 code == CV_HSV2BGR_FULL || code == CV_HLS2BGR_FULL ? 0 : 2;
3870             int hrange = depth == CV_32F ? 360 : code == CV_HSV2BGR || code == CV_HSV2RGB ||
3871                 code == CV_HLS2BGR || code == CV_HLS2RGB ? 180 : 255;
3872
3873             _dst.create(sz, CV_MAKETYPE(depth, dcn));
3874             dst = _dst.getMat();
3875
3876 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3877             if( depth == CV_8U || depth == CV_16U )
3878             {
3879                 if( code == CV_HSV2BGR_FULL && dcn == 3 )
3880                 {
3881                     if( CvtColorIPPLoopCopy(src, dst, IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
3882                         return;
3883                     setIppErrorStatus();
3884                 }
3885                 else if( code == CV_HSV2BGR_FULL && dcn == 4 )
3886                 {
3887                     if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
3888                         return;
3889                     setIppErrorStatus();
3890                 }
3891                 else if( code == CV_HSV2RGB_FULL && dcn == 3 )
3892                 {
3893                     if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiHSV2RGBTab[depth])) )
3894                         return;
3895                     setIppErrorStatus();
3896                 }
3897                 else if( code == CV_HSV2RGB_FULL && dcn == 4 )
3898                 {
3899                     if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
3900                         return;
3901                     setIppErrorStatus();
3902                 }
3903                 else if( code == CV_HLS2BGR_FULL && dcn == 3 )
3904                 {
3905                     if( CvtColorIPPLoopCopy(src, dst, IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
3906                         return;
3907                     setIppErrorStatus();
3908                 }
3909                 else if( code == CV_HLS2BGR_FULL && dcn == 4 )
3910                 {
3911                     if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
3912                         return;
3913                     setIppErrorStatus();
3914                 }
3915                 else if( code == CV_HLS2RGB_FULL && dcn == 3 )
3916                 {
3917                     if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiHLS2RGBTab[depth])) )
3918                         return;
3919                     setIppErrorStatus();
3920                 }
3921                 else if( code == CV_HLS2RGB_FULL && dcn == 4 )
3922                 {
3923                     if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
3924                         return;
3925                     setIppErrorStatus();
3926                 }
3927             }
3928 #endif
3929
3930             if( code == CV_HSV2BGR || code == CV_HSV2RGB ||
3931                 code == CV_HSV2BGR_FULL || code == CV_HSV2RGB_FULL )
3932             {
3933                 if( depth == CV_8U )
3934                     CvtColorLoop(src, dst, HSV2RGB_b(dcn, bidx, hrange));
3935                 else
3936                     CvtColorLoop(src, dst, HSV2RGB_f(dcn, bidx, (float)hrange));
3937             }
3938             else
3939             {
3940                 if( depth == CV_8U )
3941                     CvtColorLoop(src, dst, HLS2RGB_b(dcn, bidx, hrange));
3942                 else
3943                     CvtColorLoop(src, dst, HLS2RGB_f(dcn, bidx, (float)hrange));
3944             }
3945             }
3946             break;
3947
3948         case CV_BGR2Lab: case CV_RGB2Lab: case CV_LBGR2Lab: case CV_LRGB2Lab:
3949         case CV_BGR2Luv: case CV_RGB2Luv: case CV_LBGR2Luv: case CV_LRGB2Luv:
3950             {
3951             CV_Assert( (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) );
3952             bidx = code == CV_BGR2Lab || code == CV_BGR2Luv ||
3953                    code == CV_LBGR2Lab || code == CV_LBGR2Luv ? 0 : 2;
3954             bool srgb = code == CV_BGR2Lab || code == CV_RGB2Lab ||
3955                         code == CV_BGR2Luv || code == CV_RGB2Luv;
3956
3957             _dst.create(sz, CV_MAKETYPE(depth, 3));
3958             dst = _dst.getMat();
3959
3960 #ifdef HAVE_IPP
3961 #if 0
3962             if (code == CV_LBGR2Lab && scn == 3 && depth == CV_8U)
3963             {
3964                 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiBGRToLab_8u_C3R)))
3965                     return;
3966                 setIppErrorStatus();
3967             }
3968             else if (code == CV_LBGR2Lab && scn == 4 && depth == CV_8U)
3969             {
3970                 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3971                                                                        (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 0, 1, 2, depth)))
3972                     return;
3973                 setIppErrorStatus();
3974             }
3975             else
3976             if (code == CV_LRGB2Lab && scn == 3 && depth == CV_8U) // slower than OpenCV
3977             {
3978                 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth],
3979                                                                        (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 2, 1, 0, depth)))
3980                     return;
3981                 setIppErrorStatus();
3982             }
3983             else if (code == CV_LRGB2Lab && scn == 4 && depth == CV_8U) // slower than OpenCV
3984             {
3985                 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3986                                                                        (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 2, 1, 0, depth)))
3987                     return;
3988                 setIppErrorStatus();
3989             }
3990             else if (code == CV_LRGB2Luv && scn == 3)
3991             {
3992                 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiRGBToLUVTab[depth])))
3993                     return;
3994                 setIppErrorStatus();
3995             }
3996             else if (code == CV_LRGB2Luv && scn == 4)
3997             {
3998                 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3999                                                                        ippiRGBToLUVTab[depth], 0, 1, 2, depth)))
4000                     return;
4001                 setIppErrorStatus();
4002             }
4003             else if (code == CV_LBGR2Luv && scn == 3)
4004             {
4005                 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth],
4006                                                                        ippiRGBToLUVTab[depth], 2, 1, 0, depth)))
4007                     return;
4008                 setIppErrorStatus();
4009             }
4010             else if (code == CV_LBGR2Luv && scn == 4)
4011             {
4012                 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
4013                                                                        ippiRGBToLUVTab[depth], 2, 1, 0, depth)))
4014                     return;
4015                 setIppErrorStatus();
4016             }
4017 #endif
4018 #endif
4019
4020             if( code == CV_BGR2Lab || code == CV_RGB2Lab ||
4021                 code == CV_LBGR2Lab || code == CV_LRGB2Lab )
4022             {
4023                 if( depth == CV_8U )
4024                     CvtColorLoop(src, dst, RGB2Lab_b(scn, bidx, 0, 0, srgb));
4025                 else
4026                     CvtColorLoop(src, dst, RGB2Lab_f(scn, bidx, 0, 0, srgb));
4027             }
4028             else
4029             {
4030                 if( depth == CV_8U )
4031                     CvtColorLoop(src, dst, RGB2Luv_b(scn, bidx, 0, 0, srgb));
4032                 else
4033                     CvtColorLoop(src, dst, RGB2Luv_f(scn, bidx, 0, 0, srgb));
4034             }
4035             }
4036             break;
4037
4038         case CV_Lab2BGR: case CV_Lab2RGB: case CV_Lab2LBGR: case CV_Lab2LRGB:
4039         case CV_Luv2BGR: case CV_Luv2RGB: case CV_Luv2LBGR: case CV_Luv2LRGB:
4040             {
4041             if( dcn <= 0 ) dcn = 3;
4042             CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) );
4043             bidx = code == CV_Lab2BGR || code == CV_Luv2BGR ||
4044                    code == CV_Lab2LBGR || code == CV_Luv2LBGR ? 0 : 2;
4045             bool srgb = code == CV_Lab2BGR || code == CV_Lab2RGB ||
4046                     code == CV_Luv2BGR || code == CV_Luv2RGB;
4047
4048             _dst.create(sz, CV_MAKETYPE(depth, dcn));
4049             dst = _dst.getMat();
4050
4051 #if defined HAVE_IPP && 0
4052             if( code == CV_Lab2LBGR && dcn == 3 && depth == CV_8U)
4053             {
4054                 if( CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R)) )
4055                     return;
4056                 setIppErrorStatus();
4057             }
4058             else if( code == CV_Lab2LBGR && dcn == 4 && depth == CV_8U )
4059             {
4060                 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R,
4061                                     ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
4062                     return;
4063                 setIppErrorStatus();
4064             }
4065             if( code == CV_Lab2LRGB && dcn == 3 && depth == CV_8U )
4066             {
4067                 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R,
4068                                                                            ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
4069                     return;
4070                 setIppErrorStatus();
4071             }
4072             else if( code == CV_Lab2LRGB && dcn == 4 && depth == CV_8U )
4073             {
4074                 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R,
4075                                                                        ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
4076                     return;
4077                 setIppErrorStatus();
4078             }
4079             if( code == CV_Luv2LRGB && dcn == 3 )
4080             {
4081                 if( CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiLUVToRGBTab[depth])) )
4082                     return;
4083             }
4084             else if( code == CV_Luv2LRGB && dcn == 4 )
4085             {
4086                 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth],
4087                                                                        ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
4088                     return;
4089             }
4090             if( code == CV_Luv2LBGR && dcn == 3 )
4091             {
4092                 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth],
4093                                                                        ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
4094                     return;
4095             }
4096             else if( code == CV_Luv2LBGR && dcn == 4 )
4097             {
4098                 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth],
4099                                                                        ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
4100                     return;
4101             }
4102 #endif
4103
4104             if( code == CV_Lab2BGR || code == CV_Lab2RGB ||
4105                 code == CV_Lab2LBGR || code == CV_Lab2LRGB )
4106             {
4107                 if( depth == CV_8U )
4108                     CvtColorLoop(src, dst, Lab2RGB_b(dcn, bidx, 0, 0, srgb));
4109                 else
4110                     CvtColorLoop(src, dst, Lab2RGB_f(dcn, bidx, 0, 0, srgb));
4111             }
4112             else
4113             {
4114                 if( depth == CV_8U )
4115                     CvtColorLoop(src, dst, Luv2RGB_b(dcn, bidx, 0, 0, srgb));
4116                 else
4117                     CvtColorLoop(src, dst, Luv2RGB_f(dcn, bidx, 0, 0, srgb));
4118             }
4119             }
4120             break;
4121
4122         case CV_BayerBG2GRAY: case CV_BayerGB2GRAY: case CV_BayerRG2GRAY: case CV_BayerGR2GRAY:
4123         case CV_BayerBG2BGR: case CV_BayerGB2BGR: case CV_BayerRG2BGR: case CV_BayerGR2BGR:
4124         case CV_BayerBG2BGR_VNG: case CV_BayerGB2BGR_VNG: case CV_BayerRG2BGR_VNG: case CV_BayerGR2BGR_VNG:
4125         case CV_BayerBG2BGR_EA: case CV_BayerGB2BGR_EA: case CV_BayerRG2BGR_EA: case CV_BayerGR2BGR_EA:
4126             demosaicing(src, _dst, code, dcn);
4127             break;
4128
4129         case CV_YUV2BGR_NV21:  case CV_YUV2RGB_NV21:  case CV_YUV2BGR_NV12:  case CV_YUV2RGB_NV12:
4130         case CV_YUV2BGRA_NV21: case CV_YUV2RGBA_NV21: case CV_YUV2BGRA_NV12: case CV_YUV2RGBA_NV12:
4131             {
4132                 // http://www.fourcc.org/yuv.php#NV21 == yuv420sp -> a plane of 8 bit Y samples followed by an interleaved V/U plane containing 8 bit 2x2 subsampled chroma samples
4133                 // http://www.fourcc.org/yuv.php#NV12 -> a plane of 8 bit Y samples followed by an interleaved U/V plane containing 8 bit 2x2 subsampled colour difference samples
4134
4135                 if (dcn <= 0) dcn = (code==CV_YUV420sp2BGRA || code==CV_YUV420sp2RGBA || code==CV_YUV2BGRA_NV12 || code==CV_YUV2RGBA_NV12) ? 4 : 3;
4136                 const int bIdx = (code==CV_YUV2BGR_NV21 || code==CV_YUV2BGRA_NV21 || code==CV_YUV2BGR_NV12 || code==CV_YUV2BGRA_NV12) ? 0 : 2;
4137                 const int uIdx = (code==CV_YUV2BGR_NV21 || code==CV_YUV2BGRA_NV21 || code==CV_YUV2RGB_NV21 || code==CV_YUV2RGBA_NV21) ? 1 : 0;
4138
4139                 CV_Assert( dcn == 3 || dcn == 4 );
4140                 CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
4141
4142                 Size dstSz(sz.width, sz.height * 2 / 3);
4143                 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
4144                 dst = _dst.getMat();
4145
4146                 int srcstep = (int)src.step;
4147                 const uchar* y = src.ptr();
4148                 const uchar* uv = y + srcstep * dstSz.height;
4149
4150                 switch(dcn*100 + bIdx * 10 + uIdx)
4151                 {
4152                     case 300: cvtYUV420sp2RGB<0, 0> (dst, srcstep, y, uv); break;
4153                     case 301: cvtYUV420sp2RGB<0, 1> (dst, srcstep, y, uv); break;
4154                     case 320: cvtYUV420sp2RGB<2, 0> (dst, srcstep, y, uv); break;
4155                     case 321: cvtYUV420sp2RGB<2, 1> (dst, srcstep, y, uv); break;
4156                     case 400: cvtYUV420sp2RGBA<0, 0>(dst, srcstep, y, uv); break;
4157                     case 401: cvtYUV420sp2RGBA<0, 1>(dst, srcstep, y, uv); break;
4158                     case 420: cvtYUV420sp2RGBA<2, 0>(dst, srcstep, y, uv); break;
4159                     case 421: cvtYUV420sp2RGBA<2, 1>(dst, srcstep, y, uv); break;
4160                     default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
4161                 };
4162             }
4163             break;
4164         case CV_YUV2BGR_YV12: case CV_YUV2RGB_YV12: case CV_YUV2BGRA_YV12: case CV_YUV2RGBA_YV12:
4165         case CV_YUV2BGR_IYUV: case CV_YUV2RGB_IYUV: case CV_YUV2BGRA_IYUV: case CV_YUV2RGBA_IYUV:
4166             {
4167                 //http://www.fourcc.org/yuv.php#YV12 == yuv420p -> It comprises an NxM Y plane followed by (N/2)x(M/2) V and U planes.
4168                 //http://www.fourcc.org/yuv.php#IYUV == I420 -> It comprises an NxN Y plane followed by (N/2)x(N/2) U and V planes
4169
4170                 if (dcn <= 0) dcn = (code==CV_YUV2BGRA_YV12 || code==CV_YUV2RGBA_YV12 || code==CV_YUV2RGBA_IYUV || code==CV_YUV2BGRA_IYUV) ? 4 : 3;
4171                 const int bIdx = (code==CV_YUV2BGR_YV12 || code==CV_YUV2BGRA_YV12 || code==CV_YUV2BGR_IYUV || code==CV_YUV2BGRA_IYUV) ? 0 : 2;
4172                 const int uIdx  = (code==CV_YUV2BGR_YV12 || code==CV_YUV2RGB_YV12 || code==CV_YUV2BGRA_YV12 || code==CV_YUV2RGBA_YV12) ? 1 : 0;
4173
4174                 CV_Assert( dcn == 3 || dcn == 4 );
4175                 CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
4176
4177                 Size dstSz(sz.width, sz.height * 2 / 3);
4178                 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
4179                 dst = _dst.getMat();
4180
4181                 int srcstep = (int)src.step;
4182                 const uchar* y = src.ptr();
4183                 const uchar* u = y + srcstep * dstSz.height;
4184                 const uchar* v = y + srcstep * (dstSz.height + dstSz.height/4) + (dstSz.width/2) * ((dstSz.height % 4)/2);
4185
4186                 int ustepIdx = 0;
4187                 int vstepIdx = dstSz.height % 4 == 2 ? 1 : 0;
4188
4189                 if(uIdx == 1) { std::swap(u ,v), std::swap(ustepIdx, vstepIdx); }
4190
4191                 switch(dcn*10 + bIdx)
4192                 {
4193                     case 30: cvtYUV420p2RGB<0>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
4194                     case 32: cvtYUV420p2RGB<2>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
4195                     case 40: cvtYUV420p2RGBA<0>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
4196                     case 42: cvtYUV420p2RGBA<2>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
4197                     default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
4198                 };
4199             }
4200             break;
4201         case CV_YUV2GRAY_420:
4202             {
4203                 if (dcn <= 0) dcn = 1;
4204
4205                 CV_Assert( dcn == 1 );
4206                 CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
4207
4208                 Size dstSz(sz.width, sz.height * 2 / 3);
4209                 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
4210                 dst = _dst.getMat();
4211 #if defined HAVE_IPP
4212                 if (ippStsNoErr == ippiCopy_8u_C1R(src.data, (int)src.step, dst.data, (int)dst.step,
4213                         ippiSize(dstSz.width, dstSz.height)))
4214                     return;
4215                 setIppErrorStatus();
4216 #endif
4217                 src(Range(0, dstSz.height), Range::all()).copyTo(dst);
4218             }
4219             break;
4220         case CV_RGB2YUV_YV12: case CV_BGR2YUV_YV12: case CV_RGBA2YUV_YV12: case CV_BGRA2YUV_YV12:
4221         case CV_RGB2YUV_IYUV: case CV_BGR2YUV_IYUV: case CV_RGBA2YUV_IYUV: case CV_BGRA2YUV_IYUV:
4222             {
4223                 if (dcn <= 0) dcn = 1;
4224                 const int bIdx = (code == CV_BGR2YUV_IYUV || code == CV_BGRA2YUV_IYUV || code == CV_BGR2YUV_YV12 || code == CV_BGRA2YUV_YV12) ? 0 : 2;
4225                 const int uIdx = (code == CV_BGR2YUV_IYUV || code == CV_BGRA2YUV_IYUV || code == CV_RGB2YUV_IYUV || code == CV_RGBA2YUV_IYUV) ? 1 : 2;
4226
4227                 CV_Assert( (scn == 3 || scn == 4) && depth == CV_8U );
4228                 CV_Assert( dcn == 1 );
4229                 CV_Assert( sz.width % 2 == 0 && sz.height % 2 == 0 );
4230
4231                 Size dstSz(sz.width, sz.height / 2 * 3);
4232                 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
4233                 dst = _dst.getMat();
4234
4235                 switch(bIdx + uIdx*10)
4236                 {
4237                     case 10: cvtRGBtoYUV420p<0, 1>(src, dst); break;
4238                     case 12: cvtRGBtoYUV420p<2, 1>(src, dst); break;
4239                     case 20: cvtRGBtoYUV420p<0, 2>(src, dst); break;
4240                     case 22: cvtRGBtoYUV420p<2, 2>(src, dst); break;
4241                     default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
4242                 };
4243             }
4244             break;
4245         case CV_YUV2RGB_UYVY: case CV_YUV2BGR_UYVY: case CV_YUV2RGBA_UYVY: case CV_YUV2BGRA_UYVY:
4246         case CV_YUV2RGB_YUY2: case CV_YUV2BGR_YUY2: case CV_YUV2RGB_YVYU: case CV_YUV2BGR_YVYU:
4247         case CV_YUV2RGBA_YUY2: case CV_YUV2BGRA_YUY2: case CV_YUV2RGBA_YVYU: case CV_YUV2BGRA_YVYU:
4248             {
4249                 //http://www.fourcc.org/yuv.php#UYVY
4250                 //http://www.fourcc.org/yuv.php#YUY2
4251                 //http://www.fourcc.org/yuv.php#YVYU
4252
4253                 if (dcn <= 0) dcn = (code==CV_YUV2RGBA_UYVY || code==CV_YUV2BGRA_UYVY || code==CV_YUV2RGBA_YUY2 || code==CV_YUV2BGRA_YUY2 || code==CV_YUV2RGBA_YVYU || code==CV_YUV2BGRA_YVYU) ? 4 : 3;
4254                 const int bIdx = (code==CV_YUV2BGR_UYVY || code==CV_YUV2BGRA_UYVY || code==CV_YUV2BGR_YUY2 || code==CV_YUV2BGRA_YUY2 || code==CV_YUV2BGR_YVYU || code==CV_YUV2BGRA_YVYU) ? 0 : 2;
4255                 const int ycn  = (code==CV_YUV2RGB_UYVY || code==CV_YUV2BGR_UYVY || code==CV_YUV2RGBA_UYVY || code==CV_YUV2BGRA_UYVY) ? 1 : 0;
4256                 const int uIdx = (code==CV_YUV2RGB_YVYU || code==CV_YUV2BGR_YVYU || code==CV_YUV2RGBA_YVYU || code==CV_YUV2BGRA_YVYU) ? 1 : 0;
4257
4258                 CV_Assert( dcn == 3 || dcn == 4 );
4259                 CV_Assert( scn == 2 && depth == CV_8U );
4260
4261                 _dst.create(sz, CV_8UC(dcn));
4262                 dst = _dst.getMat();
4263
4264                 switch(dcn*1000 + bIdx*100 + uIdx*10 + ycn)
4265                 {
4266                     case 3000: cvtYUV422toRGB<0,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4267                     case 3001: cvtYUV422toRGB<0,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4268                     case 3010: cvtYUV422toRGB<0,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4269                     case 3011: cvtYUV422toRGB<0,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4270                     case 3200: cvtYUV422toRGB<2,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4271                     case 3201: cvtYUV422toRGB<2,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4272                     case 3210: cvtYUV422toRGB<2,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4273                     case 3211: cvtYUV422toRGB<2,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4274                     case 4000: cvtYUV422toRGBA<0,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4275                     case 4001: cvtYUV422toRGBA<0,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4276                     case 4010: cvtYUV422toRGBA<0,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4277                     case 4011: cvtYUV422toRGBA<0,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4278                     case 4200: cvtYUV422toRGBA<2,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4279                     case 4201: cvtYUV422toRGBA<2,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4280                     case 4210: cvtYUV422toRGBA<2,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4281                     case 4211: cvtYUV422toRGBA<2,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4282                     default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
4283                 };
4284             }
4285             break;
4286         case CV_YUV2GRAY_UYVY: case CV_YUV2GRAY_YUY2:
4287             {
4288                 if (dcn <= 0) dcn = 1;
4289
4290                 CV_Assert( dcn == 1 );
4291                 CV_Assert( scn == 2 && depth == CV_8U );
4292
4293                 extractChannel(_src, _dst, code == CV_YUV2GRAY_UYVY ? 1 : 0);
4294             }
4295             break;
4296         case CV_RGBA2mRGBA:
4297             {
4298                 if (dcn <= 0) dcn = 4;
4299                 CV_Assert( scn == 4 && dcn == 4 );
4300
4301                 _dst.create(sz, CV_MAKETYPE(depth, dcn));
4302                 dst = _dst.getMat();
4303
4304                 if( depth == CV_8U )
4305                 {
4306 #if defined(HAVE_IPP)
4307                     if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiAlphaPremul_8u_AC4R)))
4308                         return;
4309                     setIppErrorStatus();
4310 #endif
4311                     CvtColorLoop(src, dst, RGBA2mRGBA<uchar>());
4312                 }
4313                 else
4314                 {
4315                     CV_Error( CV_StsBadArg, "Unsupported image depth" );
4316                 }
4317             }
4318             break;
4319         case CV_mRGBA2RGBA:
4320             {
4321                 if (dcn <= 0) dcn = 4;
4322                 CV_Assert( scn == 4 && dcn == 4 );
4323
4324                 _dst.create(sz, CV_MAKETYPE(depth, dcn));
4325                 dst = _dst.getMat();
4326
4327                 if( depth == CV_8U )
4328                     CvtColorLoop(src, dst, mRGBA2RGBA<uchar>());
4329                 else
4330                 {
4331                     CV_Error( CV_StsBadArg, "Unsupported image depth" );
4332                 }
4333             }
4334             break;
4335         default:
4336             CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" );
4337     }
4338 }
4339
4340 CV_IMPL void
4341 cvCvtColor( const CvArr* srcarr, CvArr* dstarr, int code )
4342 {
4343     cv::Mat src = cv::cvarrToMat(srcarr), dst0 = cv::cvarrToMat(dstarr), dst = dst0;
4344     CV_Assert( src.depth() == dst.depth() );
4345
4346     cv::cvtColor(src, dst, code, dst.channels());
4347     CV_Assert( dst.data == dst0.data );
4348 }
4349
4350
4351 /* End of file. */