fixed defects found by coverity scan
[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.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.data, (int)temp.step[0], ippiSize(cols, rows)) < 0)
472             return false;
473         int order[4] = {0, 1, 2, 3};
474         return func2(temp.data, (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.data, (int)temp.step[0], ippiSize(cols, rows), order) < 0)
500             return false;
501         return func2(temp.data, (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.data, (int)temp.step[0], ippiSize(cols, rows)) < 0)
528             return false;
529         return func2(temp.data, (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             if( gammaTab )
2042             {
2043                 R = splineInterpolate(R*gscale, gammaTab, GAMMA_TAB_SIZE);
2044                 G = splineInterpolate(G*gscale, gammaTab, GAMMA_TAB_SIZE);
2045                 B = splineInterpolate(B*gscale, gammaTab, GAMMA_TAB_SIZE);
2046             }
2047
2048             dst[0] = R; dst[1] = G; dst[2] = B;
2049             if( dcn == 4 )
2050                 dst[3] = alpha;
2051         }
2052     }
2053
2054     int dstcn;
2055     float coeffs[9], un, vn;
2056     bool srgb;
2057 };
2058
2059
2060 struct RGB2Luv_b
2061 {
2062     typedef uchar channel_type;
2063
2064     RGB2Luv_b( int _srccn, int blueIdx, const float* _coeffs,
2065                const float* _whitept, bool _srgb )
2066     : srccn(_srccn), cvt(3, blueIdx, _coeffs, _whitept, _srgb) {}
2067
2068     void operator()(const uchar* src, uchar* dst, int n) const
2069     {
2070         int i, j, scn = srccn;
2071         float buf[3*BLOCK_SIZE];
2072
2073         for( i = 0; i < n; i += BLOCK_SIZE, dst += BLOCK_SIZE*3 )
2074         {
2075             int dn = std::min(n - i, (int)BLOCK_SIZE);
2076
2077             for( j = 0; j < dn*3; j += 3, src += scn )
2078             {
2079                 buf[j] = src[0]*(1.f/255.f);
2080                 buf[j+1] = (float)(src[1]*(1.f/255.f));
2081                 buf[j+2] = (float)(src[2]*(1.f/255.f));
2082             }
2083             cvt(buf, buf, dn);
2084
2085             for( j = 0; j < dn*3; j += 3 )
2086             {
2087                 dst[j] = saturate_cast<uchar>(buf[j]*2.55f);
2088                 dst[j+1] = saturate_cast<uchar>(buf[j+1]*0.72033898305084743f + 96.525423728813564f);
2089                 dst[j+2] = saturate_cast<uchar>(buf[j+2]*0.99609375f + 139.453125f);
2090             }
2091         }
2092     }
2093
2094     int srccn;
2095     RGB2Luv_f cvt;
2096 };
2097
2098
2099 struct Luv2RGB_b
2100 {
2101     typedef uchar channel_type;
2102
2103     Luv2RGB_b( int _dstcn, int blueIdx, const float* _coeffs,
2104                const float* _whitept, bool _srgb )
2105     : dstcn(_dstcn), cvt(3, blueIdx, _coeffs, _whitept, _srgb ) {}
2106
2107     void operator()(const uchar* src, uchar* dst, int n) const
2108     {
2109         int i, j, dcn = dstcn;
2110         uchar alpha = ColorChannel<uchar>::max();
2111         float buf[3*BLOCK_SIZE];
2112
2113         for( i = 0; i < n; i += BLOCK_SIZE, src += BLOCK_SIZE*3 )
2114         {
2115             int dn = std::min(n - i, (int)BLOCK_SIZE);
2116
2117             for( j = 0; j < dn*3; j += 3 )
2118             {
2119                 buf[j] = src[j]*(100.f/255.f);
2120                 buf[j+1] = (float)(src[j+1]*1.388235294117647f - 134.f);
2121                 buf[j+2] = (float)(src[j+2]*1.003921568627451f - 140.f);
2122             }
2123             cvt(buf, buf, dn);
2124
2125             for( j = 0; j < dn*3; j += 3, dst += dcn )
2126             {
2127                 dst[0] = saturate_cast<uchar>(buf[j]*255.f);
2128                 dst[1] = saturate_cast<uchar>(buf[j+1]*255.f);
2129                 dst[2] = saturate_cast<uchar>(buf[j+2]*255.f);
2130                 if( dcn == 4 )
2131                     dst[3] = alpha;
2132             }
2133         }
2134     }
2135
2136     int dstcn;
2137     Luv2RGB_f cvt;
2138 };
2139
2140
2141 ///////////////////////////////////// YUV420 -> RGB /////////////////////////////////////
2142
2143 const int ITUR_BT_601_CY = 1220542;
2144 const int ITUR_BT_601_CUB = 2116026;
2145 const int ITUR_BT_601_CUG = -409993;
2146 const int ITUR_BT_601_CVG = -852492;
2147 const int ITUR_BT_601_CVR = 1673527;
2148 const int ITUR_BT_601_SHIFT = 20;
2149
2150 // Coefficients for RGB to YUV420p conversion
2151 const int ITUR_BT_601_CRY =  269484;
2152 const int ITUR_BT_601_CGY =  528482;
2153 const int ITUR_BT_601_CBY =  102760;
2154 const int ITUR_BT_601_CRU = -155188;
2155 const int ITUR_BT_601_CGU = -305135;
2156 const int ITUR_BT_601_CBU =  460324;
2157 const int ITUR_BT_601_CGV = -385875;
2158 const int ITUR_BT_601_CBV = -74448;
2159
2160 template<int bIdx, int uIdx>
2161 struct YUV420sp2RGB888Invoker : ParallelLoopBody
2162 {
2163     Mat* dst;
2164     const uchar* my1, *muv;
2165     int width, stride;
2166
2167     YUV420sp2RGB888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _uv)
2168         : dst(_dst), my1(_y1), muv(_uv), width(_dst->cols), stride(_stride) {}
2169
2170     void operator()(const Range& range) const
2171     {
2172         int rangeBegin = range.start * 2;
2173         int rangeEnd = range.end * 2;
2174
2175         //R = 1.164(Y - 16) + 1.596(V - 128)
2176         //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
2177         //B = 1.164(Y - 16)                  + 2.018(U - 128)
2178
2179         //R = (1220542(Y - 16) + 1673527(V - 128)                  + (1 << 19)) >> 20
2180         //G = (1220542(Y - 16) - 852492(V - 128) - 409993(U - 128) + (1 << 19)) >> 20
2181         //B = (1220542(Y - 16)                  + 2116026(U - 128) + (1 << 19)) >> 20
2182
2183         const uchar* y1 = my1 + rangeBegin * stride, *uv = muv + rangeBegin * stride / 2;
2184
2185 #ifdef HAVE_TEGRA_OPTIMIZATION
2186         if(tegra::cvtYUV4202RGB(bIdx, uIdx, 3, y1, uv, stride, dst->ptr<uchar>(rangeBegin), dst->step, rangeEnd - rangeBegin, dst->cols))
2187             return;
2188 #endif
2189
2190         for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, uv += stride)
2191         {
2192             uchar* row1 = dst->ptr<uchar>(j);
2193             uchar* row2 = dst->ptr<uchar>(j + 1);
2194             const uchar* y2 = y1 + stride;
2195
2196             for (int i = 0; i < width; i += 2, row1 += 6, row2 += 6)
2197             {
2198                 int u = int(uv[i + 0 + uIdx]) - 128;
2199                 int v = int(uv[i + 1 - uIdx]) - 128;
2200
2201                 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2202                 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2203                 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2204
2205                 int y00 = std::max(0, int(y1[i]) - 16) * ITUR_BT_601_CY;
2206                 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2207                 row1[1]      = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2208                 row1[bIdx]   = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2209
2210                 int y01 = std::max(0, int(y1[i + 1]) - 16) * ITUR_BT_601_CY;
2211                 row1[5-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2212                 row1[4]      = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2213                 row1[3+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2214
2215                 int y10 = std::max(0, int(y2[i]) - 16) * ITUR_BT_601_CY;
2216                 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2217                 row2[1]      = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2218                 row2[bIdx]   = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2219
2220                 int y11 = std::max(0, int(y2[i + 1]) - 16) * ITUR_BT_601_CY;
2221                 row2[5-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2222                 row2[4]      = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2223                 row2[3+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2224             }
2225         }
2226     }
2227 };
2228
2229 template<int bIdx, int uIdx>
2230 struct YUV420sp2RGBA8888Invoker : ParallelLoopBody
2231 {
2232     Mat* dst;
2233     const uchar* my1, *muv;
2234     int width, stride;
2235
2236     YUV420sp2RGBA8888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _uv)
2237         : dst(_dst), my1(_y1), muv(_uv), width(_dst->cols), stride(_stride) {}
2238
2239     void operator()(const Range& range) const
2240     {
2241         int rangeBegin = range.start * 2;
2242         int rangeEnd = range.end * 2;
2243
2244         //R = 1.164(Y - 16) + 1.596(V - 128)
2245         //G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
2246         //B = 1.164(Y - 16)                  + 2.018(U - 128)
2247
2248         //R = (1220542(Y - 16) + 1673527(V - 128)                  + (1 << 19)) >> 20
2249         //G = (1220542(Y - 16) - 852492(V - 128) - 409993(U - 128) + (1 << 19)) >> 20
2250         //B = (1220542(Y - 16)                  + 2116026(U - 128) + (1 << 19)) >> 20
2251
2252         const uchar* y1 = my1 + rangeBegin * stride, *uv = muv + rangeBegin * stride / 2;
2253
2254 #ifdef HAVE_TEGRA_OPTIMIZATION
2255         if(tegra::cvtYUV4202RGB(bIdx, uIdx, 4, y1, uv, stride, dst->ptr<uchar>(rangeBegin), dst->step, rangeEnd - rangeBegin, dst->cols))
2256             return;
2257 #endif
2258
2259         for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, uv += stride)
2260         {
2261             uchar* row1 = dst->ptr<uchar>(j);
2262             uchar* row2 = dst->ptr<uchar>(j + 1);
2263             const uchar* y2 = y1 + stride;
2264
2265             for (int i = 0; i < width; i += 2, row1 += 8, row2 += 8)
2266             {
2267                 int u = int(uv[i + 0 + uIdx]) - 128;
2268                 int v = int(uv[i + 1 - uIdx]) - 128;
2269
2270                 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2271                 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2272                 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2273
2274                 int y00 = std::max(0, int(y1[i]) - 16) * ITUR_BT_601_CY;
2275                 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2276                 row1[1]      = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2277                 row1[bIdx]   = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2278                 row1[3]      = uchar(0xff);
2279
2280                 int y01 = std::max(0, int(y1[i + 1]) - 16) * ITUR_BT_601_CY;
2281                 row1[6-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2282                 row1[5]      = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2283                 row1[4+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2284                 row1[7]      = uchar(0xff);
2285
2286                 int y10 = std::max(0, int(y2[i]) - 16) * ITUR_BT_601_CY;
2287                 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2288                 row2[1]      = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2289                 row2[bIdx]   = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2290                 row2[3]      = uchar(0xff);
2291
2292                 int y11 = std::max(0, int(y2[i + 1]) - 16) * ITUR_BT_601_CY;
2293                 row2[6-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2294                 row2[5]      = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2295                 row2[4+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2296                 row2[7]      = uchar(0xff);
2297             }
2298         }
2299     }
2300 };
2301
2302 template<int bIdx>
2303 struct YUV420p2RGB888Invoker : ParallelLoopBody
2304 {
2305     Mat* dst;
2306     const uchar* my1, *mu, *mv;
2307     int width, stride;
2308     int ustepIdx, vstepIdx;
2309
2310     YUV420p2RGB888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int _ustepIdx, int _vstepIdx)
2311         : dst(_dst), my1(_y1), mu(_u), mv(_v), width(_dst->cols), stride(_stride), ustepIdx(_ustepIdx), vstepIdx(_vstepIdx) {}
2312
2313     void operator()(const Range& range) const
2314     {
2315         const int rangeBegin = range.start * 2;
2316         const int rangeEnd = range.end * 2;
2317
2318         int uvsteps[2] = {width/2, stride - width/2};
2319         int usIdx = ustepIdx, vsIdx = vstepIdx;
2320
2321         const uchar* y1 = my1 + rangeBegin * stride;
2322         const uchar* u1 = mu + (range.start / 2) * stride;
2323         const uchar* v1 = mv + (range.start / 2) * stride;
2324
2325         if(range.start % 2 == 1)
2326         {
2327             u1 += uvsteps[(usIdx++) & 1];
2328             v1 += uvsteps[(vsIdx++) & 1];
2329         }
2330
2331         for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, u1 += uvsteps[(usIdx++) & 1], v1 += uvsteps[(vsIdx++) & 1])
2332         {
2333             uchar* row1 = dst->ptr<uchar>(j);
2334             uchar* row2 = dst->ptr<uchar>(j + 1);
2335             const uchar* y2 = y1 + stride;
2336
2337             for (int i = 0; i < width / 2; i += 1, row1 += 6, row2 += 6)
2338             {
2339                 int u = int(u1[i]) - 128;
2340                 int v = int(v1[i]) - 128;
2341
2342                 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2343                 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2344                 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2345
2346                 int y00 = std::max(0, int(y1[2 * i]) - 16) * ITUR_BT_601_CY;
2347                 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2348                 row1[1]      = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2349                 row1[bIdx]   = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2350
2351                 int y01 = std::max(0, int(y1[2 * i + 1]) - 16) * ITUR_BT_601_CY;
2352                 row1[5-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2353                 row1[4]      = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2354                 row1[3+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2355
2356                 int y10 = std::max(0, int(y2[2 * i]) - 16) * ITUR_BT_601_CY;
2357                 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2358                 row2[1]      = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2359                 row2[bIdx]   = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2360
2361                 int y11 = std::max(0, int(y2[2 * i + 1]) - 16) * ITUR_BT_601_CY;
2362                 row2[5-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2363                 row2[4]      = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2364                 row2[3+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2365             }
2366         }
2367     }
2368 };
2369
2370 template<int bIdx>
2371 struct YUV420p2RGBA8888Invoker : ParallelLoopBody
2372 {
2373     Mat* dst;
2374     const uchar* my1, *mu, *mv;
2375     int width, stride;
2376     int ustepIdx, vstepIdx;
2377
2378     YUV420p2RGBA8888Invoker(Mat* _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int _ustepIdx, int _vstepIdx)
2379         : dst(_dst), my1(_y1), mu(_u), mv(_v), width(_dst->cols), stride(_stride), ustepIdx(_ustepIdx), vstepIdx(_vstepIdx) {}
2380
2381     void operator()(const Range& range) const
2382     {
2383         int rangeBegin = range.start * 2;
2384         int rangeEnd = range.end * 2;
2385
2386         int uvsteps[2] = {width/2, stride - width/2};
2387         int usIdx = ustepIdx, vsIdx = vstepIdx;
2388
2389         const uchar* y1 = my1 + rangeBegin * stride;
2390         const uchar* u1 = mu + (range.start / 2) * stride;
2391         const uchar* v1 = mv + (range.start / 2) * stride;
2392
2393         if(range.start % 2 == 1)
2394         {
2395             u1 += uvsteps[(usIdx++) & 1];
2396             v1 += uvsteps[(vsIdx++) & 1];
2397         }
2398
2399         for (int j = rangeBegin; j < rangeEnd; j += 2, y1 += stride * 2, u1 += uvsteps[(usIdx++) & 1], v1 += uvsteps[(vsIdx++) & 1])
2400         {
2401             uchar* row1 = dst->ptr<uchar>(j);
2402             uchar* row2 = dst->ptr<uchar>(j + 1);
2403             const uchar* y2 = y1 + stride;
2404
2405             for (int i = 0; i < width / 2; i += 1, row1 += 8, row2 += 8)
2406             {
2407                 int u = int(u1[i]) - 128;
2408                 int v = int(v1[i]) - 128;
2409
2410                 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2411                 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2412                 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2413
2414                 int y00 = std::max(0, int(y1[2 * i]) - 16) * ITUR_BT_601_CY;
2415                 row1[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2416                 row1[1]      = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2417                 row1[bIdx]   = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2418                 row1[3]      = uchar(0xff);
2419
2420                 int y01 = std::max(0, int(y1[2 * i + 1]) - 16) * ITUR_BT_601_CY;
2421                 row1[6-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2422                 row1[5]      = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2423                 row1[4+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2424                 row1[7]      = uchar(0xff);
2425
2426                 int y10 = std::max(0, int(y2[2 * i]) - 16) * ITUR_BT_601_CY;
2427                 row2[2-bIdx] = saturate_cast<uchar>((y10 + ruv) >> ITUR_BT_601_SHIFT);
2428                 row2[1]      = saturate_cast<uchar>((y10 + guv) >> ITUR_BT_601_SHIFT);
2429                 row2[bIdx]   = saturate_cast<uchar>((y10 + buv) >> ITUR_BT_601_SHIFT);
2430                 row2[3]      = uchar(0xff);
2431
2432                 int y11 = std::max(0, int(y2[2 * i + 1]) - 16) * ITUR_BT_601_CY;
2433                 row2[6-bIdx] = saturate_cast<uchar>((y11 + ruv) >> ITUR_BT_601_SHIFT);
2434                 row2[5]      = saturate_cast<uchar>((y11 + guv) >> ITUR_BT_601_SHIFT);
2435                 row2[4+bIdx] = saturate_cast<uchar>((y11 + buv) >> ITUR_BT_601_SHIFT);
2436                 row2[7]      = uchar(0xff);
2437             }
2438         }
2439     }
2440 };
2441
2442 #define MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION (320*240)
2443
2444 template<int bIdx, int uIdx>
2445 inline void cvtYUV420sp2RGB(Mat& _dst, int _stride, const uchar* _y1, const uchar* _uv)
2446 {
2447     YUV420sp2RGB888Invoker<bIdx, uIdx> converter(&_dst, _stride, _y1,  _uv);
2448     if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
2449         parallel_for_(Range(0, _dst.rows/2), converter);
2450     else
2451         converter(Range(0, _dst.rows/2));
2452 }
2453
2454 template<int bIdx, int uIdx>
2455 inline void cvtYUV420sp2RGBA(Mat& _dst, int _stride, const uchar* _y1, const uchar* _uv)
2456 {
2457     YUV420sp2RGBA8888Invoker<bIdx, uIdx> converter(&_dst, _stride, _y1,  _uv);
2458     if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
2459         parallel_for_(Range(0, _dst.rows/2), converter);
2460     else
2461         converter(Range(0, _dst.rows/2));
2462 }
2463
2464 template<int bIdx>
2465 inline void cvtYUV420p2RGB(Mat& _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int ustepIdx, int vstepIdx)
2466 {
2467     YUV420p2RGB888Invoker<bIdx> converter(&_dst, _stride, _y1,  _u, _v, ustepIdx, vstepIdx);
2468     if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
2469         parallel_for_(Range(0, _dst.rows/2), converter);
2470     else
2471         converter(Range(0, _dst.rows/2));
2472 }
2473
2474 template<int bIdx>
2475 inline void cvtYUV420p2RGBA(Mat& _dst, int _stride, const uchar* _y1, const uchar* _u, const uchar* _v, int ustepIdx, int vstepIdx)
2476 {
2477     YUV420p2RGBA8888Invoker<bIdx> converter(&_dst, _stride, _y1,  _u, _v, ustepIdx, vstepIdx);
2478     if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV420_CONVERSION)
2479         parallel_for_(Range(0, _dst.rows/2), converter);
2480     else
2481         converter(Range(0, _dst.rows/2));
2482 }
2483
2484 ///////////////////////////////////// RGB -> YUV420p /////////////////////////////////////
2485
2486 template<int bIdx>
2487 struct RGB888toYUV420pInvoker: public ParallelLoopBody
2488 {
2489     RGB888toYUV420pInvoker( const Mat& src, Mat* dst, const int uIdx )
2490         : src_(src),
2491           dst_(dst),
2492           uIdx_(uIdx) { }
2493
2494     void operator()(const Range& rowRange) const
2495     {
2496         const int w = src_.cols;
2497         const int h = src_.rows;
2498
2499         const int cn = src_.channels();
2500         for( int i = rowRange.start; i < rowRange.end; i++ )
2501         {
2502             const uchar* row0 = src_.ptr<uchar>(2 * i);
2503             const uchar* row1 = src_.ptr<uchar>(2 * i + 1);
2504
2505             uchar* y = dst_->ptr<uchar>(2*i);
2506             uchar* u = dst_->ptr<uchar>(h + i/2) + (i % 2) * (w/2);
2507             uchar* v = dst_->ptr<uchar>(h + (i + h/2)/2) + ((i + h/2) % 2) * (w/2);
2508             if( uIdx_ == 2 ) std::swap(u, v);
2509
2510             for( int j = 0, k = 0; j < w * cn; j += 2 * cn, k++ )
2511             {
2512                 int r00 = row0[2-bIdx + j];      int g00 = row0[1 + j];      int b00 = row0[bIdx + j];
2513                 int r01 = row0[2-bIdx + cn + j]; int g01 = row0[1 + cn + j]; int b01 = row0[bIdx + cn + j];
2514                 int r10 = row1[2-bIdx + j];      int g10 = row1[1 + j];      int b10 = row1[bIdx + j];
2515                 int r11 = row1[2-bIdx + cn + j]; int g11 = row1[1 + cn + j]; int b11 = row1[bIdx + cn + j];
2516
2517                 const int shifted16 = (16 << ITUR_BT_601_SHIFT);
2518                 const int halfShift = (1 << (ITUR_BT_601_SHIFT - 1));
2519                 int y00 = ITUR_BT_601_CRY * r00 + ITUR_BT_601_CGY * g00 + ITUR_BT_601_CBY * b00 + halfShift + shifted16;
2520                 int y01 = ITUR_BT_601_CRY * r01 + ITUR_BT_601_CGY * g01 + ITUR_BT_601_CBY * b01 + halfShift + shifted16;
2521                 int y10 = ITUR_BT_601_CRY * r10 + ITUR_BT_601_CGY * g10 + ITUR_BT_601_CBY * b10 + halfShift + shifted16;
2522                 int y11 = ITUR_BT_601_CRY * r11 + ITUR_BT_601_CGY * g11 + ITUR_BT_601_CBY * b11 + halfShift + shifted16;
2523
2524                 y[2*k + 0]            = saturate_cast<uchar>(y00 >> ITUR_BT_601_SHIFT);
2525                 y[2*k + 1]            = saturate_cast<uchar>(y01 >> ITUR_BT_601_SHIFT);
2526                 y[2*k + dst_->step + 0] = saturate_cast<uchar>(y10 >> ITUR_BT_601_SHIFT);
2527                 y[2*k + dst_->step + 1] = saturate_cast<uchar>(y11 >> ITUR_BT_601_SHIFT);
2528
2529                 const int shifted128 = (128 << ITUR_BT_601_SHIFT);
2530                 int u00 = ITUR_BT_601_CRU * r00 + ITUR_BT_601_CGU * g00 + ITUR_BT_601_CBU * b00 + halfShift + shifted128;
2531                 int v00 = ITUR_BT_601_CBU * r00 + ITUR_BT_601_CGV * g00 + ITUR_BT_601_CBV * b00 + halfShift + shifted128;
2532
2533                 u[k] = saturate_cast<uchar>(u00 >> ITUR_BT_601_SHIFT);
2534                 v[k] = saturate_cast<uchar>(v00 >> ITUR_BT_601_SHIFT);
2535             }
2536         }
2537     }
2538
2539     static bool isFit( const Mat& src )
2540     {
2541         return (src.total() >= 320*240);
2542     }
2543
2544 private:
2545     RGB888toYUV420pInvoker& operator=(const RGB888toYUV420pInvoker&);
2546
2547     const Mat& src_;
2548     Mat* const dst_;
2549     const int uIdx_;
2550 };
2551
2552 template<int bIdx, int uIdx>
2553 static void cvtRGBtoYUV420p(const Mat& src, Mat& dst)
2554 {
2555     RGB888toYUV420pInvoker<bIdx> colorConverter(src, &dst, uIdx);
2556     if( RGB888toYUV420pInvoker<bIdx>::isFit(src) )
2557         parallel_for_(Range(0, src.rows/2), colorConverter);
2558     else
2559         colorConverter(Range(0, src.rows/2));
2560 }
2561
2562 ///////////////////////////////////// YUV422 -> RGB /////////////////////////////////////
2563
2564 template<int bIdx, int uIdx, int yIdx>
2565 struct YUV422toRGB888Invoker : ParallelLoopBody
2566 {
2567     Mat* dst;
2568     const uchar* src;
2569     int width, stride;
2570
2571     YUV422toRGB888Invoker(Mat* _dst, int _stride, const uchar* _yuv)
2572         : dst(_dst), src(_yuv), width(_dst->cols), stride(_stride) {}
2573
2574     void operator()(const Range& range) const
2575     {
2576         int rangeBegin = range.start;
2577         int rangeEnd = range.end;
2578
2579         const int uidx = 1 - yIdx + uIdx * 2;
2580         const int vidx = (2 + uidx) % 4;
2581         const uchar* yuv_src = src + rangeBegin * stride;
2582
2583         for (int j = rangeBegin; j < rangeEnd; j++, yuv_src += stride)
2584         {
2585             uchar* row = dst->ptr<uchar>(j);
2586
2587             for (int i = 0; i < 2 * width; i += 4, row += 6)
2588             {
2589                 int u = int(yuv_src[i + uidx]) - 128;
2590                 int v = int(yuv_src[i + vidx]) - 128;
2591
2592                 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2593                 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2594                 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2595
2596                 int y00 = std::max(0, int(yuv_src[i + yIdx]) - 16) * ITUR_BT_601_CY;
2597                 row[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2598                 row[1]      = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2599                 row[bIdx]   = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2600
2601                 int y01 = std::max(0, int(yuv_src[i + yIdx + 2]) - 16) * ITUR_BT_601_CY;
2602                 row[5-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2603                 row[4]      = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2604                 row[3+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2605             }
2606         }
2607     }
2608 };
2609
2610 template<int bIdx, int uIdx, int yIdx>
2611 struct YUV422toRGBA8888Invoker : ParallelLoopBody
2612 {
2613     Mat* dst;
2614     const uchar* src;
2615     int width, stride;
2616
2617     YUV422toRGBA8888Invoker(Mat* _dst, int _stride, const uchar* _yuv)
2618         : dst(_dst), src(_yuv), width(_dst->cols), stride(_stride) {}
2619
2620     void operator()(const Range& range) const
2621     {
2622         int rangeBegin = range.start;
2623         int rangeEnd = range.end;
2624
2625         const int uidx = 1 - yIdx + uIdx * 2;
2626         const int vidx = (2 + uidx) % 4;
2627         const uchar* yuv_src = src + rangeBegin * stride;
2628
2629         for (int j = rangeBegin; j < rangeEnd; j++, yuv_src += stride)
2630         {
2631             uchar* row = dst->ptr<uchar>(j);
2632
2633             for (int i = 0; i < 2 * width; i += 4, row += 8)
2634             {
2635                 int u = int(yuv_src[i + uidx]) - 128;
2636                 int v = int(yuv_src[i + vidx]) - 128;
2637
2638                 int ruv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVR * v;
2639                 int guv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CVG * v + ITUR_BT_601_CUG * u;
2640                 int buv = (1 << (ITUR_BT_601_SHIFT - 1)) + ITUR_BT_601_CUB * u;
2641
2642                 int y00 = std::max(0, int(yuv_src[i + yIdx]) - 16) * ITUR_BT_601_CY;
2643                 row[2-bIdx] = saturate_cast<uchar>((y00 + ruv) >> ITUR_BT_601_SHIFT);
2644                 row[1]      = saturate_cast<uchar>((y00 + guv) >> ITUR_BT_601_SHIFT);
2645                 row[bIdx]   = saturate_cast<uchar>((y00 + buv) >> ITUR_BT_601_SHIFT);
2646                 row[3]      = uchar(0xff);
2647
2648                 int y01 = std::max(0, int(yuv_src[i + yIdx + 2]) - 16) * ITUR_BT_601_CY;
2649                 row[6-bIdx] = saturate_cast<uchar>((y01 + ruv) >> ITUR_BT_601_SHIFT);
2650                 row[5]      = saturate_cast<uchar>((y01 + guv) >> ITUR_BT_601_SHIFT);
2651                 row[4+bIdx] = saturate_cast<uchar>((y01 + buv) >> ITUR_BT_601_SHIFT);
2652                 row[7]      = uchar(0xff);
2653             }
2654         }
2655     }
2656 };
2657
2658 #define MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION (320*240)
2659
2660 template<int bIdx, int uIdx, int yIdx>
2661 inline void cvtYUV422toRGB(Mat& _dst, int _stride, const uchar* _yuv)
2662 {
2663     YUV422toRGB888Invoker<bIdx, uIdx, yIdx> converter(&_dst, _stride, _yuv);
2664     if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION)
2665         parallel_for_(Range(0, _dst.rows), converter);
2666     else
2667         converter(Range(0, _dst.rows));
2668 }
2669
2670 template<int bIdx, int uIdx, int yIdx>
2671 inline void cvtYUV422toRGBA(Mat& _dst, int _stride, const uchar* _yuv)
2672 {
2673     YUV422toRGBA8888Invoker<bIdx, uIdx, yIdx> converter(&_dst, _stride, _yuv);
2674     if (_dst.total() >= MIN_SIZE_FOR_PARALLEL_YUV422_CONVERSION)
2675         parallel_for_(Range(0, _dst.rows), converter);
2676     else
2677         converter(Range(0, _dst.rows));
2678 }
2679
2680 /////////////////////////// RGBA <-> mRGBA (alpha premultiplied) //////////////
2681
2682 template<typename _Tp>
2683 struct RGBA2mRGBA
2684 {
2685     typedef _Tp channel_type;
2686
2687     void operator()(const _Tp* src, _Tp* dst, int n) const
2688     {
2689         _Tp max_val  = ColorChannel<_Tp>::max();
2690         _Tp half_val = ColorChannel<_Tp>::half();
2691         for( int i = 0; i < n; i++ )
2692         {
2693             _Tp v0 = *src++;
2694             _Tp v1 = *src++;
2695             _Tp v2 = *src++;
2696             _Tp v3 = *src++;
2697
2698             *dst++ = (v0 * v3 + half_val) / max_val;
2699             *dst++ = (v1 * v3 + half_val) / max_val;
2700             *dst++ = (v2 * v3 + half_val) / max_val;
2701             *dst++ = v3;
2702         }
2703     }
2704 };
2705
2706
2707 template<typename _Tp>
2708 struct mRGBA2RGBA
2709 {
2710     typedef _Tp channel_type;
2711
2712     void operator()(const _Tp* src, _Tp* dst, int n) const
2713     {
2714         _Tp max_val = ColorChannel<_Tp>::max();
2715         for( int i = 0; i < n; i++ )
2716         {
2717             _Tp v0 = *src++;
2718             _Tp v1 = *src++;
2719             _Tp v2 = *src++;
2720             _Tp v3 = *src++;
2721             _Tp v3_half = v3 / 2;
2722
2723             *dst++ = (v3==0)? 0 : (v0 * max_val + v3_half) / v3;
2724             *dst++ = (v3==0)? 0 : (v1 * max_val + v3_half) / v3;
2725             *dst++ = (v3==0)? 0 : (v2 * max_val + v3_half) / v3;
2726             *dst++ = v3;
2727         }
2728     }
2729 };
2730
2731 #ifdef HAVE_OPENCL
2732
2733 #define DIVUP(total, grain) (((total) + (grain) - 1) / (grain))
2734
2735 static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
2736 {
2737     bool ok = false;
2738     UMat src = _src.getUMat(), dst;
2739     Size sz = src.size(), dstSz = sz;
2740     int scn = src.channels(), depth = src.depth(), bidx;
2741     int dims = 2, stripeSize = 1;
2742     size_t globalsize[] = { src.cols, src.rows };
2743     ocl::Kernel k;
2744
2745     if (depth != CV_8U && depth != CV_16U && depth != CV_32F)
2746         return false;
2747
2748     cv::String opts = format("-D depth=%d -D scn=%d ", depth, scn);
2749
2750     ocl::Device dev = ocl::Device::getDefault();
2751     int pxPerWIy = 1;
2752     if (dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU) &&
2753             !(code == CV_BGR2Luv || code == CV_RGB2Luv || code == CV_LBGR2Luv || code == CV_LRGB2Luv ||
2754               code == CV_Luv2BGR || code == CV_Luv2RGB || code == CV_Luv2LBGR || code == CV_Luv2LRGB))
2755         pxPerWIy = 4;
2756
2757     globalsize[1] = DIVUP(globalsize[1], pxPerWIy);
2758     opts += format("-D PIX_PER_WI_Y=%d ", pxPerWIy);
2759
2760     switch (code)
2761     {
2762     case COLOR_BGR2BGRA: case COLOR_RGB2BGRA: case COLOR_BGRA2BGR:
2763     case COLOR_RGBA2BGR: case COLOR_RGB2BGR: case COLOR_BGRA2RGBA:
2764     {
2765         CV_Assert(scn == 3 || scn == 4);
2766         dcn = code == COLOR_BGR2BGRA || code == COLOR_RGB2BGRA || code == COLOR_BGRA2RGBA ? 4 : 3;
2767         bool reverse = !(code == COLOR_BGR2BGRA || code == COLOR_BGRA2BGR);
2768         k.create("RGB", ocl::imgproc::cvtcolor_oclsrc,
2769                  opts + format("-D dcn=%d -D bidx=0 -D %s", dcn,
2770                         reverse ? "REVERSE" : "ORDER"));
2771         break;
2772     }
2773     case COLOR_BGR5652BGR: case COLOR_BGR5552BGR: case COLOR_BGR5652RGB: case COLOR_BGR5552RGB:
2774     case COLOR_BGR5652BGRA: case COLOR_BGR5552BGRA: case COLOR_BGR5652RGBA: case COLOR_BGR5552RGBA:
2775     {
2776         dcn = code == COLOR_BGR5652BGRA || code == COLOR_BGR5552BGRA || code == COLOR_BGR5652RGBA || code == COLOR_BGR5552RGBA ? 4 : 3;
2777         CV_Assert((dcn == 3 || dcn == 4) && scn == 2 && depth == CV_8U);
2778         bidx = code == COLOR_BGR5652BGR || code == COLOR_BGR5552BGR ||
2779             code == COLOR_BGR5652BGRA || code == COLOR_BGR5552BGRA ? 0 : 2;
2780         int greenbits = code == COLOR_BGR5652BGR || code == COLOR_BGR5652RGB ||
2781             code == COLOR_BGR5652BGRA || code == COLOR_BGR5652RGBA ? 6 : 5;
2782         k.create("RGB5x52RGB", ocl::imgproc::cvtcolor_oclsrc,
2783                  opts + format("-D dcn=%d -D bidx=%d -D greenbits=%d", dcn, bidx, greenbits));
2784         break;
2785     }
2786     case COLOR_BGR2BGR565: case COLOR_BGR2BGR555: case COLOR_RGB2BGR565: case COLOR_RGB2BGR555:
2787     case COLOR_BGRA2BGR565: case COLOR_BGRA2BGR555: case COLOR_RGBA2BGR565: case COLOR_RGBA2BGR555:
2788     {
2789         CV_Assert((scn == 3 || scn == 4) && depth == CV_8U );
2790         bidx = code == COLOR_BGR2BGR565 || code == COLOR_BGR2BGR555 ||
2791             code == COLOR_BGRA2BGR565 || code == COLOR_BGRA2BGR555 ? 0 : 2;
2792         int greenbits = code == COLOR_BGR2BGR565 || code == COLOR_RGB2BGR565 ||
2793             code == COLOR_BGRA2BGR565 || code == COLOR_RGBA2BGR565 ? 6 : 5;
2794         dcn = 2;
2795         k.create("RGB2RGB5x5", ocl::imgproc::cvtcolor_oclsrc,
2796                  opts + format("-D dcn=2 -D bidx=%d -D greenbits=%d", bidx, greenbits));
2797         break;
2798     }
2799     case COLOR_BGR5652GRAY: case COLOR_BGR5552GRAY:
2800     {
2801         CV_Assert(scn == 2 && depth == CV_8U);
2802         dcn = 1;
2803         int greenbits = code == COLOR_BGR5652GRAY ? 6 : 5;
2804         k.create("BGR5x52Gray", ocl::imgproc::cvtcolor_oclsrc,
2805                  opts + format("-D dcn=1 -D bidx=0 -D greenbits=%d", greenbits));
2806         break;
2807     }
2808     case COLOR_GRAY2BGR565: case COLOR_GRAY2BGR555:
2809     {
2810         CV_Assert(scn == 1 && depth == CV_8U);
2811         dcn = 2;
2812         int greenbits = code == COLOR_GRAY2BGR565 ? 6 : 5;
2813         k.create("Gray2BGR5x5", ocl::imgproc::cvtcolor_oclsrc,
2814                  opts + format("-D dcn=2 -D bidx=0 -D greenbits=%d", greenbits));
2815         break;
2816     }
2817     case COLOR_BGR2GRAY: case COLOR_BGRA2GRAY:
2818     case COLOR_RGB2GRAY: case COLOR_RGBA2GRAY:
2819     {
2820         CV_Assert(scn == 3 || scn == 4);
2821         bidx = code == COLOR_BGR2GRAY || code == COLOR_BGRA2GRAY ? 0 : 2;
2822         dcn = 1;
2823         k.create("RGB2Gray", ocl::imgproc::cvtcolor_oclsrc,
2824                  opts + format("-D dcn=1 -D bidx=%d -D STRIPE_SIZE=%d",
2825                                bidx, stripeSize));
2826         globalsize[0] = (src.cols + stripeSize-1)/stripeSize;
2827         break;
2828     }
2829     case COLOR_GRAY2BGR:
2830     case COLOR_GRAY2BGRA:
2831     {
2832         CV_Assert(scn == 1);
2833         dcn = code == COLOR_GRAY2BGRA ? 4 : 3;
2834         k.create("Gray2RGB", ocl::imgproc::cvtcolor_oclsrc,
2835                  opts + format("-D bidx=0 -D dcn=%d", dcn));
2836         break;
2837     }
2838     case COLOR_BGR2YUV:
2839     case COLOR_RGB2YUV:
2840     {
2841         CV_Assert(scn == 3 || scn == 4);
2842         bidx = code == COLOR_RGB2YUV ? 0 : 2;
2843         dcn = 3;
2844         k.create("RGB2YUV", ocl::imgproc::cvtcolor_oclsrc,
2845                  opts + format("-D dcn=3 -D bidx=%d", bidx));
2846         break;
2847     }
2848     case COLOR_YUV2BGR:
2849     case COLOR_YUV2RGB:
2850     {
2851         if(dcn < 0) dcn = 3;
2852         CV_Assert(dcn == 3 || dcn == 4);
2853         bidx = code == COLOR_YUV2RGB ? 0 : 2;
2854         k.create("YUV2RGB", ocl::imgproc::cvtcolor_oclsrc,
2855                  opts + format("-D dcn=%d -D bidx=%d", dcn, bidx));
2856         break;
2857     }
2858     case COLOR_YUV2RGB_NV12: case COLOR_YUV2BGR_NV12:
2859     case COLOR_YUV2RGBA_NV12: case COLOR_YUV2BGRA_NV12:
2860     {
2861         CV_Assert( scn == 1 );
2862         CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
2863         dcn  = code == COLOR_YUV2BGRA_NV12 || code == COLOR_YUV2RGBA_NV12 ? 4 : 3;
2864         bidx = code == COLOR_YUV2BGRA_NV12 || code == COLOR_YUV2BGR_NV12 ? 0 : 2;
2865
2866         dstSz = Size(sz.width, sz.height * 2 / 3);
2867         k.create("YUV2RGB_NV12", ocl::imgproc::cvtcolor_oclsrc,
2868                  opts + format("-D dcn=%d -D bidx=%d", dcn, bidx));
2869         break;
2870     }
2871     case COLOR_BGR2YCrCb:
2872     case COLOR_RGB2YCrCb:
2873     {
2874         CV_Assert(scn == 3 || scn == 4);
2875         bidx = code == COLOR_BGR2YCrCb ? 0 : 2;
2876         dcn = 3;
2877         k.create("RGB2YCrCb", ocl::imgproc::cvtcolor_oclsrc,
2878                  opts + format("-D dcn=3 -D bidx=%d", bidx));
2879         break;
2880     }
2881     case COLOR_YCrCb2BGR:
2882     case COLOR_YCrCb2RGB:
2883     {
2884         if( dcn <= 0 )
2885             dcn = 3;
2886         CV_Assert(scn == 3 && (dcn == 3 || dcn == 4));
2887         bidx = code == COLOR_YCrCb2BGR ? 0 : 2;
2888         k.create("YCrCb2RGB", ocl::imgproc::cvtcolor_oclsrc,
2889                  opts + format("-D dcn=%d -D bidx=%d", dcn, bidx));
2890         break;
2891     }
2892     case COLOR_BGR2XYZ: case COLOR_RGB2XYZ:
2893     {
2894         CV_Assert(scn == 3 || scn == 4);
2895         bidx = code == COLOR_BGR2XYZ ? 0 : 2;
2896
2897         UMat c;
2898         if (depth == CV_32F)
2899         {
2900             float coeffs[] =
2901             {
2902                 0.412453f, 0.357580f, 0.180423f,
2903                 0.212671f, 0.715160f, 0.072169f,
2904                 0.019334f, 0.119193f, 0.950227f
2905             };
2906             if (bidx == 0)
2907             {
2908                 std::swap(coeffs[0], coeffs[2]);
2909                 std::swap(coeffs[3], coeffs[5]);
2910                 std::swap(coeffs[6], coeffs[8]);
2911             }
2912             Mat(1, 9, CV_32FC1, &coeffs[0]).copyTo(c);
2913         }
2914         else
2915         {
2916             int coeffs[] =
2917             {
2918                 1689,    1465,    739,
2919                 871,     2929,    296,
2920                 79,      488,     3892
2921             };
2922             if (bidx == 0)
2923             {
2924                 std::swap(coeffs[0], coeffs[2]);
2925                 std::swap(coeffs[3], coeffs[5]);
2926                 std::swap(coeffs[6], coeffs[8]);
2927             }
2928             Mat(1, 9, CV_32SC1, &coeffs[0]).copyTo(c);
2929         }
2930
2931         _dst.create(dstSz, CV_MAKETYPE(depth, 3));
2932         dst = _dst.getUMat();
2933
2934         k.create("RGB2XYZ", ocl::imgproc::cvtcolor_oclsrc,
2935                  opts + format("-D dcn=3 -D bidx=%d", bidx));
2936         if (k.empty())
2937             return false;
2938         k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst), ocl::KernelArg::PtrReadOnly(c));
2939         return k.run(2, globalsize, 0, false);
2940     }
2941     case COLOR_XYZ2BGR: case COLOR_XYZ2RGB:
2942     {
2943         if (dcn <= 0)
2944             dcn = 3;
2945         CV_Assert(scn == 3 && (dcn == 3 || dcn == 4));
2946         bidx = code == COLOR_XYZ2BGR ? 0 : 2;
2947
2948         UMat c;
2949         if (depth == CV_32F)
2950         {
2951             float coeffs[] =
2952             {
2953                 3.240479f, -1.53715f, -0.498535f,
2954                 -0.969256f, 1.875991f, 0.041556f,
2955                 0.055648f, -0.204043f, 1.057311f
2956             };
2957             if (bidx == 0)
2958             {
2959                 std::swap(coeffs[0], coeffs[6]);
2960                 std::swap(coeffs[1], coeffs[7]);
2961                 std::swap(coeffs[2], coeffs[8]);
2962             }
2963             Mat(1, 9, CV_32FC1, &coeffs[0]).copyTo(c);
2964         }
2965         else
2966         {
2967             int coeffs[] =
2968             {
2969                 13273,  -6296,  -2042,
2970                 -3970,   7684,    170,
2971                   228,   -836,   4331
2972             };
2973             if (bidx == 0)
2974             {
2975                 std::swap(coeffs[0], coeffs[6]);
2976                 std::swap(coeffs[1], coeffs[7]);
2977                 std::swap(coeffs[2], coeffs[8]);
2978             }
2979             Mat(1, 9, CV_32SC1, &coeffs[0]).copyTo(c);
2980         }
2981
2982         _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
2983         dst = _dst.getUMat();
2984
2985         k.create("XYZ2RGB", ocl::imgproc::cvtcolor_oclsrc,
2986                  opts + format("-D dcn=%d -D bidx=%d", dcn, bidx));
2987         if (k.empty())
2988             return false;
2989         k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst), ocl::KernelArg::PtrReadOnly(c));
2990         return k.run(2, globalsize, 0, false);
2991     }
2992     case COLOR_BGR2HSV: case COLOR_RGB2HSV: case COLOR_BGR2HSV_FULL: case COLOR_RGB2HSV_FULL:
2993     case COLOR_BGR2HLS: case COLOR_RGB2HLS: case COLOR_BGR2HLS_FULL: case COLOR_RGB2HLS_FULL:
2994     {
2995         CV_Assert((scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F));
2996         bidx = code == COLOR_BGR2HSV || code == COLOR_BGR2HLS ||
2997             code == COLOR_BGR2HSV_FULL || code == COLOR_BGR2HLS_FULL ? 0 : 2;
2998         int hrange = depth == CV_32F ? 360 : code == COLOR_BGR2HSV || code == COLOR_RGB2HSV ||
2999             code == COLOR_BGR2HLS || code == COLOR_RGB2HLS ? 180 : 256;
3000         bool is_hsv = code == COLOR_BGR2HSV || code == COLOR_RGB2HSV || code == COLOR_BGR2HSV_FULL || code == COLOR_RGB2HSV_FULL;
3001         String kernelName = String("RGB2") + (is_hsv ? "HSV" : "HLS");
3002         dcn = 3;
3003
3004         if (is_hsv && depth == CV_8U)
3005         {
3006             static UMat sdiv_data;
3007             static UMat hdiv_data180;
3008             static UMat hdiv_data256;
3009             static int sdiv_table[256];
3010             static int hdiv_table180[256];
3011             static int hdiv_table256[256];
3012             static volatile bool initialized180 = false, initialized256 = false;
3013             volatile bool & initialized = hrange == 180 ? initialized180 : initialized256;
3014
3015             if (!initialized)
3016             {
3017                 int * const hdiv_table = hrange == 180 ? hdiv_table180 : hdiv_table256, hsv_shift = 12;
3018                 UMat & hdiv_data = hrange == 180 ? hdiv_data180 : hdiv_data256;
3019
3020                 sdiv_table[0] = hdiv_table180[0] = hdiv_table256[0] = 0;
3021
3022                 int v = 255 << hsv_shift;
3023                 if (!initialized180 && !initialized256)
3024                 {
3025                     for(int i = 1; i < 256; i++ )
3026                         sdiv_table[i] = saturate_cast<int>(v/(1.*i));
3027                     Mat(1, 256, CV_32SC1, sdiv_table).copyTo(sdiv_data);
3028                 }
3029
3030                 v = hrange << hsv_shift;
3031                 for (int i = 1; i < 256; i++ )
3032                     hdiv_table[i] = saturate_cast<int>(v/(6.*i));
3033
3034                 Mat(1, 256, CV_32SC1, hdiv_table).copyTo(hdiv_data);
3035                 initialized = true;
3036             }
3037
3038             _dst.create(dstSz, CV_8UC3);
3039             dst = _dst.getUMat();
3040
3041             k.create("RGB2HSV", ocl::imgproc::cvtcolor_oclsrc,
3042                      opts + format("-D hrange=%d -D bidx=%d -D dcn=3",
3043                                    hrange, bidx));
3044             if (k.empty())
3045                 return false;
3046
3047             k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst),
3048                    ocl::KernelArg::PtrReadOnly(sdiv_data), hrange == 256 ? ocl::KernelArg::PtrReadOnly(hdiv_data256) :
3049                                                                        ocl::KernelArg::PtrReadOnly(hdiv_data180));
3050
3051             return k.run(2, globalsize, NULL, false);
3052         }
3053         else
3054             k.create(kernelName.c_str(), ocl::imgproc::cvtcolor_oclsrc,
3055                      opts + format("-D hscale=%ff -D bidx=%d -D dcn=3",
3056                                    hrange*(1.f/360.f), bidx));
3057         break;
3058     }
3059     case COLOR_HSV2BGR: case COLOR_HSV2RGB: case COLOR_HSV2BGR_FULL: case COLOR_HSV2RGB_FULL:
3060     case COLOR_HLS2BGR: case COLOR_HLS2RGB: case COLOR_HLS2BGR_FULL: case COLOR_HLS2RGB_FULL:
3061     {
3062         if (dcn <= 0)
3063             dcn = 3;
3064         CV_Assert(scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F));
3065         bidx = code == COLOR_HSV2BGR || code == COLOR_HLS2BGR ||
3066             code == COLOR_HSV2BGR_FULL || code == COLOR_HLS2BGR_FULL ? 0 : 2;
3067         int hrange = depth == CV_32F ? 360 : code == COLOR_HSV2BGR || code == COLOR_HSV2RGB ||
3068             code == COLOR_HLS2BGR || code == COLOR_HLS2RGB ? 180 : 255;
3069         bool is_hsv = code == COLOR_HSV2BGR || code == COLOR_HSV2RGB ||
3070                 code == COLOR_HSV2BGR_FULL || code == COLOR_HSV2RGB_FULL;
3071
3072         String kernelName = String(is_hsv ? "HSV" : "HLS") + "2RGB";
3073         k.create(kernelName.c_str(), ocl::imgproc::cvtcolor_oclsrc,
3074                  opts + format("-D dcn=%d -D bidx=%d -D hrange=%d -D hscale=%ff",
3075                                dcn, bidx, hrange, 6.f/hrange));
3076         break;
3077     }
3078     case COLOR_RGBA2mRGBA: case COLOR_mRGBA2RGBA:
3079     {
3080         CV_Assert(scn == 4 && depth == CV_8U);
3081         dcn = 4;
3082
3083         k.create(code == COLOR_RGBA2mRGBA ? "RGBA2mRGBA" : "mRGBA2RGBA", ocl::imgproc::cvtcolor_oclsrc,
3084                  opts + "-D dcn=4 -D bidx=3");
3085         break;
3086     }
3087     case CV_BGR2Lab: case CV_RGB2Lab: case CV_LBGR2Lab: case CV_LRGB2Lab:
3088     case CV_BGR2Luv: case CV_RGB2Luv: case CV_LBGR2Luv: case CV_LRGB2Luv:
3089     {
3090         CV_Assert( (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) );
3091
3092         bidx = code == CV_BGR2Lab || code == CV_LBGR2Lab || code == CV_BGR2Luv || code == CV_LBGR2Luv ? 0 : 2;
3093         bool srgb = code == CV_BGR2Lab || code == CV_RGB2Lab || code == CV_RGB2Luv || code == CV_BGR2Luv;
3094         bool lab = code == CV_BGR2Lab || code == CV_RGB2Lab || code == CV_LBGR2Lab || code == CV_LRGB2Lab;
3095         float un, vn;
3096         dcn = 3;
3097
3098         k.create(format("BGR2%s", lab ? "Lab" : "Luv").c_str(),
3099                  ocl::imgproc::cvtcolor_oclsrc,
3100                  opts + format("-D dcn=%d -D bidx=%d%s",
3101                                dcn, bidx, srgb ? " -D SRGB" : ""));
3102         if (k.empty())
3103             return false;
3104
3105         initLabTabs();
3106
3107         _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
3108         dst = _dst.getUMat();
3109
3110         ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
3111                 dstarg = ocl::KernelArg::WriteOnly(dst);
3112
3113         if (depth == CV_8U && lab)
3114         {
3115             static UMat usRGBGammaTab, ulinearGammaTab, uLabCbrtTab, ucoeffs;
3116
3117             if (srgb && usRGBGammaTab.empty())
3118                 Mat(1, 256, CV_16UC1, sRGBGammaTab_b).copyTo(usRGBGammaTab);
3119             else if (ulinearGammaTab.empty())
3120                 Mat(1, 256, CV_16UC1, linearGammaTab_b).copyTo(ulinearGammaTab);
3121             if (uLabCbrtTab.empty())
3122                 Mat(1, LAB_CBRT_TAB_SIZE_B, CV_16UC1, LabCbrtTab_b).copyTo(uLabCbrtTab);
3123
3124             {
3125                 int coeffs[9];
3126                 const float * const _coeffs = sRGB2XYZ_D65, * const _whitept = D65;
3127                 const float scale[] =
3128                 {
3129                     (1 << lab_shift)/_whitept[0],
3130                     (float)(1 << lab_shift),
3131                     (1 << lab_shift)/_whitept[2]
3132                 };
3133
3134                 for (int i = 0; i < 3; i++ )
3135                 {
3136                     coeffs[i*3+(bidx^2)] = cvRound(_coeffs[i*3]*scale[i]);
3137                     coeffs[i*3+1] = cvRound(_coeffs[i*3+1]*scale[i]);
3138                     coeffs[i*3+bidx] = cvRound(_coeffs[i*3+2]*scale[i]);
3139
3140                     CV_Assert( coeffs[i] >= 0 && coeffs[i*3+1] >= 0 && coeffs[i*3+2] >= 0 &&
3141                               coeffs[i*3] + coeffs[i*3+1] + coeffs[i*3+2] < 2*(1 << lab_shift) );
3142                 }
3143                 Mat(1, 9, CV_32SC1, coeffs).copyTo(ucoeffs);
3144             }
3145
3146             const int Lscale = (116*255+50)/100;
3147             const int Lshift = -((16*255*(1 << lab_shift2) + 50)/100);
3148
3149             k.args(srcarg, dstarg,
3150                    ocl::KernelArg::PtrReadOnly(srgb ? usRGBGammaTab : ulinearGammaTab),
3151                    ocl::KernelArg::PtrReadOnly(uLabCbrtTab), ocl::KernelArg::PtrReadOnly(ucoeffs),
3152                    Lscale, Lshift);
3153         }
3154         else
3155         {
3156             static UMat usRGBGammaTab, ucoeffs, uLabCbrtTab;
3157
3158             if (srgb && usRGBGammaTab.empty())
3159                 Mat(1, GAMMA_TAB_SIZE * 4, CV_32FC1, sRGBGammaTab).copyTo(usRGBGammaTab);
3160             if (!lab && uLabCbrtTab.empty())
3161                 Mat(1, LAB_CBRT_TAB_SIZE * 4, CV_32FC1, LabCbrtTab).copyTo(uLabCbrtTab);
3162
3163             {
3164                 float coeffs[9];
3165                 const float * const _coeffs = sRGB2XYZ_D65, * const _whitept = D65;
3166                 float scale[] = { 1.0f / _whitept[0], 1.0f, 1.0f / _whitept[2] };
3167
3168                 for (int i = 0; i < 3; i++)
3169                 {
3170                     int j = i * 3;
3171                     coeffs[j + (bidx ^ 2)] = _coeffs[j] * (lab ? scale[i] : 1);
3172                     coeffs[j + 1] = _coeffs[j + 1] * (lab ? scale[i] : 1);
3173                     coeffs[j + bidx] = _coeffs[j + 2] * (lab ? scale[i] : 1);
3174
3175                     CV_Assert( coeffs[j] >= 0 && coeffs[j + 1] >= 0 && coeffs[j + 2] >= 0 &&
3176                                coeffs[j] + coeffs[j + 1] + coeffs[j + 2] < 1.5f*(lab ? LabCbrtTabScale : 1) );
3177                 }
3178
3179                 float d = 1.f/(_whitept[0] + _whitept[1]*15 + _whitept[2]*3);
3180                 un = 13*4*_whitept[0]*d;
3181                 vn = 13*9*_whitept[1]*d;
3182
3183                 Mat(1, 9, CV_32FC1, coeffs).copyTo(ucoeffs);
3184             }
3185
3186             float _1_3 = 1.0f / 3.0f, _a = 16.0f / 116.0f;
3187             ocl::KernelArg ucoeffsarg = ocl::KernelArg::PtrReadOnly(ucoeffs);
3188
3189             if (lab)
3190             {
3191                 if (srgb)
3192                     k.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(usRGBGammaTab),
3193                            ucoeffsarg, _1_3, _a);
3194                 else
3195                     k.args(srcarg, dstarg, ucoeffsarg, _1_3, _a);
3196             }
3197             else
3198             {
3199                 ocl::KernelArg LabCbrtTabarg = ocl::KernelArg::PtrReadOnly(uLabCbrtTab);
3200                 if (srgb)
3201                     k.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(usRGBGammaTab),
3202                            LabCbrtTabarg, ucoeffsarg, un, vn);
3203                 else
3204                     k.args(srcarg, dstarg, LabCbrtTabarg, ucoeffsarg, un, vn);
3205             }
3206         }
3207
3208         return k.run(dims, globalsize, NULL, false);
3209     }
3210     case CV_Lab2BGR: case CV_Lab2RGB: case CV_Lab2LBGR: case CV_Lab2LRGB:
3211     case CV_Luv2BGR: case CV_Luv2RGB: case CV_Luv2LBGR: case CV_Luv2LRGB:
3212     {
3213         if( dcn <= 0 )
3214             dcn = 3;
3215         CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) );
3216
3217         bidx = code == CV_Lab2BGR || code == CV_Lab2LBGR || code == CV_Luv2BGR || code == CV_Luv2LBGR ? 0 : 2;
3218         bool srgb = code == CV_Lab2BGR || code == CV_Lab2RGB || code == CV_Luv2BGR || code == CV_Luv2RGB;
3219         bool lab = code == CV_Lab2BGR || code == CV_Lab2RGB || code == CV_Lab2LBGR || code == CV_Lab2LRGB;
3220         float un, vn;
3221
3222         k.create(format("%s2BGR", lab ? "Lab" : "Luv").c_str(),
3223                  ocl::imgproc::cvtcolor_oclsrc,
3224                  opts + format("-D dcn=%d -D bidx=%d%s",
3225                                dcn, bidx, srgb ? " -D SRGB" : ""));
3226         if (k.empty())
3227             return false;
3228
3229         initLabTabs();
3230         static UMat ucoeffs, usRGBInvGammaTab;
3231
3232         if (srgb && usRGBInvGammaTab.empty())
3233             Mat(1, GAMMA_TAB_SIZE*4, CV_32FC1, sRGBInvGammaTab).copyTo(usRGBInvGammaTab);
3234
3235         {
3236             float coeffs[9];
3237             const float * const _coeffs = XYZ2sRGB_D65, * const _whitept = D65;
3238
3239             for( int i = 0; i < 3; i++ )
3240             {
3241                 coeffs[i+(bidx^2)*3] = _coeffs[i] * (lab ? _whitept[i] : 1);
3242                 coeffs[i+3] = _coeffs[i+3] * (lab ? _whitept[i] : 1);
3243                 coeffs[i+bidx*3] = _coeffs[i+6] * (lab ? _whitept[i] : 1);
3244             }
3245
3246             float d = 1.f/(_whitept[0] + _whitept[1]*15 + _whitept[2]*3);
3247             un = 4*_whitept[0]*d;
3248             vn = 9*_whitept[1]*d;
3249
3250             Mat(1, 9, CV_32FC1, coeffs).copyTo(ucoeffs);
3251         }
3252
3253         _dst.create(sz, CV_MAKETYPE(depth, dcn));
3254         dst = _dst.getUMat();
3255
3256         float lThresh = 0.008856f * 903.3f;
3257         float fThresh = 7.787f * 0.008856f + 16.0f / 116.0f;
3258
3259         ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
3260                 dstarg = ocl::KernelArg::WriteOnly(dst),
3261                 coeffsarg = ocl::KernelArg::PtrReadOnly(ucoeffs);
3262
3263         if (lab)
3264         {
3265             if (srgb)
3266                 k.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(usRGBInvGammaTab),
3267                        coeffsarg, lThresh, fThresh);
3268             else
3269                 k.args(srcarg, dstarg, coeffsarg, lThresh, fThresh);
3270         }
3271         else
3272         {
3273             if (srgb)
3274                 k.args(srcarg, dstarg, ocl::KernelArg::PtrReadOnly(usRGBInvGammaTab),
3275                        coeffsarg, un, vn);
3276             else
3277                 k.args(srcarg, dstarg, coeffsarg, un, vn);
3278         }
3279
3280         return k.run(dims, globalsize, NULL, false);
3281     }
3282     default:
3283         break;
3284     }
3285
3286     if( !k.empty() )
3287     {
3288         _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
3289         dst = _dst.getUMat();
3290         k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst));
3291         ok = k.run(dims, globalsize, NULL, false);
3292     }
3293     return ok;
3294 }
3295
3296 #endif
3297
3298 }//namespace cv
3299
3300 //////////////////////////////////////////////////////////////////////////////////////////
3301 //                                   The main function                                  //
3302 //////////////////////////////////////////////////////////////////////////////////////////
3303
3304 void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
3305 {
3306     int stype = _src.type();
3307     int scn = CV_MAT_CN(stype), depth = CV_MAT_DEPTH(stype), bidx;
3308
3309     CV_OCL_RUN( _src.dims() <= 2 && _dst.isUMat() && !(depth == CV_8U && (code == CV_Luv2BGR || code == CV_Luv2RGB)),
3310                 ocl_cvtColor(_src, _dst, code, dcn) )
3311
3312     Mat src = _src.getMat(), dst;
3313     Size sz = src.size();
3314
3315     CV_Assert( depth == CV_8U || depth == CV_16U || depth == CV_32F );
3316
3317     switch( code )
3318     {
3319         case CV_BGR2BGRA: case CV_RGB2BGRA: case CV_BGRA2BGR:
3320         case CV_RGBA2BGR: case CV_RGB2BGR: case CV_BGRA2RGBA:
3321             CV_Assert( scn == 3 || scn == 4 );
3322             dcn = code == CV_BGR2BGRA || code == CV_RGB2BGRA || code == CV_BGRA2RGBA ? 4 : 3;
3323             bidx = code == CV_BGR2BGRA || code == CV_BGRA2BGR ? 0 : 2;
3324
3325             _dst.create( sz, CV_MAKETYPE(depth, dcn));
3326             dst = _dst.getMat();
3327
3328 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3329             if( code == CV_BGR2BGRA)
3330             {
3331                 if ( CvtColorIPPLoop(src, dst, IPPReorderFunctor(ippiSwapChannelsC3C4RTab[depth], 0, 1, 2)) )
3332                     return;
3333                 setIppErrorStatus();
3334             }
3335             else if( code == CV_BGRA2BGR )
3336             {
3337                 if ( CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiCopyAC4C3RTab[depth])) )
3338                     return;
3339                 setIppErrorStatus();
3340             }
3341             else if( code == CV_BGR2RGBA )
3342             {
3343                 if( CvtColorIPPLoop(src, dst, IPPReorderFunctor(ippiSwapChannelsC3C4RTab[depth], 2, 1, 0)) )
3344                     return;
3345                 setIppErrorStatus();
3346             }
3347             else if( code == CV_RGBA2BGR )
3348             {
3349                 if( CvtColorIPPLoop(src, dst, IPPReorderFunctor(ippiSwapChannelsC4C3RTab[depth], 2, 1, 0)) )
3350                     return;
3351                 setIppErrorStatus();
3352             }
3353             else if( code == CV_RGB2BGR )
3354             {
3355                 if( CvtColorIPPLoopCopy(src, dst, IPPReorderFunctor(ippiSwapChannelsC3RTab[depth], 2, 1, 0)) )
3356                     return;
3357                 setIppErrorStatus();
3358             }
3359 #if IPP_VERSION_X100 >= 801
3360             else if( code == CV_RGBA2BGRA )
3361             {
3362                 if( CvtColorIPPLoopCopy(src, dst, IPPReorderFunctor(ippiSwapChannelsC4RTab[depth], 2, 1, 0)) )
3363                     return;
3364                 setIppErrorStatus();
3365             }
3366 #endif
3367 #endif
3368
3369             if( depth == CV_8U )
3370             {
3371 #ifdef HAVE_TEGRA_OPTIMIZATION
3372                 if(!tegra::cvtBGR2RGB(src, dst, bidx))
3373 #endif
3374                     CvtColorLoop(src, dst, RGB2RGB<uchar>(scn, dcn, bidx));
3375             }
3376             else if( depth == CV_16U )
3377                 CvtColorLoop(src, dst, RGB2RGB<ushort>(scn, dcn, bidx));
3378             else
3379                 CvtColorLoop(src, dst, RGB2RGB<float>(scn, dcn, bidx));
3380             break;
3381
3382         case CV_BGR2BGR565: case CV_BGR2BGR555: case CV_RGB2BGR565: case CV_RGB2BGR555:
3383         case CV_BGRA2BGR565: case CV_BGRA2BGR555: case CV_RGBA2BGR565: case CV_RGBA2BGR555:
3384             CV_Assert( (scn == 3 || scn == 4) && depth == CV_8U );
3385             _dst.create(sz, CV_8UC2);
3386             dst = _dst.getMat();
3387
3388 #ifdef HAVE_IPP
3389             CV_SUPPRESS_DEPRECATED_START
3390 #if 0
3391             if (code == CV_BGR2BGR565 && scn == 3)
3392             {
3393                 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R)))
3394                     return;
3395                 setIppErrorStatus();
3396             }
3397             else
3398 #endif
3399             if (code == CV_BGRA2BGR565 && scn == 4)
3400             {
3401                 if (CvtColorIPPLoopCopy(src, dst,
3402                                         IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3403                                         (ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R, 0, 1, 2, depth)))
3404                     return;
3405                 setIppErrorStatus();
3406             }
3407             else if (code == CV_RGB2BGR565 && scn == 3)
3408             {
3409                 if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth],
3410                                                                            (ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R, 2, 1, 0, depth)) )
3411                     return;
3412                 setIppErrorStatus();
3413             }
3414             else if (code == CV_RGBA2BGR565 && scn == 4)
3415             {
3416                 if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3417                                                                            (ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R, 2, 1, 0, depth)) )
3418                     return;
3419                 setIppErrorStatus();
3420             }
3421             CV_SUPPRESS_DEPRECATED_END
3422 #endif
3423
3424 #ifdef HAVE_TEGRA_OPTIMIZATION
3425             if(code == CV_BGR2BGR565 || code == CV_BGRA2BGR565 || code == CV_RGB2BGR565  || code == CV_RGBA2BGR565)
3426                 if(tegra::cvtRGB2RGB565(src, dst, code == CV_RGB2BGR565 || code == CV_RGBA2BGR565 ? 0 : 2))
3427                     break;
3428 #endif
3429
3430             CvtColorLoop(src, dst, RGB2RGB5x5(scn,
3431                       code == CV_BGR2BGR565 || code == CV_BGR2BGR555 ||
3432                       code == CV_BGRA2BGR565 || code == CV_BGRA2BGR555 ? 0 : 2,
3433                       code == CV_BGR2BGR565 || code == CV_RGB2BGR565 ||
3434                       code == CV_BGRA2BGR565 || code == CV_RGBA2BGR565 ? 6 : 5 // green bits
3435                                               ));
3436             break;
3437
3438         case CV_BGR5652BGR: case CV_BGR5552BGR: case CV_BGR5652RGB: case CV_BGR5552RGB:
3439         case CV_BGR5652BGRA: case CV_BGR5552BGRA: case CV_BGR5652RGBA: case CV_BGR5552RGBA:
3440             if(dcn <= 0) dcn = (code==CV_BGR5652BGRA || code==CV_BGR5552BGRA || code==CV_BGR5652RGBA || code==CV_BGR5552RGBA) ? 4 : 3;
3441             CV_Assert( (dcn == 3 || dcn == 4) && scn == 2 && depth == CV_8U );
3442             _dst.create(sz, CV_MAKETYPE(depth, dcn));
3443             dst = _dst.getMat();
3444
3445 #ifdef HAVE_IPP
3446             CV_SUPPRESS_DEPRECATED_START
3447             if (code == CV_BGR5652BGR && dcn == 3)
3448             {
3449                 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R)))
3450                     return;
3451                 setIppErrorStatus();
3452             }
3453             else if (code == CV_BGR5652RGB && dcn == 3)
3454             {
3455                 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R,
3456                                                                        ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)))
3457                     return;
3458                 setIppErrorStatus();
3459             }
3460             else if (code == CV_BGR5652BGRA && dcn == 4)
3461             {
3462                 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R,
3463                                                                        ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)))
3464                     return;
3465                 setIppErrorStatus();
3466             }
3467             else if (code == CV_BGR5652RGBA && dcn == 4)
3468             {
3469                 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R,
3470                                                                        ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)))
3471                     return;
3472                 setIppErrorStatus();
3473             }
3474             CV_SUPPRESS_DEPRECATED_END
3475 #endif
3476
3477             CvtColorLoop(src, dst, RGB5x52RGB(dcn,
3478                       code == CV_BGR5652BGR || code == CV_BGR5552BGR ||
3479                       code == CV_BGR5652BGRA || code == CV_BGR5552BGRA ? 0 : 2, // blue idx
3480                       code == CV_BGR5652BGR || code == CV_BGR5652RGB ||
3481                       code == CV_BGR5652BGRA || code == CV_BGR5652RGBA ? 6 : 5 // green bits
3482                       ));
3483             break;
3484
3485         case CV_BGR2GRAY: case CV_BGRA2GRAY: case CV_RGB2GRAY: case CV_RGBA2GRAY:
3486             CV_Assert( scn == 3 || scn == 4 );
3487             _dst.create(sz, CV_MAKETYPE(depth, 1));
3488             dst = _dst.getMat();
3489
3490 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3491             if( code == CV_BGR2GRAY && depth == CV_32F )
3492             {
3493                 if( CvtColorIPPLoop(src, dst, IPPColor2GrayFunctor(ippiColor2GrayC3Tab[depth])) )
3494                     return;
3495                 setIppErrorStatus();
3496             }
3497             else if( code == CV_RGB2GRAY && depth == CV_32F )
3498             {
3499                 if( CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiRGB2GrayC3Tab[depth])) )
3500                     return;
3501                 setIppErrorStatus();
3502             }
3503             else if( code == CV_BGRA2GRAY && depth == CV_32F )
3504             {
3505                 if( CvtColorIPPLoop(src, dst, IPPColor2GrayFunctor(ippiColor2GrayC4Tab[depth])) )
3506                     return;
3507                 setIppErrorStatus();
3508             }
3509             else if( code == CV_RGBA2GRAY && depth == CV_32F )
3510             {
3511                 if( CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiRGB2GrayC4Tab[depth])) )
3512                     return;
3513                 setIppErrorStatus();
3514             }
3515 #endif
3516
3517             bidx = code == CV_BGR2GRAY || code == CV_BGRA2GRAY ? 0 : 2;
3518
3519             if( depth == CV_8U )
3520             {
3521 #ifdef HAVE_TEGRA_OPTIMIZATION
3522                 if(!tegra::cvtRGB2Gray(src, dst, bidx))
3523 #endif
3524                 CvtColorLoop(src, dst, RGB2Gray<uchar>(scn, bidx, 0));
3525             }
3526             else if( depth == CV_16U )
3527                 CvtColorLoop(src, dst, RGB2Gray<ushort>(scn, bidx, 0));
3528             else
3529                 CvtColorLoop(src, dst, RGB2Gray<float>(scn, bidx, 0));
3530             break;
3531
3532         case CV_BGR5652GRAY: case CV_BGR5552GRAY:
3533             CV_Assert( scn == 2 && depth == CV_8U );
3534             _dst.create(sz, CV_8UC1);
3535             dst = _dst.getMat();
3536
3537             CvtColorLoop(src, dst, RGB5x52Gray(code == CV_BGR5652GRAY ? 6 : 5));
3538             break;
3539
3540         case CV_GRAY2BGR: case CV_GRAY2BGRA:
3541             if( dcn <= 0 ) dcn = (code==CV_GRAY2BGRA) ? 4 : 3;
3542             CV_Assert( scn == 1 && (dcn == 3 || dcn == 4));
3543             _dst.create(sz, CV_MAKETYPE(depth, dcn));
3544             dst = _dst.getMat();
3545
3546 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3547             if( code == CV_GRAY2BGR )
3548             {
3549                 if( CvtColorIPPLoop(src, dst, IPPGray2BGRFunctor(ippiCopyP3C3RTab[depth])) )
3550                     return;
3551                 setIppErrorStatus();
3552             }
3553             else if( code == CV_GRAY2BGRA )
3554             {
3555                 if( CvtColorIPPLoop(src, dst, IPPGray2BGRAFunctor(ippiCopyP3C3RTab[depth], ippiSwapChannelsC3C4RTab[depth], depth)) )
3556                     return;
3557                 setIppErrorStatus();
3558             }
3559 #endif
3560
3561
3562             if( depth == CV_8U )
3563             {
3564 #ifdef HAVE_TEGRA_OPTIMIZATION
3565                 if(!tegra::cvtGray2RGB(src, dst))
3566 #endif
3567                 CvtColorLoop(src, dst, Gray2RGB<uchar>(dcn));
3568             }
3569             else if( depth == CV_16U )
3570                 CvtColorLoop(src, dst, Gray2RGB<ushort>(dcn));
3571             else
3572                 CvtColorLoop(src, dst, Gray2RGB<float>(dcn));
3573             break;
3574
3575         case CV_GRAY2BGR565: case CV_GRAY2BGR555:
3576             CV_Assert( scn == 1 && depth == CV_8U );
3577             _dst.create(sz, CV_8UC2);
3578             dst = _dst.getMat();
3579
3580             CvtColorLoop(src, dst, Gray2RGB5x5(code == CV_GRAY2BGR565 ? 6 : 5));
3581             break;
3582
3583         case CV_BGR2YCrCb: case CV_RGB2YCrCb:
3584         case CV_BGR2YUV: case CV_RGB2YUV:
3585             {
3586             CV_Assert( scn == 3 || scn == 4 );
3587             bidx = code == CV_BGR2YCrCb || code == CV_BGR2YUV ? 0 : 2;
3588             static const float yuv_f[] = { 0.114f, 0.587f, 0.299f, 0.492f, 0.877f };
3589             static const int yuv_i[] = { B2Y, G2Y, R2Y, 8061, 14369 };
3590             const float* coeffs_f = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_f;
3591             const int* coeffs_i = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_i;
3592
3593             _dst.create(sz, CV_MAKETYPE(depth, 3));
3594             dst = _dst.getMat();
3595
3596 #if defined HAVE_IPP && 0
3597             if (code == CV_RGB2YUV && scn == 3 && depth == CV_8U)
3598             {
3599                 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiRGBToYUV_8u_C3R)))
3600                     return;
3601                 setIppErrorStatus();
3602             }
3603             else if (code == CV_BGR2YUV && scn == 3 && depth == CV_8U)
3604             {
3605                 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth],
3606                                                                        (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth)))
3607                     return;
3608                 setIppErrorStatus();
3609             }
3610             else if (code == CV_RGB2YUV && scn == 4 && depth == CV_8U)
3611             {
3612                 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3613                                                                        (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 0, 1, 2, depth)))
3614                     return;
3615                 setIppErrorStatus();
3616             }
3617             else if (code == CV_BGR2YUV && scn == 4 && depth == CV_8U)
3618             {
3619                 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3620                                                                        (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth)))
3621                     return;
3622                 setIppErrorStatus();
3623             }
3624 #endif
3625
3626             if( depth == CV_8U )
3627             {
3628 #ifdef HAVE_TEGRA_OPTIMIZATION
3629                 if((code == CV_RGB2YCrCb || code == CV_BGR2YCrCb) && tegra::cvtRGB2YCrCb(src, dst, bidx))
3630                     break;
3631 #endif
3632                 CvtColorLoop(src, dst, RGB2YCrCb_i<uchar>(scn, bidx, coeffs_i));
3633             }
3634             else if( depth == CV_16U )
3635                 CvtColorLoop(src, dst, RGB2YCrCb_i<ushort>(scn, bidx, coeffs_i));
3636             else
3637                 CvtColorLoop(src, dst, RGB2YCrCb_f<float>(scn, bidx, coeffs_f));
3638             }
3639             break;
3640
3641         case CV_YCrCb2BGR: case CV_YCrCb2RGB:
3642         case CV_YUV2BGR: case CV_YUV2RGB:
3643             {
3644             if( dcn <= 0 ) dcn = 3;
3645             CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) );
3646             bidx = code == CV_YCrCb2BGR || code == CV_YUV2BGR ? 0 : 2;
3647             static const float yuv_f[] = { 2.032f, -0.395f, -0.581f, 1.140f };
3648             static const int yuv_i[] = { 33292, -6472, -9519, 18678 };
3649             const float* coeffs_f = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_f;
3650             const int* coeffs_i = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_i;
3651
3652             _dst.create(sz, CV_MAKETYPE(depth, dcn));
3653             dst = _dst.getMat();
3654
3655 #if defined HAVE_IPP && 0
3656             if (code == CV_YUV2RGB && dcn == 3 && depth == CV_8U)
3657             {
3658                 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R)))
3659                     return;
3660                 setIppErrorStatus();
3661             }
3662             else if (code == CV_YUV2BGR && dcn == 3 && depth == CV_8U)
3663             {
3664                 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R,
3665                                                                        ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)))
3666                     return;
3667                 setIppErrorStatus();
3668             }
3669             else if (code == CV_YUV2RGB && dcn == 4 && depth == CV_8U)
3670             {
3671                 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R,
3672                                                                        ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)))
3673                     return;
3674                 setIppErrorStatus();
3675             }
3676             else if (code == CV_YUV2BGR && dcn == 4 && depth == CV_8U)
3677             {
3678                 if (CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R,
3679                                                                        ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)))
3680                     return;
3681                 setIppErrorStatus();
3682             }
3683 #endif
3684
3685             if( depth == CV_8U )
3686                 CvtColorLoop(src, dst, YCrCb2RGB_i<uchar>(dcn, bidx, coeffs_i));
3687             else if( depth == CV_16U )
3688                 CvtColorLoop(src, dst, YCrCb2RGB_i<ushort>(dcn, bidx, coeffs_i));
3689             else
3690                 CvtColorLoop(src, dst, YCrCb2RGB_f<float>(dcn, bidx, coeffs_f));
3691             }
3692             break;
3693
3694         case CV_BGR2XYZ: case CV_RGB2XYZ:
3695             CV_Assert( scn == 3 || scn == 4 );
3696             bidx = code == CV_BGR2XYZ ? 0 : 2;
3697
3698             _dst.create(sz, CV_MAKETYPE(depth, 3));
3699             dst = _dst.getMat();
3700
3701 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3702             if( code == CV_BGR2XYZ && scn == 3 && depth != CV_32F )
3703             {
3704                 if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2XYZTab[depth], 2, 1, 0, depth)) )
3705                     return;
3706                 setIppErrorStatus();
3707             }
3708             else if( code == CV_BGR2XYZ && scn == 4 && depth != CV_32F )
3709             {
3710                 if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2XYZTab[depth], 2, 1, 0, depth)) )
3711                     return;
3712                 setIppErrorStatus();
3713             }
3714             else if( code == CV_RGB2XYZ && scn == 3 && depth != CV_32F )
3715             {
3716                 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiRGB2XYZTab[depth])) )
3717                     return;
3718                 setIppErrorStatus();
3719             }
3720             else if( code == CV_RGB2XYZ && scn == 4 && depth != CV_32F )
3721             {
3722                 if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2XYZTab[depth], 0, 1, 2, depth)) )
3723                     return;
3724                 setIppErrorStatus();
3725             }
3726 #endif
3727
3728             if( depth == CV_8U )
3729                 CvtColorLoop(src, dst, RGB2XYZ_i<uchar>(scn, bidx, 0));
3730             else if( depth == CV_16U )
3731                 CvtColorLoop(src, dst, RGB2XYZ_i<ushort>(scn, bidx, 0));
3732             else
3733                 CvtColorLoop(src, dst, RGB2XYZ_f<float>(scn, bidx, 0));
3734             break;
3735
3736         case CV_XYZ2BGR: case CV_XYZ2RGB:
3737             if( dcn <= 0 ) dcn = 3;
3738             CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) );
3739             bidx = code == CV_XYZ2BGR ? 0 : 2;
3740
3741             _dst.create(sz, CV_MAKETYPE(depth, dcn));
3742             dst = _dst.getMat();
3743
3744 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3745             if( code == CV_XYZ2BGR && dcn == 3 && depth != CV_32F )
3746             {
3747                 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
3748                     return;
3749                 setIppErrorStatus();
3750             }
3751             else if( code == CV_XYZ2BGR && dcn == 4 && depth != CV_32F )
3752             {
3753                 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
3754                     return;
3755                 setIppErrorStatus();
3756             }
3757             if( code == CV_XYZ2RGB && dcn == 3 && depth != CV_32F )
3758             {
3759                 if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiXYZ2RGBTab[depth])) )
3760                     return;
3761                 setIppErrorStatus();
3762             }
3763             else if( code == CV_XYZ2RGB && dcn == 4 && depth != CV_32F )
3764             {
3765                 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
3766                     return;
3767                 setIppErrorStatus();
3768             }
3769 #endif
3770
3771             if( depth == CV_8U )
3772                 CvtColorLoop(src, dst, XYZ2RGB_i<uchar>(dcn, bidx, 0));
3773             else if( depth == CV_16U )
3774                 CvtColorLoop(src, dst, XYZ2RGB_i<ushort>(dcn, bidx, 0));
3775             else
3776                 CvtColorLoop(src, dst, XYZ2RGB_f<float>(dcn, bidx, 0));
3777             break;
3778
3779         case CV_BGR2HSV: case CV_RGB2HSV: case CV_BGR2HSV_FULL: case CV_RGB2HSV_FULL:
3780         case CV_BGR2HLS: case CV_RGB2HLS: case CV_BGR2HLS_FULL: case CV_RGB2HLS_FULL:
3781             {
3782             CV_Assert( (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) );
3783             bidx = code == CV_BGR2HSV || code == CV_BGR2HLS ||
3784                 code == CV_BGR2HSV_FULL || code == CV_BGR2HLS_FULL ? 0 : 2;
3785             int hrange = depth == CV_32F ? 360 : code == CV_BGR2HSV || code == CV_RGB2HSV ||
3786                 code == CV_BGR2HLS || code == CV_RGB2HLS ? 180 : 256;
3787
3788             _dst.create(sz, CV_MAKETYPE(depth, 3));
3789             dst = _dst.getMat();
3790
3791 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3792             if( depth == CV_8U || depth == CV_16U )
3793             {
3794                 if( code == CV_BGR2HSV_FULL && scn == 3 )
3795                 {
3796                     if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) )
3797                         return;
3798                     setIppErrorStatus();
3799                 }
3800                 else if( code == CV_BGR2HSV_FULL && scn == 4 )
3801                 {
3802                     if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) )
3803                         return;
3804                     setIppErrorStatus();
3805                 }
3806                 else if( code == CV_RGB2HSV_FULL && scn == 3 && depth == CV_16U )
3807                 {
3808                     if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiRGB2HSVTab[depth])) )
3809                         return;
3810                     setIppErrorStatus();
3811                 }
3812                 else if( code == CV_RGB2HSV_FULL && scn == 4 )
3813                 {
3814                     if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 0, 1, 2, depth)) )
3815                         return;
3816                     setIppErrorStatus();
3817                 }
3818                 else if( code == CV_BGR2HLS_FULL && scn == 3 )
3819                 {
3820                     if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) )
3821                         return;
3822                     setIppErrorStatus();
3823                 }
3824                 else if( code == CV_BGR2HLS_FULL && scn == 4 )
3825                 {
3826                     if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) )
3827                         return;
3828                     setIppErrorStatus();
3829                 }
3830                 else if( code == CV_RGB2HLS_FULL && scn == 3 )
3831                 {
3832                     if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiRGB2HLSTab[depth])) )
3833                         return;
3834                     setIppErrorStatus();
3835                 }
3836                 else if( code == CV_RGB2HLS_FULL && scn == 4 )
3837                 {
3838                     if( CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 0, 1, 2, depth)) )
3839                         return;
3840                     setIppErrorStatus();
3841                 }
3842             }
3843 #endif
3844
3845             if( code == CV_BGR2HSV || code == CV_RGB2HSV ||
3846                 code == CV_BGR2HSV_FULL || code == CV_RGB2HSV_FULL )
3847             {
3848 #ifdef HAVE_TEGRA_OPTIMIZATION
3849                 if(tegra::cvtRGB2HSV(src, dst, bidx, hrange))
3850                     break;
3851 #endif
3852                 if( depth == CV_8U )
3853                     CvtColorLoop(src, dst, RGB2HSV_b(scn, bidx, hrange));
3854                 else
3855                     CvtColorLoop(src, dst, RGB2HSV_f(scn, bidx, (float)hrange));
3856             }
3857             else
3858             {
3859                 if( depth == CV_8U )
3860                     CvtColorLoop(src, dst, RGB2HLS_b(scn, bidx, hrange));
3861                 else
3862                     CvtColorLoop(src, dst, RGB2HLS_f(scn, bidx, (float)hrange));
3863             }
3864             }
3865             break;
3866
3867         case CV_HSV2BGR: case CV_HSV2RGB: case CV_HSV2BGR_FULL: case CV_HSV2RGB_FULL:
3868         case CV_HLS2BGR: case CV_HLS2RGB: case CV_HLS2BGR_FULL: case CV_HLS2RGB_FULL:
3869             {
3870             if( dcn <= 0 ) dcn = 3;
3871             CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) );
3872             bidx = code == CV_HSV2BGR || code == CV_HLS2BGR ||
3873                 code == CV_HSV2BGR_FULL || code == CV_HLS2BGR_FULL ? 0 : 2;
3874             int hrange = depth == CV_32F ? 360 : code == CV_HSV2BGR || code == CV_HSV2RGB ||
3875                 code == CV_HLS2BGR || code == CV_HLS2RGB ? 180 : 255;
3876
3877             _dst.create(sz, CV_MAKETYPE(depth, dcn));
3878             dst = _dst.getMat();
3879
3880 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
3881             if( depth == CV_8U || depth == CV_16U )
3882             {
3883                 if( code == CV_HSV2BGR_FULL && dcn == 3 )
3884                 {
3885                     if( CvtColorIPPLoopCopy(src, dst, IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
3886                         return;
3887                     setIppErrorStatus();
3888                 }
3889                 else if( code == CV_HSV2BGR_FULL && dcn == 4 )
3890                 {
3891                     if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
3892                         return;
3893                     setIppErrorStatus();
3894                 }
3895                 else if( code == CV_HSV2RGB_FULL && dcn == 3 )
3896                 {
3897                     if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiHSV2RGBTab[depth])) )
3898                         return;
3899                     setIppErrorStatus();
3900                 }
3901                 else if( code == CV_HSV2RGB_FULL && dcn == 4 )
3902                 {
3903                     if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
3904                         return;
3905                     setIppErrorStatus();
3906                 }
3907                 else if( code == CV_HLS2BGR_FULL && dcn == 3 )
3908                 {
3909                     if( CvtColorIPPLoopCopy(src, dst, IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
3910                         return;
3911                     setIppErrorStatus();
3912                 }
3913                 else if( code == CV_HLS2BGR_FULL && dcn == 4 )
3914                 {
3915                     if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
3916                         return;
3917                     setIppErrorStatus();
3918                 }
3919                 else if( code == CV_HLS2RGB_FULL && dcn == 3 )
3920                 {
3921                     if( CvtColorIPPLoopCopy(src, dst, IPPGeneralFunctor(ippiHLS2RGBTab[depth])) )
3922                         return;
3923                     setIppErrorStatus();
3924                 }
3925                 else if( code == CV_HLS2RGB_FULL && dcn == 4 )
3926                 {
3927                     if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
3928                         return;
3929                     setIppErrorStatus();
3930                 }
3931             }
3932 #endif
3933
3934             if( code == CV_HSV2BGR || code == CV_HSV2RGB ||
3935                 code == CV_HSV2BGR_FULL || code == CV_HSV2RGB_FULL )
3936             {
3937                 if( depth == CV_8U )
3938                     CvtColorLoop(src, dst, HSV2RGB_b(dcn, bidx, hrange));
3939                 else
3940                     CvtColorLoop(src, dst, HSV2RGB_f(dcn, bidx, (float)hrange));
3941             }
3942             else
3943             {
3944                 if( depth == CV_8U )
3945                     CvtColorLoop(src, dst, HLS2RGB_b(dcn, bidx, hrange));
3946                 else
3947                     CvtColorLoop(src, dst, HLS2RGB_f(dcn, bidx, (float)hrange));
3948             }
3949             }
3950             break;
3951
3952         case CV_BGR2Lab: case CV_RGB2Lab: case CV_LBGR2Lab: case CV_LRGB2Lab:
3953         case CV_BGR2Luv: case CV_RGB2Luv: case CV_LBGR2Luv: case CV_LRGB2Luv:
3954             {
3955             CV_Assert( (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) );
3956             bidx = code == CV_BGR2Lab || code == CV_BGR2Luv ||
3957                    code == CV_LBGR2Lab || code == CV_LBGR2Luv ? 0 : 2;
3958             bool srgb = code == CV_BGR2Lab || code == CV_RGB2Lab ||
3959                         code == CV_BGR2Luv || code == CV_RGB2Luv;
3960
3961             _dst.create(sz, CV_MAKETYPE(depth, 3));
3962             dst = _dst.getMat();
3963
3964 #ifdef HAVE_IPP
3965 #if 0
3966             if (code == CV_LBGR2Lab && scn == 3 && depth == CV_8U)
3967             {
3968                 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiBGRToLab_8u_C3R)))
3969                     return;
3970                 setIppErrorStatus();
3971             }
3972             else if (code == CV_LBGR2Lab && scn == 4 && depth == CV_8U)
3973             {
3974                 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3975                                                                        (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 0, 1, 2, depth)))
3976                     return;
3977                 setIppErrorStatus();
3978             }
3979             else
3980             if (code == CV_LRGB2Lab && scn == 3 && depth == CV_8U) // slower than OpenCV
3981             {
3982                 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth],
3983                                                                        (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 2, 1, 0, depth)))
3984                     return;
3985                 setIppErrorStatus();
3986             }
3987             else if (code == CV_LRGB2Lab && scn == 4 && depth == CV_8U) // slower than OpenCV
3988             {
3989                 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
3990                                                                        (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 2, 1, 0, depth)))
3991                     return;
3992                 setIppErrorStatus();
3993             }
3994             else if (code == CV_LRGB2Luv && scn == 3)
3995             {
3996                 if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiRGBToLUVTab[depth])))
3997                     return;
3998                 setIppErrorStatus();
3999             }
4000             else if (code == CV_LRGB2Luv && scn == 4)
4001             {
4002                 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
4003                                                                        ippiRGBToLUVTab[depth], 0, 1, 2, depth)))
4004                     return;
4005                 setIppErrorStatus();
4006             }
4007             else if (code == CV_LBGR2Luv && scn == 3)
4008             {
4009                 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth],
4010                                                                        ippiRGBToLUVTab[depth], 2, 1, 0, depth)))
4011                     return;
4012                 setIppErrorStatus();
4013             }
4014             else if (code == CV_LBGR2Luv && scn == 4)
4015             {
4016                 if (CvtColorIPPLoop(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth],
4017                                                                        ippiRGBToLUVTab[depth], 2, 1, 0, depth)))
4018                     return;
4019                 setIppErrorStatus();
4020             }
4021 #endif
4022 #endif
4023
4024             if( code == CV_BGR2Lab || code == CV_RGB2Lab ||
4025                 code == CV_LBGR2Lab || code == CV_LRGB2Lab )
4026             {
4027                 if( depth == CV_8U )
4028                     CvtColorLoop(src, dst, RGB2Lab_b(scn, bidx, 0, 0, srgb));
4029                 else
4030                     CvtColorLoop(src, dst, RGB2Lab_f(scn, bidx, 0, 0, srgb));
4031             }
4032             else
4033             {
4034                 if( depth == CV_8U )
4035                     CvtColorLoop(src, dst, RGB2Luv_b(scn, bidx, 0, 0, srgb));
4036                 else
4037                     CvtColorLoop(src, dst, RGB2Luv_f(scn, bidx, 0, 0, srgb));
4038             }
4039             }
4040             break;
4041
4042         case CV_Lab2BGR: case CV_Lab2RGB: case CV_Lab2LBGR: case CV_Lab2LRGB:
4043         case CV_Luv2BGR: case CV_Luv2RGB: case CV_Luv2LBGR: case CV_Luv2LRGB:
4044             {
4045             if( dcn <= 0 ) dcn = 3;
4046             CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) );
4047             bidx = code == CV_Lab2BGR || code == CV_Luv2BGR ||
4048                    code == CV_Lab2LBGR || code == CV_Luv2LBGR ? 0 : 2;
4049             bool srgb = code == CV_Lab2BGR || code == CV_Lab2RGB ||
4050                     code == CV_Luv2BGR || code == CV_Luv2RGB;
4051
4052             _dst.create(sz, CV_MAKETYPE(depth, dcn));
4053             dst = _dst.getMat();
4054
4055 #if defined HAVE_IPP && 0
4056             if( code == CV_Lab2LBGR && dcn == 3 && depth == CV_8U)
4057             {
4058                 if( CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R)) )
4059                     return;
4060                 setIppErrorStatus();
4061             }
4062             else if( code == CV_Lab2LBGR && dcn == 4 && depth == CV_8U )
4063             {
4064                 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R,
4065                                     ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
4066                     return;
4067                 setIppErrorStatus();
4068             }
4069             if( code == CV_Lab2LRGB && dcn == 3 && depth == CV_8U )
4070             {
4071                 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R,
4072                                                                            ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
4073                     return;
4074                 setIppErrorStatus();
4075             }
4076             else if( code == CV_Lab2LRGB && dcn == 4 && depth == CV_8U )
4077             {
4078                 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R,
4079                                                                        ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
4080                     return;
4081                 setIppErrorStatus();
4082             }
4083             if( code == CV_Luv2LRGB && dcn == 3 )
4084             {
4085                 if( CvtColorIPPLoop(src, dst, IPPGeneralFunctor(ippiLUVToRGBTab[depth])) )
4086                     return;
4087             }
4088             else if( code == CV_Luv2LRGB && dcn == 4 )
4089             {
4090                 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth],
4091                                                                        ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) )
4092                     return;
4093             }
4094             if( code == CV_Luv2LBGR && dcn == 3 )
4095             {
4096                 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth],
4097                                                                        ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) )
4098                     return;
4099             }
4100             else if( code == CV_Luv2LBGR && dcn == 4 )
4101             {
4102                 if( CvtColorIPPLoop(src, dst, IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth],
4103                                                                        ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) )
4104                     return;
4105             }
4106 #endif
4107
4108             if( code == CV_Lab2BGR || code == CV_Lab2RGB ||
4109                 code == CV_Lab2LBGR || code == CV_Lab2LRGB )
4110             {
4111                 if( depth == CV_8U )
4112                     CvtColorLoop(src, dst, Lab2RGB_b(dcn, bidx, 0, 0, srgb));
4113                 else
4114                     CvtColorLoop(src, dst, Lab2RGB_f(dcn, bidx, 0, 0, srgb));
4115             }
4116             else
4117             {
4118                 if( depth == CV_8U )
4119                     CvtColorLoop(src, dst, Luv2RGB_b(dcn, bidx, 0, 0, srgb));
4120                 else
4121                     CvtColorLoop(src, dst, Luv2RGB_f(dcn, bidx, 0, 0, srgb));
4122             }
4123             }
4124             break;
4125
4126         case CV_BayerBG2GRAY: case CV_BayerGB2GRAY: case CV_BayerRG2GRAY: case CV_BayerGR2GRAY:
4127         case CV_BayerBG2BGR: case CV_BayerGB2BGR: case CV_BayerRG2BGR: case CV_BayerGR2BGR:
4128         case CV_BayerBG2BGR_VNG: case CV_BayerGB2BGR_VNG: case CV_BayerRG2BGR_VNG: case CV_BayerGR2BGR_VNG:
4129         case CV_BayerBG2BGR_EA: case CV_BayerGB2BGR_EA: case CV_BayerRG2BGR_EA: case CV_BayerGR2BGR_EA:
4130             demosaicing(src, _dst, code, dcn);
4131             break;
4132
4133         case CV_YUV2BGR_NV21:  case CV_YUV2RGB_NV21:  case CV_YUV2BGR_NV12:  case CV_YUV2RGB_NV12:
4134         case CV_YUV2BGRA_NV21: case CV_YUV2RGBA_NV21: case CV_YUV2BGRA_NV12: case CV_YUV2RGBA_NV12:
4135             {
4136                 // 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
4137                 // 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
4138
4139                 if (dcn <= 0) dcn = (code==CV_YUV420sp2BGRA || code==CV_YUV420sp2RGBA || code==CV_YUV2BGRA_NV12 || code==CV_YUV2RGBA_NV12) ? 4 : 3;
4140                 const int bIdx = (code==CV_YUV2BGR_NV21 || code==CV_YUV2BGRA_NV21 || code==CV_YUV2BGR_NV12 || code==CV_YUV2BGRA_NV12) ? 0 : 2;
4141                 const int uIdx = (code==CV_YUV2BGR_NV21 || code==CV_YUV2BGRA_NV21 || code==CV_YUV2RGB_NV21 || code==CV_YUV2RGBA_NV21) ? 1 : 0;
4142
4143                 CV_Assert( dcn == 3 || dcn == 4 );
4144                 CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
4145
4146                 Size dstSz(sz.width, sz.height * 2 / 3);
4147                 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
4148                 dst = _dst.getMat();
4149
4150                 int srcstep = (int)src.step;
4151                 const uchar* y = src.ptr();
4152                 const uchar* uv = y + srcstep * dstSz.height;
4153
4154                 switch(dcn*100 + bIdx * 10 + uIdx)
4155                 {
4156                     case 300: cvtYUV420sp2RGB<0, 0> (dst, srcstep, y, uv); break;
4157                     case 301: cvtYUV420sp2RGB<0, 1> (dst, srcstep, y, uv); break;
4158                     case 320: cvtYUV420sp2RGB<2, 0> (dst, srcstep, y, uv); break;
4159                     case 321: cvtYUV420sp2RGB<2, 1> (dst, srcstep, y, uv); break;
4160                     case 400: cvtYUV420sp2RGBA<0, 0>(dst, srcstep, y, uv); break;
4161                     case 401: cvtYUV420sp2RGBA<0, 1>(dst, srcstep, y, uv); break;
4162                     case 420: cvtYUV420sp2RGBA<2, 0>(dst, srcstep, y, uv); break;
4163                     case 421: cvtYUV420sp2RGBA<2, 1>(dst, srcstep, y, uv); break;
4164                     default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
4165                 };
4166             }
4167             break;
4168         case CV_YUV2BGR_YV12: case CV_YUV2RGB_YV12: case CV_YUV2BGRA_YV12: case CV_YUV2RGBA_YV12:
4169         case CV_YUV2BGR_IYUV: case CV_YUV2RGB_IYUV: case CV_YUV2BGRA_IYUV: case CV_YUV2RGBA_IYUV:
4170             {
4171                 //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.
4172                 //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
4173
4174                 if (dcn <= 0) dcn = (code==CV_YUV2BGRA_YV12 || code==CV_YUV2RGBA_YV12 || code==CV_YUV2RGBA_IYUV || code==CV_YUV2BGRA_IYUV) ? 4 : 3;
4175                 const int bIdx = (code==CV_YUV2BGR_YV12 || code==CV_YUV2BGRA_YV12 || code==CV_YUV2BGR_IYUV || code==CV_YUV2BGRA_IYUV) ? 0 : 2;
4176                 const int uIdx  = (code==CV_YUV2BGR_YV12 || code==CV_YUV2RGB_YV12 || code==CV_YUV2BGRA_YV12 || code==CV_YUV2RGBA_YV12) ? 1 : 0;
4177
4178                 CV_Assert( dcn == 3 || dcn == 4 );
4179                 CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
4180
4181                 Size dstSz(sz.width, sz.height * 2 / 3);
4182                 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
4183                 dst = _dst.getMat();
4184
4185                 int srcstep = (int)src.step;
4186                 const uchar* y = src.ptr();
4187                 const uchar* u = y + srcstep * dstSz.height;
4188                 const uchar* v = y + srcstep * (dstSz.height + dstSz.height/4) + (dstSz.width/2) * ((dstSz.height % 4)/2);
4189
4190                 int ustepIdx = 0;
4191                 int vstepIdx = dstSz.height % 4 == 2 ? 1 : 0;
4192
4193                 if(uIdx == 1) { std::swap(u ,v), std::swap(ustepIdx, vstepIdx); }
4194
4195                 switch(dcn*10 + bIdx)
4196                 {
4197                     case 30: cvtYUV420p2RGB<0>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
4198                     case 32: cvtYUV420p2RGB<2>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
4199                     case 40: cvtYUV420p2RGBA<0>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
4200                     case 42: cvtYUV420p2RGBA<2>(dst, srcstep, y, u, v, ustepIdx, vstepIdx); break;
4201                     default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
4202                 };
4203             }
4204             break;
4205         case CV_YUV2GRAY_420:
4206             {
4207                 if (dcn <= 0) dcn = 1;
4208
4209                 CV_Assert( dcn == 1 );
4210                 CV_Assert( sz.width % 2 == 0 && sz.height % 3 == 0 && depth == CV_8U );
4211
4212                 Size dstSz(sz.width, sz.height * 2 / 3);
4213                 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
4214                 dst = _dst.getMat();
4215
4216                 src(Range(0, dstSz.height), Range::all()).copyTo(dst);
4217             }
4218             break;
4219         case CV_RGB2YUV_YV12: case CV_BGR2YUV_YV12: case CV_RGBA2YUV_YV12: case CV_BGRA2YUV_YV12:
4220         case CV_RGB2YUV_IYUV: case CV_BGR2YUV_IYUV: case CV_RGBA2YUV_IYUV: case CV_BGRA2YUV_IYUV:
4221             {
4222                 if (dcn <= 0) dcn = 1;
4223                 const int bIdx = (code == CV_BGR2YUV_IYUV || code == CV_BGRA2YUV_IYUV || code == CV_BGR2YUV_YV12 || code == CV_BGRA2YUV_YV12) ? 0 : 2;
4224                 const int uIdx = (code == CV_BGR2YUV_IYUV || code == CV_BGRA2YUV_IYUV || code == CV_RGB2YUV_IYUV || code == CV_RGBA2YUV_IYUV) ? 1 : 2;
4225
4226                 CV_Assert( (scn == 3 || scn == 4) && depth == CV_8U );
4227                 CV_Assert( dcn == 1 );
4228                 CV_Assert( sz.width % 2 == 0 && sz.height % 2 == 0 );
4229
4230                 Size dstSz(sz.width, sz.height / 2 * 3);
4231                 _dst.create(dstSz, CV_MAKETYPE(depth, dcn));
4232                 dst = _dst.getMat();
4233
4234                 switch(bIdx + uIdx*10)
4235                 {
4236                     case 10: cvtRGBtoYUV420p<0, 1>(src, dst); break;
4237                     case 12: cvtRGBtoYUV420p<2, 1>(src, dst); break;
4238                     case 20: cvtRGBtoYUV420p<0, 2>(src, dst); break;
4239                     case 22: cvtRGBtoYUV420p<2, 2>(src, dst); break;
4240                     default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
4241                 };
4242             }
4243             break;
4244         case CV_YUV2RGB_UYVY: case CV_YUV2BGR_UYVY: case CV_YUV2RGBA_UYVY: case CV_YUV2BGRA_UYVY:
4245         case CV_YUV2RGB_YUY2: case CV_YUV2BGR_YUY2: case CV_YUV2RGB_YVYU: case CV_YUV2BGR_YVYU:
4246         case CV_YUV2RGBA_YUY2: case CV_YUV2BGRA_YUY2: case CV_YUV2RGBA_YVYU: case CV_YUV2BGRA_YVYU:
4247             {
4248                 //http://www.fourcc.org/yuv.php#UYVY
4249                 //http://www.fourcc.org/yuv.php#YUY2
4250                 //http://www.fourcc.org/yuv.php#YVYU
4251
4252                 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;
4253                 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;
4254                 const int ycn  = (code==CV_YUV2RGB_UYVY || code==CV_YUV2BGR_UYVY || code==CV_YUV2RGBA_UYVY || code==CV_YUV2BGRA_UYVY) ? 1 : 0;
4255                 const int uIdx = (code==CV_YUV2RGB_YVYU || code==CV_YUV2BGR_YVYU || code==CV_YUV2RGBA_YVYU || code==CV_YUV2BGRA_YVYU) ? 1 : 0;
4256
4257                 CV_Assert( dcn == 3 || dcn == 4 );
4258                 CV_Assert( scn == 2 && depth == CV_8U );
4259
4260                 _dst.create(sz, CV_8UC(dcn));
4261                 dst = _dst.getMat();
4262
4263                 switch(dcn*1000 + bIdx*100 + uIdx*10 + ycn)
4264                 {
4265                     case 3000: cvtYUV422toRGB<0,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4266                     case 3001: cvtYUV422toRGB<0,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4267                     case 3010: cvtYUV422toRGB<0,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4268                     case 3011: cvtYUV422toRGB<0,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4269                     case 3200: cvtYUV422toRGB<2,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4270                     case 3201: cvtYUV422toRGB<2,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4271                     case 3210: cvtYUV422toRGB<2,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4272                     case 3211: cvtYUV422toRGB<2,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4273                     case 4000: cvtYUV422toRGBA<0,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4274                     case 4001: cvtYUV422toRGBA<0,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4275                     case 4010: cvtYUV422toRGBA<0,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4276                     case 4011: cvtYUV422toRGBA<0,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4277                     case 4200: cvtYUV422toRGBA<2,0,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4278                     case 4201: cvtYUV422toRGBA<2,0,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4279                     case 4210: cvtYUV422toRGBA<2,1,0>(dst, (int)src.step, src.ptr<uchar>()); break;
4280                     case 4211: cvtYUV422toRGBA<2,1,1>(dst, (int)src.step, src.ptr<uchar>()); break;
4281                     default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break;
4282                 };
4283             }
4284             break;
4285         case CV_YUV2GRAY_UYVY: case CV_YUV2GRAY_YUY2:
4286             {
4287                 if (dcn <= 0) dcn = 1;
4288
4289                 CV_Assert( dcn == 1 );
4290                 CV_Assert( scn == 2 && depth == CV_8U );
4291
4292                 extractChannel(_src, _dst, code == CV_YUV2GRAY_UYVY ? 1 : 0);
4293             }
4294             break;
4295         case CV_RGBA2mRGBA:
4296             {
4297                 if (dcn <= 0) dcn = 4;
4298                 CV_Assert( scn == 4 && dcn == 4 );
4299
4300                 _dst.create(sz, CV_MAKETYPE(depth, dcn));
4301                 dst = _dst.getMat();
4302
4303                 if( depth == CV_8U )
4304                 {
4305 #if defined(HAVE_IPP)
4306                     if (CvtColorIPPLoop(src, dst, IPPGeneralFunctor((ippiGeneralFunc)ippiAlphaPremul_8u_AC4R)))
4307                         return;
4308                     setIppErrorStatus();
4309 #endif
4310                     CvtColorLoop(src, dst, RGBA2mRGBA<uchar>());
4311                 }
4312                 else
4313                 {
4314                     CV_Error( CV_StsBadArg, "Unsupported image depth" );
4315                 }
4316             }
4317             break;
4318         case CV_mRGBA2RGBA:
4319             {
4320                 if (dcn <= 0) dcn = 4;
4321                 CV_Assert( scn == 4 && dcn == 4 );
4322
4323                 _dst.create(sz, CV_MAKETYPE(depth, dcn));
4324                 dst = _dst.getMat();
4325
4326                 if( depth == CV_8U )
4327                     CvtColorLoop(src, dst, mRGBA2RGBA<uchar>());
4328                 else
4329                 {
4330                     CV_Error( CV_StsBadArg, "Unsupported image depth" );
4331                 }
4332             }
4333             break;
4334         default:
4335             CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" );
4336     }
4337 }
4338
4339 CV_IMPL void
4340 cvCvtColor( const CvArr* srcarr, CvArr* dstarr, int code )
4341 {
4342     cv::Mat src = cv::cvarrToMat(srcarr), dst0 = cv::cvarrToMat(dstarr), dst = dst0;
4343     CV_Assert( src.depth() == dst.depth() );
4344
4345     cv::cvtColor(src, dst, code, dst.channels());
4346     CV_Assert( dst.data == dst0.data );
4347 }
4348
4349
4350 /* End of file. */