d6abaa4adbf80dfd5be07984c787ece61721a54a
[profile/ivi/opencv.git] / modules / core / src / convert.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-2011, 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 #include "precomp.hpp"
44 #include "opencl_kernels.hpp"
45
46 namespace cv
47 {
48
49 /****************************************************************************************\
50 *                                       split & merge                                    *
51 \****************************************************************************************/
52
53 template<typename T> static void
54 split_( const T* src, T** dst, int len, int cn )
55 {
56     int k = cn % 4 ? cn % 4 : 4;
57     int i, j;
58     if( k == 1 )
59     {
60         T* dst0 = dst[0];
61         for( i = j = 0; i < len; i++, j += cn )
62             dst0[i] = src[j];
63     }
64     else if( k == 2 )
65     {
66         T *dst0 = dst[0], *dst1 = dst[1];
67         for( i = j = 0; i < len; i++, j += cn )
68         {
69             dst0[i] = src[j];
70             dst1[i] = src[j+1];
71         }
72     }
73     else if( k == 3 )
74     {
75         T *dst0 = dst[0], *dst1 = dst[1], *dst2 = dst[2];
76         for( i = j = 0; i < len; i++, j += cn )
77         {
78             dst0[i] = src[j];
79             dst1[i] = src[j+1];
80             dst2[i] = src[j+2];
81         }
82     }
83     else
84     {
85         T *dst0 = dst[0], *dst1 = dst[1], *dst2 = dst[2], *dst3 = dst[3];
86         for( i = j = 0; i < len; i++, j += cn )
87         {
88             dst0[i] = src[j]; dst1[i] = src[j+1];
89             dst2[i] = src[j+2]; dst3[i] = src[j+3];
90         }
91     }
92
93     for( ; k < cn; k += 4 )
94     {
95         T *dst0 = dst[k], *dst1 = dst[k+1], *dst2 = dst[k+2], *dst3 = dst[k+3];
96         for( i = 0, j = k; i < len; i++, j += cn )
97         {
98             dst0[i] = src[j]; dst1[i] = src[j+1];
99             dst2[i] = src[j+2]; dst3[i] = src[j+3];
100         }
101     }
102 }
103
104 template<typename T> static void
105 merge_( const T** src, T* dst, int len, int cn )
106 {
107     int k = cn % 4 ? cn % 4 : 4;
108     int i, j;
109     if( k == 1 )
110     {
111         const T* src0 = src[0];
112         for( i = j = 0; i < len; i++, j += cn )
113             dst[j] = src0[i];
114     }
115     else if( k == 2 )
116     {
117         const T *src0 = src[0], *src1 = src[1];
118         for( i = j = 0; i < len; i++, j += cn )
119         {
120             dst[j] = src0[i];
121             dst[j+1] = src1[i];
122         }
123     }
124     else if( k == 3 )
125     {
126         const T *src0 = src[0], *src1 = src[1], *src2 = src[2];
127         for( i = j = 0; i < len; i++, j += cn )
128         {
129             dst[j] = src0[i];
130             dst[j+1] = src1[i];
131             dst[j+2] = src2[i];
132         }
133     }
134     else
135     {
136         const T *src0 = src[0], *src1 = src[1], *src2 = src[2], *src3 = src[3];
137         for( i = j = 0; i < len; i++, j += cn )
138         {
139             dst[j] = src0[i]; dst[j+1] = src1[i];
140             dst[j+2] = src2[i]; dst[j+3] = src3[i];
141         }
142     }
143
144     for( ; k < cn; k += 4 )
145     {
146         const T *src0 = src[k], *src1 = src[k+1], *src2 = src[k+2], *src3 = src[k+3];
147         for( i = 0, j = k; i < len; i++, j += cn )
148         {
149             dst[j] = src0[i]; dst[j+1] = src1[i];
150             dst[j+2] = src2[i]; dst[j+3] = src3[i];
151         }
152     }
153 }
154
155 static void split8u(const uchar* src, uchar** dst, int len, int cn )
156 {
157     split_(src, dst, len, cn);
158 }
159
160 static void split16u(const ushort* src, ushort** dst, int len, int cn )
161 {
162     split_(src, dst, len, cn);
163 }
164
165 static void split32s(const int* src, int** dst, int len, int cn )
166 {
167     split_(src, dst, len, cn);
168 }
169
170 static void split64s(const int64* src, int64** dst, int len, int cn )
171 {
172     split_(src, dst, len, cn);
173 }
174
175 static void merge8u(const uchar** src, uchar* dst, int len, int cn )
176 {
177     merge_(src, dst, len, cn);
178 }
179
180 static void merge16u(const ushort** src, ushort* dst, int len, int cn )
181 {
182     merge_(src, dst, len, cn);
183 }
184
185 static void merge32s(const int** src, int* dst, int len, int cn )
186 {
187     merge_(src, dst, len, cn);
188 }
189
190 static void merge64s(const int64** src, int64* dst, int len, int cn )
191 {
192     merge_(src, dst, len, cn);
193 }
194
195 typedef void (*SplitFunc)(const uchar* src, uchar** dst, int len, int cn);
196 typedef void (*MergeFunc)(const uchar** src, uchar* dst, int len, int cn);
197
198 static SplitFunc getSplitFunc(int depth)
199 {
200     static SplitFunc splitTab[] =
201     {
202         (SplitFunc)GET_OPTIMIZED(split8u), (SplitFunc)GET_OPTIMIZED(split8u), (SplitFunc)GET_OPTIMIZED(split16u), (SplitFunc)GET_OPTIMIZED(split16u),
203         (SplitFunc)GET_OPTIMIZED(split32s), (SplitFunc)GET_OPTIMIZED(split32s), (SplitFunc)GET_OPTIMIZED(split64s), 0
204     };
205
206     return splitTab[depth];
207 }
208
209 static MergeFunc getMergeFunc(int depth)
210 {
211     static MergeFunc mergeTab[] =
212     {
213         (MergeFunc)GET_OPTIMIZED(merge8u), (MergeFunc)GET_OPTIMIZED(merge8u), (MergeFunc)GET_OPTIMIZED(merge16u), (MergeFunc)GET_OPTIMIZED(merge16u),
214         (MergeFunc)GET_OPTIMIZED(merge32s), (MergeFunc)GET_OPTIMIZED(merge32s), (MergeFunc)GET_OPTIMIZED(merge64s), 0
215     };
216
217     return mergeTab[depth];
218 }
219
220 }
221
222 void cv::split(const Mat& src, Mat* mv)
223 {
224     int k, depth = src.depth(), cn = src.channels();
225     if( cn == 1 )
226     {
227         src.copyTo(mv[0]);
228         return;
229     }
230
231     SplitFunc func = getSplitFunc(depth);
232     CV_Assert( func != 0 );
233
234     int esz = (int)src.elemSize(), esz1 = (int)src.elemSize1();
235     int blocksize0 = (BLOCK_SIZE + esz-1)/esz;
236     AutoBuffer<uchar> _buf((cn+1)*(sizeof(Mat*) + sizeof(uchar*)) + 16);
237     const Mat** arrays = (const Mat**)(uchar*)_buf;
238     uchar** ptrs = (uchar**)alignPtr(arrays + cn + 1, 16);
239
240     arrays[0] = &src;
241     for( k = 0; k < cn; k++ )
242     {
243         mv[k].create(src.dims, src.size, depth);
244         arrays[k+1] = &mv[k];
245     }
246
247     NAryMatIterator it(arrays, ptrs, cn+1);
248     int total = (int)it.size, blocksize = cn <= 4 ? total : std::min(total, blocksize0);
249
250     for( size_t i = 0; i < it.nplanes; i++, ++it )
251     {
252         for( int j = 0; j < total; j += blocksize )
253         {
254             int bsz = std::min(total - j, blocksize);
255             func( ptrs[0], &ptrs[1], bsz, cn );
256
257             if( j + blocksize < total )
258             {
259                 ptrs[0] += bsz*esz;
260                 for( k = 0; k < cn; k++ )
261                     ptrs[k+1] += bsz*esz1;
262             }
263         }
264     }
265 }
266
267 #ifdef HAVE_OPENCL
268
269 namespace cv {
270
271 static bool ocl_split( InputArray _m, OutputArrayOfArrays _mv )
272 {
273     int type = _m.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
274             rowsPerWI = ocl::Device::getDefault().isIntel() ? 4 : 1;
275
276     String dstargs, processelem, indexdecl;
277     for (int i = 0; i < cn; ++i)
278     {
279         dstargs += format("DECLARE_DST_PARAM(%d)", i);
280         indexdecl += format("DECLARE_INDEX(%d)", i);
281         processelem += format("PROCESS_ELEM(%d)", i);
282     }
283
284     ocl::Kernel k("split", ocl::core::split_merge_oclsrc,
285                   format("-D T=%s -D OP_SPLIT -D cn=%d -D DECLARE_DST_PARAMS=%s"
286                          " -D PROCESS_ELEMS_N=%s -D DECLARE_INDEX_N=%s",
287                          ocl::memopTypeToStr(depth), cn, dstargs.c_str(),
288                          processelem.c_str(), indexdecl.c_str()));
289     if (k.empty())
290         return false;
291
292     Size size = _m.size();
293     _mv.create(cn, 1, depth);
294     for (int i = 0; i < cn; ++i)
295         _mv.create(size, depth, i);
296
297     std::vector<UMat> dst;
298     _mv.getUMatVector(dst);
299
300     int argidx = k.set(0, ocl::KernelArg::ReadOnly(_m.getUMat()));
301     for (int i = 0; i < cn; ++i)
302         argidx = k.set(argidx, ocl::KernelArg::WriteOnlyNoSize(dst[i]));
303     k.set(argidx, rowsPerWI);
304
305     size_t globalsize[2] = { size.width, (size.height + rowsPerWI - 1) / rowsPerWI };
306     return k.run(2, globalsize, NULL, false);
307 }
308
309 }
310
311 #endif
312
313 void cv::split(InputArray _m, OutputArrayOfArrays _mv)
314 {
315     CV_OCL_RUN(_m.dims() <= 2 && _mv.isUMatVector(),
316                ocl_split(_m, _mv))
317
318     Mat m = _m.getMat();
319     if( m.empty() )
320     {
321         _mv.release();
322         return;
323     }
324
325     CV_Assert( !_mv.fixedType() || _mv.empty() || _mv.type() == m.depth() );
326
327     Size size = m.size();
328     int depth = m.depth(), cn = m.channels();
329     _mv.create(cn, 1, depth);
330     for (int i = 0; i < cn; ++i)
331         _mv.create(size, depth, i);
332
333     std::vector<Mat> dst;
334     _mv.getMatVector(dst);
335
336     split(m, &dst[0]);
337 }
338
339 void cv::merge(const Mat* mv, size_t n, OutputArray _dst)
340 {
341     CV_Assert( mv && n > 0 );
342
343     int depth = mv[0].depth();
344     bool allch1 = true;
345     int k, cn = 0;
346     size_t i;
347
348     for( i = 0; i < n; i++ )
349     {
350         CV_Assert(mv[i].size == mv[0].size && mv[i].depth() == depth);
351         allch1 = allch1 && mv[i].channels() == 1;
352         cn += mv[i].channels();
353     }
354
355     CV_Assert( 0 < cn && cn <= CV_CN_MAX );
356     _dst.create(mv[0].dims, mv[0].size, CV_MAKETYPE(depth, cn));
357     Mat dst = _dst.getMat();
358
359     if( n == 1 )
360     {
361         mv[0].copyTo(dst);
362         return;
363     }
364
365     if( !allch1 )
366     {
367         AutoBuffer<int> pairs(cn*2);
368         int j, ni=0;
369
370         for( i = 0, j = 0; i < n; i++, j += ni )
371         {
372             ni = mv[i].channels();
373             for( k = 0; k < ni; k++ )
374             {
375                 pairs[(j+k)*2] = j + k;
376                 pairs[(j+k)*2+1] = j + k;
377             }
378         }
379         mixChannels( mv, n, &dst, 1, &pairs[0], cn );
380         return;
381     }
382
383     size_t esz = dst.elemSize(), esz1 = dst.elemSize1();
384     int blocksize0 = (int)((BLOCK_SIZE + esz-1)/esz);
385     AutoBuffer<uchar> _buf((cn+1)*(sizeof(Mat*) + sizeof(uchar*)) + 16);
386     const Mat** arrays = (const Mat**)(uchar*)_buf;
387     uchar** ptrs = (uchar**)alignPtr(arrays + cn + 1, 16);
388
389     arrays[0] = &dst;
390     for( k = 0; k < cn; k++ )
391         arrays[k+1] = &mv[k];
392
393     NAryMatIterator it(arrays, ptrs, cn+1);
394     int total = (int)it.size, blocksize = cn <= 4 ? total : std::min(total, blocksize0);
395     MergeFunc func = getMergeFunc(depth);
396
397     for( i = 0; i < it.nplanes; i++, ++it )
398     {
399         for( int j = 0; j < total; j += blocksize )
400         {
401             int bsz = std::min(total - j, blocksize);
402             func( (const uchar**)&ptrs[1], ptrs[0], bsz, cn );
403
404             if( j + blocksize < total )
405             {
406                 ptrs[0] += bsz*esz;
407                 for( int t = 0; t < cn; t++ )
408                     ptrs[t+1] += bsz*esz1;
409             }
410         }
411     }
412 }
413
414 #ifdef HAVE_OPENCL
415
416 namespace cv {
417
418 static bool ocl_merge( InputArrayOfArrays _mv, OutputArray _dst )
419 {
420     std::vector<UMat> src, ksrc;
421     _mv.getUMatVector(src);
422     CV_Assert(!src.empty());
423
424     int type = src[0].type(), depth = CV_MAT_DEPTH(type),
425             rowsPerWI = ocl::Device::getDefault().isIntel() ? 4 : 1;
426     Size size = src[0].size();
427
428     for (size_t i = 0, srcsize = src.size(); i < srcsize; ++i)
429     {
430         int itype = src[i].type(), icn = CV_MAT_CN(itype), idepth = CV_MAT_DEPTH(itype),
431                 esz1 = CV_ELEM_SIZE1(idepth);
432         if (src[i].dims > 2)
433             return false;
434
435         CV_Assert(size == src[i].size() && depth == idepth);
436
437         for (int cn = 0; cn < icn; ++cn)
438         {
439             UMat tsrc = src[i];
440             tsrc.offset += cn * esz1;
441             ksrc.push_back(tsrc);
442         }
443     }
444     int dcn = (int)ksrc.size();
445
446     String srcargs, processelem, cndecl, indexdecl;
447     for (int i = 0; i < dcn; ++i)
448     {
449         srcargs += format("DECLARE_SRC_PARAM(%d)", i);
450         processelem += format("PROCESS_ELEM(%d)", i);
451         indexdecl += format("DECLARE_INDEX(%d)", i);
452         cndecl += format(" -D scn%d=%d", i, ksrc[i].channels());
453     }
454
455     ocl::Kernel k("merge", ocl::core::split_merge_oclsrc,
456                   format("-D OP_MERGE -D cn=%d -D T=%s -D DECLARE_SRC_PARAMS_N=%s"
457                          " -D DECLARE_INDEX_N=%s -D PROCESS_ELEMS_N=%s%s",
458                          dcn, ocl::memopTypeToStr(depth), srcargs.c_str(),
459                          indexdecl.c_str(), processelem.c_str(), cndecl.c_str()));
460     if (k.empty())
461         return false;
462
463     _dst.create(size, CV_MAKE_TYPE(depth, dcn));
464     UMat dst = _dst.getUMat();
465
466     int argidx = 0;
467     for (int i = 0; i < dcn; ++i)
468         argidx = k.set(argidx, ocl::KernelArg::ReadOnlyNoSize(ksrc[i]));
469     argidx = k.set(argidx, ocl::KernelArg::WriteOnly(dst));
470     k.set(argidx, rowsPerWI);
471
472     size_t globalsize[2] = { dst.cols, (dst.rows + rowsPerWI - 1) / rowsPerWI };
473     return k.run(2, globalsize, NULL, false);
474 }
475
476 }
477
478 #endif
479
480 void cv::merge(InputArrayOfArrays _mv, OutputArray _dst)
481 {
482     CV_OCL_RUN(_mv.isUMatVector() && _dst.isUMat(),
483                ocl_merge(_mv, _dst))
484
485     std::vector<Mat> mv;
486     _mv.getMatVector(mv);
487     merge(!mv.empty() ? &mv[0] : 0, mv.size(), _dst);
488 }
489
490 /****************************************************************************************\
491 *                       Generalized split/merge: mixing channels                         *
492 \****************************************************************************************/
493
494 namespace cv
495 {
496
497 template<typename T> static void
498 mixChannels_( const T** src, const int* sdelta,
499               T** dst, const int* ddelta,
500               int len, int npairs )
501 {
502     int i, k;
503     for( k = 0; k < npairs; k++ )
504     {
505         const T* s = src[k];
506         T* d = dst[k];
507         int ds = sdelta[k], dd = ddelta[k];
508         if( s )
509         {
510             for( i = 0; i <= len - 2; i += 2, s += ds*2, d += dd*2 )
511             {
512                 T t0 = s[0], t1 = s[ds];
513                 d[0] = t0; d[dd] = t1;
514             }
515             if( i < len )
516                 d[0] = s[0];
517         }
518         else
519         {
520             for( i = 0; i <= len - 2; i += 2, d += dd*2 )
521                 d[0] = d[dd] = 0;
522             if( i < len )
523                 d[0] = 0;
524         }
525     }
526 }
527
528
529 static void mixChannels8u( const uchar** src, const int* sdelta,
530                            uchar** dst, const int* ddelta,
531                            int len, int npairs )
532 {
533     mixChannels_(src, sdelta, dst, ddelta, len, npairs);
534 }
535
536 static void mixChannels16u( const ushort** src, const int* sdelta,
537                             ushort** dst, const int* ddelta,
538                             int len, int npairs )
539 {
540     mixChannels_(src, sdelta, dst, ddelta, len, npairs);
541 }
542
543 static void mixChannels32s( const int** src, const int* sdelta,
544                             int** dst, const int* ddelta,
545                             int len, int npairs )
546 {
547     mixChannels_(src, sdelta, dst, ddelta, len, npairs);
548 }
549
550 static void mixChannels64s( const int64** src, const int* sdelta,
551                             int64** dst, const int* ddelta,
552                             int len, int npairs )
553 {
554     mixChannels_(src, sdelta, dst, ddelta, len, npairs);
555 }
556
557 typedef void (*MixChannelsFunc)( const uchar** src, const int* sdelta,
558         uchar** dst, const int* ddelta, int len, int npairs );
559
560 static MixChannelsFunc getMixchFunc(int depth)
561 {
562     static MixChannelsFunc mixchTab[] =
563     {
564         (MixChannelsFunc)mixChannels8u, (MixChannelsFunc)mixChannels8u, (MixChannelsFunc)mixChannels16u,
565         (MixChannelsFunc)mixChannels16u, (MixChannelsFunc)mixChannels32s, (MixChannelsFunc)mixChannels32s,
566         (MixChannelsFunc)mixChannels64s, 0
567     };
568
569     return mixchTab[depth];
570 }
571
572 }
573
574 void cv::mixChannels( const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, const int* fromTo, size_t npairs )
575 {
576     if( npairs == 0 )
577         return;
578     CV_Assert( src && nsrcs > 0 && dst && ndsts > 0 && fromTo && npairs > 0 );
579
580     size_t i, j, k, esz1 = dst[0].elemSize1();
581     int depth = dst[0].depth();
582
583     AutoBuffer<uchar> buf((nsrcs + ndsts + 1)*(sizeof(Mat*) + sizeof(uchar*)) + npairs*(sizeof(uchar*)*2 + sizeof(int)*6));
584     const Mat** arrays = (const Mat**)(uchar*)buf;
585     uchar** ptrs = (uchar**)(arrays + nsrcs + ndsts);
586     const uchar** srcs = (const uchar**)(ptrs + nsrcs + ndsts + 1);
587     uchar** dsts = (uchar**)(srcs + npairs);
588     int* tab = (int*)(dsts + npairs);
589     int *sdelta = (int*)(tab + npairs*4), *ddelta = sdelta + npairs;
590
591     for( i = 0; i < nsrcs; i++ )
592         arrays[i] = &src[i];
593     for( i = 0; i < ndsts; i++ )
594         arrays[i + nsrcs] = &dst[i];
595     ptrs[nsrcs + ndsts] = 0;
596
597     for( i = 0; i < npairs; i++ )
598     {
599         int i0 = fromTo[i*2], i1 = fromTo[i*2+1];
600         if( i0 >= 0 )
601         {
602             for( j = 0; j < nsrcs; i0 -= src[j].channels(), j++ )
603                 if( i0 < src[j].channels() )
604                     break;
605             CV_Assert(j < nsrcs && src[j].depth() == depth);
606             tab[i*4] = (int)j; tab[i*4+1] = (int)(i0*esz1);
607             sdelta[i] = src[j].channels();
608         }
609         else
610         {
611             tab[i*4] = (int)(nsrcs + ndsts); tab[i*4+1] = 0;
612             sdelta[i] = 0;
613         }
614
615         for( j = 0; j < ndsts; i1 -= dst[j].channels(), j++ )
616             if( i1 < dst[j].channels() )
617                 break;
618         CV_Assert(i1 >= 0 && j < ndsts && dst[j].depth() == depth);
619         tab[i*4+2] = (int)(j + nsrcs); tab[i*4+3] = (int)(i1*esz1);
620         ddelta[i] = dst[j].channels();
621     }
622
623     NAryMatIterator it(arrays, ptrs, (int)(nsrcs + ndsts));
624     int total = (int)it.size, blocksize = std::min(total, (int)((BLOCK_SIZE + esz1-1)/esz1));
625     MixChannelsFunc func = getMixchFunc(depth);
626
627     for( i = 0; i < it.nplanes; i++, ++it )
628     {
629         for( k = 0; k < npairs; k++ )
630         {
631             srcs[k] = ptrs[tab[k*4]] + tab[k*4+1];
632             dsts[k] = ptrs[tab[k*4+2]] + tab[k*4+3];
633         }
634
635         for( int t = 0; t < total; t += blocksize )
636         {
637             int bsz = std::min(total - t, blocksize);
638             func( srcs, sdelta, dsts, ddelta, bsz, (int)npairs );
639
640             if( t + blocksize < total )
641                 for( k = 0; k < npairs; k++ )
642                 {
643                     srcs[k] += blocksize*sdelta[k]*esz1;
644                     dsts[k] += blocksize*ddelta[k]*esz1;
645                 }
646         }
647     }
648 }
649
650 #ifdef HAVE_OPENCL
651
652 namespace cv {
653
654 static void getUMatIndex(const std::vector<UMat> & um, int cn, int & idx, int & cnidx)
655 {
656     int totalChannels = 0;
657     for (size_t i = 0, size = um.size(); i < size; ++i)
658     {
659         int ccn = um[i].channels();
660         totalChannels += ccn;
661
662         if (totalChannels == cn)
663         {
664             idx = (int)(i + 1);
665             cnidx = 0;
666             return;
667         }
668         else if (totalChannels > cn)
669         {
670             idx = (int)i;
671             cnidx = i == 0 ? cn : (cn - totalChannels + ccn);
672             return;
673         }
674     }
675
676     idx = cnidx = -1;
677 }
678
679 static bool ocl_mixChannels(InputArrayOfArrays _src, InputOutputArrayOfArrays _dst,
680                             const int* fromTo, size_t npairs)
681 {
682     std::vector<UMat> src, dst;
683     _src.getUMatVector(src);
684     _dst.getUMatVector(dst);
685
686     size_t nsrc = src.size(), ndst = dst.size();
687     CV_Assert(nsrc > 0 && ndst > 0);
688
689     Size size = src[0].size();
690     int depth = src[0].depth(), esz = CV_ELEM_SIZE(depth),
691             rowsPerWI = ocl::Device::getDefault().isIntel() ? 4 : 1;
692
693     for (size_t i = 1, ssize = src.size(); i < ssize; ++i)
694         CV_Assert(src[i].size() == size && src[i].depth() == depth);
695     for (size_t i = 0, dsize = dst.size(); i < dsize; ++i)
696         CV_Assert(dst[i].size() == size && dst[i].depth() == depth);
697
698     String declsrc, decldst, declproc, declcn, indexdecl;
699     std::vector<UMat> srcargs(npairs), dstargs(npairs);
700
701     for (size_t i = 0; i < npairs; ++i)
702     {
703         int scn = fromTo[i<<1], dcn = fromTo[(i<<1) + 1];
704         int src_idx, src_cnidx, dst_idx, dst_cnidx;
705
706         getUMatIndex(src, scn, src_idx, src_cnidx);
707         getUMatIndex(dst, dcn, dst_idx, dst_cnidx);
708
709         CV_Assert(dst_idx >= 0 && src_idx >= 0);
710
711         srcargs[i] = src[src_idx];
712         srcargs[i].offset += src_cnidx * esz;
713
714         dstargs[i] = dst[dst_idx];
715         dstargs[i].offset += dst_cnidx * esz;
716
717         declsrc += format("DECLARE_INPUT_MAT(%d)", i);
718         decldst += format("DECLARE_OUTPUT_MAT(%d)", i);
719         indexdecl += format("DECLARE_INDEX(%d)", i);
720         declproc += format("PROCESS_ELEM(%d)", i);
721         declcn += format(" -D scn%d=%d -D dcn%d=%d", i, src[src_idx].channels(), i, dst[dst_idx].channels());
722     }
723
724     ocl::Kernel k("mixChannels", ocl::core::mixchannels_oclsrc,
725                   format("-D T=%s -D DECLARE_INPUT_MAT_N=%s -D DECLARE_OUTPUT_MAT_N=%s"
726                          " -D PROCESS_ELEM_N=%s -D DECLARE_INDEX_N=%s%s",
727                          ocl::memopTypeToStr(depth), declsrc.c_str(), decldst.c_str(),
728                          declproc.c_str(), indexdecl.c_str(), declcn.c_str()));
729     if (k.empty())
730         return false;
731
732     int argindex = 0;
733     for (size_t i = 0; i < npairs; ++i)
734         argindex = k.set(argindex, ocl::KernelArg::ReadOnlyNoSize(srcargs[i]));
735     for (size_t i = 0; i < npairs; ++i)
736         argindex = k.set(argindex, ocl::KernelArg::WriteOnlyNoSize(dstargs[i]));
737     argindex = k.set(argindex, size.height);
738     argindex = k.set(argindex, size.width);
739     k.set(argindex, rowsPerWI);
740
741     size_t globalsize[2] = { size.width, (size.height + rowsPerWI - 1) / rowsPerWI };
742     return k.run(2, globalsize, NULL, false);
743 }
744
745 }
746
747 #endif
748
749 void cv::mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst,
750                  const int* fromTo, size_t npairs)
751 {
752     if (npairs == 0 || fromTo == NULL)
753         return;
754
755     CV_OCL_RUN(dst.isUMatVector(),
756                ocl_mixChannels(src, dst, fromTo, npairs))
757
758     bool src_is_mat = src.kind() != _InputArray::STD_VECTOR_MAT &&
759             src.kind() != _InputArray::STD_VECTOR_VECTOR &&
760             src.kind() != _InputArray::STD_VECTOR_UMAT;
761     bool dst_is_mat = dst.kind() != _InputArray::STD_VECTOR_MAT &&
762             dst.kind() != _InputArray::STD_VECTOR_VECTOR &&
763             dst.kind() != _InputArray::STD_VECTOR_UMAT;
764     int i;
765     int nsrc = src_is_mat ? 1 : (int)src.total();
766     int ndst = dst_is_mat ? 1 : (int)dst.total();
767
768     CV_Assert(nsrc > 0 && ndst > 0);
769     cv::AutoBuffer<Mat> _buf(nsrc + ndst);
770     Mat* buf = _buf;
771     for( i = 0; i < nsrc; i++ )
772         buf[i] = src.getMat(src_is_mat ? -1 : i);
773     for( i = 0; i < ndst; i++ )
774         buf[nsrc + i] = dst.getMat(dst_is_mat ? -1 : i);
775     mixChannels(&buf[0], nsrc, &buf[nsrc], ndst, fromTo, npairs);
776 }
777
778 void cv::mixChannels(InputArrayOfArrays src, InputOutputArrayOfArrays dst,
779                      const std::vector<int>& fromTo)
780 {
781     if (fromTo.empty())
782         return;
783
784     CV_OCL_RUN(dst.isUMatVector(),
785                ocl_mixChannels(src, dst, &fromTo[0], fromTo.size()>>1))
786
787     bool src_is_mat = src.kind() != _InputArray::STD_VECTOR_MAT &&
788             src.kind() != _InputArray::STD_VECTOR_VECTOR &&
789             src.kind() != _InputArray::STD_VECTOR_UMAT;
790     bool dst_is_mat = dst.kind() != _InputArray::STD_VECTOR_MAT &&
791             dst.kind() != _InputArray::STD_VECTOR_VECTOR &&
792             dst.kind() != _InputArray::STD_VECTOR_UMAT;
793     int i;
794     int nsrc = src_is_mat ? 1 : (int)src.total();
795     int ndst = dst_is_mat ? 1 : (int)dst.total();
796
797     CV_Assert(fromTo.size()%2 == 0 && nsrc > 0 && ndst > 0);
798     cv::AutoBuffer<Mat> _buf(nsrc + ndst);
799     Mat* buf = _buf;
800     for( i = 0; i < nsrc; i++ )
801         buf[i] = src.getMat(src_is_mat ? -1 : i);
802     for( i = 0; i < ndst; i++ )
803         buf[nsrc + i] = dst.getMat(dst_is_mat ? -1 : i);
804     mixChannels(&buf[0], nsrc, &buf[nsrc], ndst, &fromTo[0], fromTo.size()/2);
805 }
806
807 void cv::extractChannel(InputArray _src, OutputArray _dst, int coi)
808 {
809     int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
810     CV_Assert( 0 <= coi && coi < cn );
811     int ch[] = { coi, 0 };
812
813     if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat())
814     {
815         UMat src = _src.getUMat();
816         _dst.create(src.dims, &src.size[0], depth);
817         UMat dst = _dst.getUMat();
818         mixChannels(std::vector<UMat>(1, src), std::vector<UMat>(1, dst), ch, 1);
819         return;
820     }
821
822     Mat src = _src.getMat();
823     _dst.create(src.dims, &src.size[0], depth);
824     Mat dst = _dst.getMat();
825     mixChannels(&src, 1, &dst, 1, ch, 1);
826 }
827
828 void cv::insertChannel(InputArray _src, InputOutputArray _dst, int coi)
829 {
830     int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), scn = CV_MAT_CN(stype);
831     int dtype = _dst.type(), ddepth = CV_MAT_DEPTH(dtype), dcn = CV_MAT_CN(dtype);
832     CV_Assert( _src.sameSize(_dst) && sdepth == ddepth );
833     CV_Assert( 0 <= coi && coi < dcn && scn == 1 );
834
835     int ch[] = { 0, coi };
836     if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat())
837     {
838         UMat src = _src.getUMat(), dst = _dst.getUMat();
839         mixChannels(std::vector<UMat>(1, src), std::vector<UMat>(1, dst), ch, 1);
840         return;
841     }
842
843     Mat src = _src.getMat(), dst = _dst.getMat();
844     mixChannels(&src, 1, &dst, 1, ch, 1);
845 }
846
847 /****************************************************************************************\
848 *                                convertScale[Abs]                                       *
849 \****************************************************************************************/
850
851 namespace cv
852 {
853
854 template<typename T, typename DT, typename WT>
855 struct cvtScaleAbs_SSE2
856 {
857     int operator () (const T *, DT *, int, WT, WT) const
858     {
859         return 0;
860     }
861 };
862
863 #if CV_SSE2
864
865 template <>
866 struct cvtScaleAbs_SSE2<uchar, uchar, float>
867 {
868     int operator () (const uchar * src, uchar * dst, int width,
869                      float scale, float shift) const
870     {
871         int x = 0;
872
873         if (USE_SSE2)
874         {
875             __m128 v_scale = _mm_set1_ps(scale), v_shift = _mm_set1_ps(shift),
876                 v_zero_f = _mm_setzero_ps();
877             __m128i v_zero_i = _mm_setzero_si128();
878
879             for ( ; x <= width - 16; x += 16)
880             {
881                 __m128i v_src = _mm_loadu_si128((const __m128i *)(src + x));
882                 __m128i v_src12 = _mm_unpacklo_epi8(v_src, v_zero_i), v_src_34 = _mm_unpackhi_epi8(v_src, v_zero_i);
883                 __m128 v_dst1 = _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src12, v_zero_i)), v_scale), v_shift);
884                 v_dst1 = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst1), v_dst1);
885                 __m128 v_dst2 = _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src12, v_zero_i)), v_scale), v_shift);
886                 v_dst2 = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst2), v_dst2);
887                 __m128 v_dst3 = _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src_34, v_zero_i)), v_scale), v_shift);
888                 v_dst3 = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst3), v_dst3);
889                 __m128 v_dst4 = _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src_34, v_zero_i)), v_scale), v_shift);
890                 v_dst4 = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst4), v_dst4);
891
892                 __m128i v_dst_i = _mm_packus_epi16(_mm_packs_epi32(_mm_cvtps_epi32(v_dst1), _mm_cvtps_epi32(v_dst2)),
893                                                    _mm_packs_epi32(_mm_cvtps_epi32(v_dst3), _mm_cvtps_epi32(v_dst4)));
894                 _mm_storeu_si128((__m128i *)(dst + x), v_dst_i);
895             }
896         }
897
898         return x;
899     }
900 };
901
902 template <>
903 struct cvtScaleAbs_SSE2<ushort, uchar, float>
904 {
905     int operator () (const ushort * src, uchar * dst, int width,
906                      float scale, float shift) const
907     {
908         int x = 0;
909
910         if (USE_SSE2)
911         {
912             __m128 v_scale = _mm_set1_ps(scale), v_shift = _mm_set1_ps(shift),
913                 v_zero_f = _mm_setzero_ps();
914             __m128i v_zero_i = _mm_setzero_si128();
915
916             for ( ; x <= width - 8; x += 8)
917             {
918                 __m128i v_src = _mm_loadu_si128((const __m128i *)(src + x));
919                 __m128 v_dst1 = _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(_mm_unpacklo_epi16(v_src, v_zero_i)), v_scale), v_shift);
920                 v_dst1 = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst1), v_dst1);
921                 __m128 v_dst2 = _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(_mm_unpackhi_epi16(v_src, v_zero_i)), v_scale), v_shift);
922                 v_dst2 = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst2), v_dst2);
923
924                 __m128i v_dst_i = _mm_packus_epi16(_mm_packs_epi32(_mm_cvtps_epi32(v_dst1), _mm_cvtps_epi32(v_dst2)), v_zero_i);
925                 _mm_storel_epi64((__m128i *)(dst + x), v_dst_i);
926             }
927         }
928
929         return x;
930     }
931 };
932
933 template <>
934 struct cvtScaleAbs_SSE2<short, uchar, float>
935 {
936     int operator () (const short * src, uchar * dst, int width,
937                      float scale, float shift) const
938     {
939         int x = 0;
940
941         if (USE_SSE2)
942         {
943             __m128 v_scale = _mm_set1_ps(scale), v_shift = _mm_set1_ps(shift),
944                 v_zero_f = _mm_setzero_ps();
945             __m128i v_zero_i = _mm_setzero_si128();
946
947             for ( ; x <= width - 8; x += 8)
948             {
949                 __m128i v_src = _mm_loadu_si128((const __m128i *)(src + x));
950                 __m128 v_dst1 = _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpacklo_epi16(v_src, v_src), 16)), v_scale), v_shift);
951                 v_dst1 = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst1), v_dst1);
952                 __m128 v_dst2 = _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpackhi_epi16(v_src, v_src), 16)), v_scale), v_shift);
953                 v_dst2 = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst2), v_dst2);
954
955                 __m128i v_dst_i = _mm_packus_epi16(_mm_packs_epi32(_mm_cvtps_epi32(v_dst1), _mm_cvtps_epi32(v_dst2)), v_zero_i);
956                 _mm_storel_epi64((__m128i *)(dst + x), v_dst_i);
957             }
958         }
959
960         return x;
961     }
962 };
963
964 template <>
965 struct cvtScaleAbs_SSE2<int, uchar, float>
966 {
967     int operator () (const int * src, uchar * dst, int width,
968                      float scale, float shift) const
969     {
970         int x = 0;
971
972         if (USE_SSE2)
973         {
974             __m128 v_scale = _mm_set1_ps(scale), v_shift = _mm_set1_ps(shift),
975                 v_zero_f = _mm_setzero_ps();
976             __m128i v_zero_i = _mm_setzero_si128();
977
978             for ( ; x <= width - 8; x += 4)
979             {
980                 __m128i v_src = _mm_loadu_si128((const __m128i *)(src + x));
981                 __m128 v_dst1 = _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(v_src), v_scale), v_shift);
982                 v_dst1 = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst1), v_dst1);
983
984                 __m128i v_dst_i = _mm_packus_epi16(_mm_packs_epi32(_mm_cvtps_epi32(v_dst1), v_zero_i), v_zero_i);
985                 _mm_storel_epi64((__m128i *)(dst + x), v_dst_i);
986             }
987         }
988
989         return x;
990     }
991 };
992
993 template <>
994 struct cvtScaleAbs_SSE2<float, uchar, float>
995 {
996     int operator () (const float * src, uchar * dst, int width,
997                      float scale, float shift) const
998     {
999         int x = 0;
1000
1001         if (USE_SSE2)
1002         {
1003             __m128 v_scale = _mm_set1_ps(scale), v_shift = _mm_set1_ps(shift),
1004                 v_zero_f = _mm_setzero_ps();
1005             __m128i v_zero_i = _mm_setzero_si128();
1006
1007             for ( ; x <= width - 8; x += 4)
1008             {
1009                 __m128 v_dst = _mm_add_ps(_mm_mul_ps(_mm_loadu_ps(src + x), v_scale), v_shift);
1010                 v_dst = _mm_max_ps(_mm_sub_ps(v_zero_f, v_dst), v_dst);
1011
1012                 __m128i v_dst_i = _mm_packs_epi32(_mm_cvtps_epi32(v_dst), v_zero_i);
1013                 _mm_storel_epi64((__m128i *)(dst + x), _mm_packus_epi16(v_dst_i, v_zero_i));
1014             }
1015         }
1016
1017         return x;
1018     }
1019 };
1020
1021 #endif
1022
1023 template<typename T, typename DT, typename WT> static void
1024 cvtScaleAbs_( const T* src, size_t sstep,
1025               DT* dst, size_t dstep, Size size,
1026               WT scale, WT shift )
1027 {
1028     sstep /= sizeof(src[0]);
1029     dstep /= sizeof(dst[0]);
1030     cvtScaleAbs_SSE2<T, DT, WT> vop;
1031
1032     for( ; size.height--; src += sstep, dst += dstep )
1033     {
1034         int x = vop(src, dst, size.width, scale, shift);
1035
1036         #if CV_ENABLE_UNROLLED
1037         for( ; x <= size.width - 4; x += 4 )
1038         {
1039             DT t0, t1;
1040             t0 = saturate_cast<DT>(std::abs(src[x]*scale + shift));
1041             t1 = saturate_cast<DT>(std::abs(src[x+1]*scale + shift));
1042             dst[x] = t0; dst[x+1] = t1;
1043             t0 = saturate_cast<DT>(std::abs(src[x+2]*scale + shift));
1044             t1 = saturate_cast<DT>(std::abs(src[x+3]*scale + shift));
1045             dst[x+2] = t0; dst[x+3] = t1;
1046         }
1047         #endif
1048         for( ; x < size.width; x++ )
1049             dst[x] = saturate_cast<DT>(std::abs(src[x]*scale + shift));
1050     }
1051 }
1052
1053 template<typename T, typename DT, typename WT> static void
1054 cvtScale_( const T* src, size_t sstep,
1055            DT* dst, size_t dstep, Size size,
1056            WT scale, WT shift )
1057 {
1058     sstep /= sizeof(src[0]);
1059     dstep /= sizeof(dst[0]);
1060
1061     for( ; size.height--; src += sstep, dst += dstep )
1062     {
1063         int x = 0;
1064         #if CV_ENABLE_UNROLLED
1065         for( ; x <= size.width - 4; x += 4 )
1066         {
1067             DT t0, t1;
1068             t0 = saturate_cast<DT>(src[x]*scale + shift);
1069             t1 = saturate_cast<DT>(src[x+1]*scale + shift);
1070             dst[x] = t0; dst[x+1] = t1;
1071             t0 = saturate_cast<DT>(src[x+2]*scale + shift);
1072             t1 = saturate_cast<DT>(src[x+3]*scale + shift);
1073             dst[x+2] = t0; dst[x+3] = t1;
1074         }
1075         #endif
1076
1077         for( ; x < size.width; x++ )
1078             dst[x] = saturate_cast<DT>(src[x]*scale + shift);
1079     }
1080 }
1081
1082 //vz optimized template specialization
1083 template<> void
1084 cvtScale_<short, short, float>( const short* src, size_t sstep,
1085            short* dst, size_t dstep, Size size,
1086            float scale, float shift )
1087 {
1088     sstep /= sizeof(src[0]);
1089     dstep /= sizeof(dst[0]);
1090
1091     for( ; size.height--; src += sstep, dst += dstep )
1092     {
1093         int x = 0;
1094         #if CV_SSE2
1095             if(USE_SSE2)
1096             {
1097                 __m128 scale128 = _mm_set1_ps (scale);
1098                 __m128 shift128 = _mm_set1_ps (shift);
1099                 for(; x <= size.width - 8; x += 8 )
1100                 {
1101                     __m128i r0 = _mm_loadl_epi64((const __m128i*)(src + x));
1102                     __m128i r1 = _mm_loadl_epi64((const __m128i*)(src + x + 4));
1103                     __m128 rf0 =_mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpacklo_epi16(r0, r0), 16));
1104                     __m128 rf1 =_mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpacklo_epi16(r1, r1), 16));
1105                     rf0 = _mm_add_ps(_mm_mul_ps(rf0, scale128), shift128);
1106                     rf1 = _mm_add_ps(_mm_mul_ps(rf1, scale128), shift128);
1107                     r0 = _mm_cvtps_epi32(rf0);
1108                     r1 = _mm_cvtps_epi32(rf1);
1109                     r0 = _mm_packs_epi32(r0, r1);
1110                     _mm_storeu_si128((__m128i*)(dst + x), r0);
1111                 }
1112             }
1113         #endif
1114
1115         for(; x < size.width; x++ )
1116             dst[x] = saturate_cast<short>(src[x]*scale + shift);
1117     }
1118 }
1119
1120 template<> void
1121 cvtScale_<short, int, float>( const short* src, size_t sstep,
1122            int* dst, size_t dstep, Size size,
1123            float scale, float shift )
1124 {
1125     sstep /= sizeof(src[0]);
1126     dstep /= sizeof(dst[0]);
1127
1128     for( ; size.height--; src += sstep, dst += dstep )
1129     {
1130         int x = 0;
1131
1132          #if CV_SSE2
1133             if(USE_SSE2)//~5X
1134             {
1135                 __m128 scale128 = _mm_set1_ps (scale);
1136                 __m128 shift128 = _mm_set1_ps (shift);
1137                 for(; x <= size.width - 8; x += 8 )
1138                 {
1139                     __m128i r0 = _mm_loadl_epi64((const __m128i*)(src + x));
1140                     __m128i r1 = _mm_loadl_epi64((const __m128i*)(src + x + 4));
1141                     __m128 rf0 =_mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpacklo_epi16(r0, r0), 16));
1142                     __m128 rf1 =_mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpacklo_epi16(r1, r1), 16));
1143                     rf0 = _mm_add_ps(_mm_mul_ps(rf0, scale128), shift128);
1144                     rf1 = _mm_add_ps(_mm_mul_ps(rf1, scale128), shift128);
1145                     r0 = _mm_cvtps_epi32(rf0);
1146                     r1 = _mm_cvtps_epi32(rf1);
1147
1148                     _mm_storeu_si128((__m128i*)(dst + x), r0);
1149                     _mm_storeu_si128((__m128i*)(dst + x + 4), r1);
1150                 }
1151             }
1152         #endif
1153
1154         //We will wait Haswell
1155         /*
1156         #if CV_AVX
1157             if(USE_AVX)//2X - bad variant
1158             {
1159                 ////TODO:AVX implementation (optimization?) required
1160                 __m256 scale256 = _mm256_set1_ps (scale);
1161                 __m256 shift256 = _mm256_set1_ps (shift);
1162                 for(; x <= size.width - 8; x += 8 )
1163                 {
1164                     __m256i buf = _mm256_set_epi32((int)(*(src+x+7)),(int)(*(src+x+6)),(int)(*(src+x+5)),(int)(*(src+x+4)),(int)(*(src+x+3)),(int)(*(src+x+2)),(int)(*(src+x+1)),(int)(*(src+x)));
1165                     __m256 r0 = _mm256_add_ps( _mm256_mul_ps(_mm256_cvtepi32_ps (buf), scale256), shift256);
1166                     __m256i res = _mm256_cvtps_epi32(r0);
1167                     _mm256_storeu_si256 ((__m256i*)(dst+x), res);
1168                 }
1169             }
1170         #endif*/
1171
1172         for(; x < size.width; x++ )
1173             dst[x] = saturate_cast<int>(src[x]*scale + shift);
1174     }
1175 }
1176
1177 template<typename T, typename DT> static void
1178 cvt_( const T* src, size_t sstep,
1179       DT* dst, size_t dstep, Size size )
1180 {
1181     sstep /= sizeof(src[0]);
1182     dstep /= sizeof(dst[0]);
1183
1184     for( ; size.height--; src += sstep, dst += dstep )
1185     {
1186         int x = 0;
1187         #if CV_ENABLE_UNROLLED
1188         for( ; x <= size.width - 4; x += 4 )
1189         {
1190             DT t0, t1;
1191             t0 = saturate_cast<DT>(src[x]);
1192             t1 = saturate_cast<DT>(src[x+1]);
1193             dst[x] = t0; dst[x+1] = t1;
1194             t0 = saturate_cast<DT>(src[x+2]);
1195             t1 = saturate_cast<DT>(src[x+3]);
1196             dst[x+2] = t0; dst[x+3] = t1;
1197         }
1198         #endif
1199         for( ; x < size.width; x++ )
1200             dst[x] = saturate_cast<DT>(src[x]);
1201     }
1202 }
1203
1204 //vz optimized template specialization, test Core_ConvertScale/ElemWiseTest
1205 template<>  void
1206 cvt_<float, short>( const float* src, size_t sstep,
1207      short* dst, size_t dstep, Size size )
1208 {
1209     sstep /= sizeof(src[0]);
1210     dstep /= sizeof(dst[0]);
1211
1212     for( ; size.height--; src += sstep, dst += dstep )
1213     {
1214         int x = 0;
1215         #if   CV_SSE2
1216         if(USE_SSE2){
1217               for( ; x <= size.width - 8; x += 8 )
1218             {
1219                 __m128 src128 = _mm_loadu_ps (src + x);
1220                 __m128i src_int128 = _mm_cvtps_epi32 (src128);
1221
1222                 src128 = _mm_loadu_ps (src + x + 4);
1223                 __m128i src1_int128 = _mm_cvtps_epi32 (src128);
1224
1225                 src1_int128 = _mm_packs_epi32(src_int128, src1_int128);
1226                 _mm_storeu_si128((__m128i*)(dst + x),src1_int128);
1227             }
1228         }
1229         #endif
1230         for( ; x < size.width; x++ )
1231             dst[x] = saturate_cast<short>(src[x]);
1232     }
1233
1234 }
1235
1236
1237 template<typename T> static void
1238 cpy_( const T* src, size_t sstep, T* dst, size_t dstep, Size size )
1239 {
1240     sstep /= sizeof(src[0]);
1241     dstep /= sizeof(dst[0]);
1242
1243     for( ; size.height--; src += sstep, dst += dstep )
1244         memcpy(dst, src, size.width*sizeof(src[0]));
1245 }
1246
1247 #define DEF_CVT_SCALE_ABS_FUNC(suffix, tfunc, stype, dtype, wtype) \
1248 static void cvtScaleAbs##suffix( const stype* src, size_t sstep, const uchar*, size_t, \
1249                          dtype* dst, size_t dstep, Size size, double* scale) \
1250 { \
1251     tfunc(src, sstep, dst, dstep, size, (wtype)scale[0], (wtype)scale[1]); \
1252 }
1253
1254 #define DEF_CVT_SCALE_FUNC(suffix, stype, dtype, wtype) \
1255 static void cvtScale##suffix( const stype* src, size_t sstep, const uchar*, size_t, \
1256 dtype* dst, size_t dstep, Size size, double* scale) \
1257 { \
1258     cvtScale_(src, sstep, dst, dstep, size, (wtype)scale[0], (wtype)scale[1]); \
1259 }
1260
1261 #if defined(HAVE_IPP)
1262 #define DEF_CVT_FUNC_F(suffix, stype, dtype, ippFavor) \
1263 static void cvt##suffix( const stype* src, size_t sstep, const uchar*, size_t, \
1264                          dtype* dst, size_t dstep, Size size, double*) \
1265 { \
1266     if (src && dst)\
1267     {\
1268         if (ippiConvert_##ippFavor(src, (int)sstep, dst, (int)dstep, ippiSize(size.width, size.height)) >= 0) \
1269             return; \
1270         setIppErrorStatus(); \
1271     }\
1272     cvt_(src, sstep, dst, dstep, size); \
1273 }
1274
1275 #define DEF_CVT_FUNC_F2(suffix, stype, dtype, ippFavor) \
1276 static void cvt##suffix( const stype* src, size_t sstep, const uchar*, size_t, \
1277                          dtype* dst, size_t dstep, Size size, double*) \
1278 { \
1279     if (src && dst)\
1280     {\
1281         if (ippiConvert_##ippFavor(src, (int)sstep, dst, (int)dstep, ippiSize(size.width, size.height), ippRndFinancial, 0) >= 0) \
1282             return; \
1283         setIppErrorStatus(); \
1284     }\
1285     cvt_(src, sstep, dst, dstep, size); \
1286 }
1287 #else
1288 #define DEF_CVT_FUNC_F(suffix, stype, dtype, ippFavor) \
1289 static void cvt##suffix( const stype* src, size_t sstep, const uchar*, size_t, \
1290                          dtype* dst, size_t dstep, Size size, double*) \
1291 { \
1292     cvt_(src, sstep, dst, dstep, size); \
1293 }
1294 #define DEF_CVT_FUNC_F2 DEF_CVT_FUNC_F
1295 #endif
1296
1297 #define DEF_CVT_FUNC(suffix, stype, dtype) \
1298 static void cvt##suffix( const stype* src, size_t sstep, const uchar*, size_t, \
1299                          dtype* dst, size_t dstep, Size size, double*) \
1300 { \
1301     cvt_(src, sstep, dst, dstep, size); \
1302 }
1303
1304 #define DEF_CPY_FUNC(suffix, stype) \
1305 static void cvt##suffix( const stype* src, size_t sstep, const uchar*, size_t, \
1306                          stype* dst, size_t dstep, Size size, double*) \
1307 { \
1308     cpy_(src, sstep, dst, dstep, size); \
1309 }
1310
1311
1312 DEF_CVT_SCALE_ABS_FUNC(8u, cvtScaleAbs_, uchar, uchar, float)
1313 DEF_CVT_SCALE_ABS_FUNC(8s8u, cvtScaleAbs_, schar, uchar, float)
1314 DEF_CVT_SCALE_ABS_FUNC(16u8u, cvtScaleAbs_, ushort, uchar, float)
1315 DEF_CVT_SCALE_ABS_FUNC(16s8u, cvtScaleAbs_, short, uchar, float)
1316 DEF_CVT_SCALE_ABS_FUNC(32s8u, cvtScaleAbs_, int, uchar, float)
1317 DEF_CVT_SCALE_ABS_FUNC(32f8u, cvtScaleAbs_, float, uchar, float)
1318 DEF_CVT_SCALE_ABS_FUNC(64f8u, cvtScaleAbs_, double, uchar, float)
1319
1320 DEF_CVT_SCALE_FUNC(8u,     uchar, uchar, float)
1321 DEF_CVT_SCALE_FUNC(8s8u,   schar, uchar, float)
1322 DEF_CVT_SCALE_FUNC(16u8u,  ushort, uchar, float)
1323 DEF_CVT_SCALE_FUNC(16s8u,  short, uchar, float)
1324 DEF_CVT_SCALE_FUNC(32s8u,  int, uchar, float)
1325 DEF_CVT_SCALE_FUNC(32f8u,  float, uchar, float)
1326 DEF_CVT_SCALE_FUNC(64f8u,  double, uchar, float)
1327
1328 DEF_CVT_SCALE_FUNC(8u8s,   uchar, schar, float)
1329 DEF_CVT_SCALE_FUNC(8s,     schar, schar, float)
1330 DEF_CVT_SCALE_FUNC(16u8s,  ushort, schar, float)
1331 DEF_CVT_SCALE_FUNC(16s8s,  short, schar, float)
1332 DEF_CVT_SCALE_FUNC(32s8s,  int, schar, float)
1333 DEF_CVT_SCALE_FUNC(32f8s,  float, schar, float)
1334 DEF_CVT_SCALE_FUNC(64f8s,  double, schar, float)
1335
1336 DEF_CVT_SCALE_FUNC(8u16u,  uchar, ushort, float)
1337 DEF_CVT_SCALE_FUNC(8s16u,  schar, ushort, float)
1338 DEF_CVT_SCALE_FUNC(16u,    ushort, ushort, float)
1339 DEF_CVT_SCALE_FUNC(16s16u, short, ushort, float)
1340 DEF_CVT_SCALE_FUNC(32s16u, int, ushort, float)
1341 DEF_CVT_SCALE_FUNC(32f16u, float, ushort, float)
1342 DEF_CVT_SCALE_FUNC(64f16u, double, ushort, float)
1343
1344 DEF_CVT_SCALE_FUNC(8u16s,  uchar, short, float)
1345 DEF_CVT_SCALE_FUNC(8s16s,  schar, short, float)
1346 DEF_CVT_SCALE_FUNC(16u16s, ushort, short, float)
1347 DEF_CVT_SCALE_FUNC(16s,    short, short, float)
1348 DEF_CVT_SCALE_FUNC(32s16s, int, short, float)
1349 DEF_CVT_SCALE_FUNC(32f16s, float, short, float)
1350 DEF_CVT_SCALE_FUNC(64f16s, double, short, float)
1351
1352 DEF_CVT_SCALE_FUNC(8u32s,  uchar, int, float)
1353 DEF_CVT_SCALE_FUNC(8s32s,  schar, int, float)
1354 DEF_CVT_SCALE_FUNC(16u32s, ushort, int, float)
1355 DEF_CVT_SCALE_FUNC(16s32s, short, int, float)
1356 DEF_CVT_SCALE_FUNC(32s,    int, int, double)
1357 DEF_CVT_SCALE_FUNC(32f32s, float, int, float)
1358 DEF_CVT_SCALE_FUNC(64f32s, double, int, double)
1359
1360 DEF_CVT_SCALE_FUNC(8u32f,  uchar, float, float)
1361 DEF_CVT_SCALE_FUNC(8s32f,  schar, float, float)
1362 DEF_CVT_SCALE_FUNC(16u32f, ushort, float, float)
1363 DEF_CVT_SCALE_FUNC(16s32f, short, float, float)
1364 DEF_CVT_SCALE_FUNC(32s32f, int, float, double)
1365 DEF_CVT_SCALE_FUNC(32f,    float, float, float)
1366 DEF_CVT_SCALE_FUNC(64f32f, double, float, double)
1367
1368 DEF_CVT_SCALE_FUNC(8u64f,  uchar, double, double)
1369 DEF_CVT_SCALE_FUNC(8s64f,  schar, double, double)
1370 DEF_CVT_SCALE_FUNC(16u64f, ushort, double, double)
1371 DEF_CVT_SCALE_FUNC(16s64f, short, double, double)
1372 DEF_CVT_SCALE_FUNC(32s64f, int, double, double)
1373 DEF_CVT_SCALE_FUNC(32f64f, float, double, double)
1374 DEF_CVT_SCALE_FUNC(64f,    double, double, double)
1375
1376 DEF_CPY_FUNC(8u,     uchar)
1377 DEF_CVT_FUNC_F(8s8u,   schar, uchar, 8s8u_C1Rs)
1378 DEF_CVT_FUNC_F(16u8u,  ushort, uchar, 16u8u_C1R)
1379 DEF_CVT_FUNC_F(16s8u,  short, uchar, 16s8u_C1R)
1380 DEF_CVT_FUNC_F(32s8u,  int, uchar, 32s8u_C1R)
1381 DEF_CVT_FUNC_F2(32f8u,  float, uchar, 32f8u_C1RSfs)
1382 DEF_CVT_FUNC(64f8u,  double, uchar)
1383
1384 DEF_CVT_FUNC_F2(8u8s,   uchar, schar, 8u8s_C1RSfs)
1385 DEF_CVT_FUNC_F2(16u8s,  ushort, schar, 16u8s_C1RSfs)
1386 DEF_CVT_FUNC_F2(16s8s,  short, schar, 16s8s_C1RSfs)
1387 DEF_CVT_FUNC_F(32s8s,  int, schar, 32s8s_C1R)
1388 DEF_CVT_FUNC_F2(32f8s,  float, schar, 32f8s_C1RSfs)
1389 DEF_CVT_FUNC(64f8s,  double, schar)
1390
1391 DEF_CVT_FUNC_F(8u16u,  uchar, ushort, 8u16u_C1R)
1392 DEF_CVT_FUNC_F(8s16u,  schar, ushort, 8s16u_C1Rs)
1393 DEF_CPY_FUNC(16u,    ushort)
1394 DEF_CVT_FUNC_F(16s16u, short, ushort, 16s16u_C1Rs)
1395 DEF_CVT_FUNC_F2(32s16u, int, ushort, 32s16u_C1RSfs)
1396 DEF_CVT_FUNC_F2(32f16u, float, ushort, 32f16u_C1RSfs)
1397 DEF_CVT_FUNC(64f16u, double, ushort)
1398
1399 DEF_CVT_FUNC_F(8u16s,  uchar, short, 8u16s_C1R)
1400 DEF_CVT_FUNC_F(8s16s,  schar, short, 8s16s_C1R)
1401 DEF_CVT_FUNC_F2(16u16s, ushort, short, 16u16s_C1RSfs)
1402 DEF_CVT_FUNC_F2(32s16s, int, short, 32s16s_C1RSfs)
1403 DEF_CVT_FUNC_F2(32f16s, float, short, 32f16s_C1RSfs)
1404 DEF_CVT_FUNC(64f16s, double, short)
1405
1406 DEF_CVT_FUNC_F(8u32s,  uchar, int, 8u32s_C1R)
1407 DEF_CVT_FUNC_F(8s32s,  schar, int, 8s32s_C1R)
1408 DEF_CVT_FUNC_F(16u32s, ushort, int, 16u32s_C1R)
1409 DEF_CVT_FUNC_F(16s32s, short, int, 16s32s_C1R)
1410 DEF_CPY_FUNC(32s,    int)
1411 DEF_CVT_FUNC_F2(32f32s, float, int, 32f32s_C1RSfs)
1412 DEF_CVT_FUNC(64f32s, double, int)
1413
1414 DEF_CVT_FUNC_F(8u32f,  uchar, float, 8u32f_C1R)
1415 DEF_CVT_FUNC_F(8s32f,  schar, float, 8s32f_C1R)
1416 DEF_CVT_FUNC_F(16u32f, ushort, float, 16u32f_C1R)
1417 DEF_CVT_FUNC_F(16s32f, short, float, 16s32f_C1R)
1418 DEF_CVT_FUNC_F(32s32f, int, float, 32s32f_C1R)
1419 DEF_CVT_FUNC(64f32f, double, float)
1420
1421 DEF_CVT_FUNC(8u64f,  uchar, double)
1422 DEF_CVT_FUNC(8s64f,  schar, double)
1423 DEF_CVT_FUNC(16u64f, ushort, double)
1424 DEF_CVT_FUNC(16s64f, short, double)
1425 DEF_CVT_FUNC(32s64f, int, double)
1426 DEF_CVT_FUNC(32f64f, float, double)
1427 DEF_CPY_FUNC(64s,    int64)
1428
1429 static BinaryFunc getCvtScaleAbsFunc(int depth)
1430 {
1431     static BinaryFunc cvtScaleAbsTab[] =
1432     {
1433         (BinaryFunc)cvtScaleAbs8u, (BinaryFunc)cvtScaleAbs8s8u, (BinaryFunc)cvtScaleAbs16u8u,
1434         (BinaryFunc)cvtScaleAbs16s8u, (BinaryFunc)cvtScaleAbs32s8u, (BinaryFunc)cvtScaleAbs32f8u,
1435         (BinaryFunc)cvtScaleAbs64f8u, 0
1436     };
1437
1438     return cvtScaleAbsTab[depth];
1439 }
1440
1441 BinaryFunc getConvertFunc(int sdepth, int ddepth)
1442 {
1443     static BinaryFunc cvtTab[][8] =
1444     {
1445         {
1446             (BinaryFunc)(cvt8u), (BinaryFunc)GET_OPTIMIZED(cvt8s8u), (BinaryFunc)GET_OPTIMIZED(cvt16u8u),
1447             (BinaryFunc)GET_OPTIMIZED(cvt16s8u), (BinaryFunc)GET_OPTIMIZED(cvt32s8u), (BinaryFunc)GET_OPTIMIZED(cvt32f8u),
1448             (BinaryFunc)GET_OPTIMIZED(cvt64f8u), 0
1449         },
1450         {
1451             (BinaryFunc)GET_OPTIMIZED(cvt8u8s), (BinaryFunc)cvt8u, (BinaryFunc)GET_OPTIMIZED(cvt16u8s),
1452             (BinaryFunc)GET_OPTIMIZED(cvt16s8s), (BinaryFunc)GET_OPTIMIZED(cvt32s8s), (BinaryFunc)GET_OPTIMIZED(cvt32f8s),
1453             (BinaryFunc)GET_OPTIMIZED(cvt64f8s), 0
1454         },
1455         {
1456             (BinaryFunc)GET_OPTIMIZED(cvt8u16u), (BinaryFunc)GET_OPTIMIZED(cvt8s16u), (BinaryFunc)cvt16u,
1457             (BinaryFunc)GET_OPTIMIZED(cvt16s16u), (BinaryFunc)GET_OPTIMIZED(cvt32s16u), (BinaryFunc)GET_OPTIMIZED(cvt32f16u),
1458             (BinaryFunc)GET_OPTIMIZED(cvt64f16u), 0
1459         },
1460         {
1461             (BinaryFunc)GET_OPTIMIZED(cvt8u16s), (BinaryFunc)GET_OPTIMIZED(cvt8s16s), (BinaryFunc)GET_OPTIMIZED(cvt16u16s),
1462             (BinaryFunc)cvt16u, (BinaryFunc)GET_OPTIMIZED(cvt32s16s), (BinaryFunc)GET_OPTIMIZED(cvt32f16s),
1463             (BinaryFunc)GET_OPTIMIZED(cvt64f16s), 0
1464         },
1465         {
1466             (BinaryFunc)GET_OPTIMIZED(cvt8u32s), (BinaryFunc)GET_OPTIMIZED(cvt8s32s), (BinaryFunc)GET_OPTIMIZED(cvt16u32s),
1467             (BinaryFunc)GET_OPTIMIZED(cvt16s32s), (BinaryFunc)cvt32s, (BinaryFunc)GET_OPTIMIZED(cvt32f32s),
1468             (BinaryFunc)GET_OPTIMIZED(cvt64f32s), 0
1469         },
1470         {
1471             (BinaryFunc)GET_OPTIMIZED(cvt8u32f), (BinaryFunc)GET_OPTIMIZED(cvt8s32f), (BinaryFunc)GET_OPTIMIZED(cvt16u32f),
1472             (BinaryFunc)GET_OPTIMIZED(cvt16s32f), (BinaryFunc)GET_OPTIMIZED(cvt32s32f), (BinaryFunc)cvt32s,
1473             (BinaryFunc)GET_OPTIMIZED(cvt64f32f), 0
1474         },
1475         {
1476             (BinaryFunc)GET_OPTIMIZED(cvt8u64f), (BinaryFunc)GET_OPTIMIZED(cvt8s64f), (BinaryFunc)GET_OPTIMIZED(cvt16u64f),
1477             (BinaryFunc)GET_OPTIMIZED(cvt16s64f), (BinaryFunc)GET_OPTIMIZED(cvt32s64f), (BinaryFunc)GET_OPTIMIZED(cvt32f64f),
1478             (BinaryFunc)(cvt64s), 0
1479         },
1480         {
1481             0, 0, 0, 0, 0, 0, 0, 0
1482         }
1483     };
1484
1485     return cvtTab[CV_MAT_DEPTH(ddepth)][CV_MAT_DEPTH(sdepth)];
1486 }
1487
1488 static BinaryFunc getConvertScaleFunc(int sdepth, int ddepth)
1489 {
1490     static BinaryFunc cvtScaleTab[][8] =
1491     {
1492         {
1493             (BinaryFunc)GET_OPTIMIZED(cvtScale8u), (BinaryFunc)GET_OPTIMIZED(cvtScale8s8u), (BinaryFunc)GET_OPTIMIZED(cvtScale16u8u),
1494             (BinaryFunc)GET_OPTIMIZED(cvtScale16s8u), (BinaryFunc)GET_OPTIMIZED(cvtScale32s8u), (BinaryFunc)GET_OPTIMIZED(cvtScale32f8u),
1495             (BinaryFunc)cvtScale64f8u, 0
1496         },
1497         {
1498             (BinaryFunc)GET_OPTIMIZED(cvtScale8u8s), (BinaryFunc)GET_OPTIMIZED(cvtScale8s), (BinaryFunc)GET_OPTIMIZED(cvtScale16u8s),
1499             (BinaryFunc)GET_OPTIMIZED(cvtScale16s8s), (BinaryFunc)GET_OPTIMIZED(cvtScale32s8s), (BinaryFunc)GET_OPTIMIZED(cvtScale32f8s),
1500             (BinaryFunc)cvtScale64f8s, 0
1501         },
1502         {
1503             (BinaryFunc)GET_OPTIMIZED(cvtScale8u16u), (BinaryFunc)GET_OPTIMIZED(cvtScale8s16u), (BinaryFunc)GET_OPTIMIZED(cvtScale16u),
1504             (BinaryFunc)GET_OPTIMIZED(cvtScale16s16u), (BinaryFunc)GET_OPTIMIZED(cvtScale32s16u), (BinaryFunc)GET_OPTIMIZED(cvtScale32f16u),
1505             (BinaryFunc)cvtScale64f16u, 0
1506         },
1507         {
1508             (BinaryFunc)GET_OPTIMIZED(cvtScale8u16s), (BinaryFunc)GET_OPTIMIZED(cvtScale8s16s), (BinaryFunc)GET_OPTIMIZED(cvtScale16u16s),
1509             (BinaryFunc)GET_OPTIMIZED(cvtScale16s), (BinaryFunc)GET_OPTIMIZED(cvtScale32s16s), (BinaryFunc)GET_OPTIMIZED(cvtScale32f16s),
1510             (BinaryFunc)cvtScale64f16s, 0
1511         },
1512         {
1513             (BinaryFunc)GET_OPTIMIZED(cvtScale8u32s), (BinaryFunc)GET_OPTIMIZED(cvtScale8s32s), (BinaryFunc)GET_OPTIMIZED(cvtScale16u32s),
1514             (BinaryFunc)GET_OPTIMIZED(cvtScale16s32s), (BinaryFunc)GET_OPTIMIZED(cvtScale32s), (BinaryFunc)GET_OPTIMIZED(cvtScale32f32s),
1515             (BinaryFunc)cvtScale64f32s, 0
1516         },
1517         {
1518             (BinaryFunc)GET_OPTIMIZED(cvtScale8u32f), (BinaryFunc)GET_OPTIMIZED(cvtScale8s32f), (BinaryFunc)GET_OPTIMIZED(cvtScale16u32f),
1519             (BinaryFunc)GET_OPTIMIZED(cvtScale16s32f), (BinaryFunc)GET_OPTIMIZED(cvtScale32s32f), (BinaryFunc)GET_OPTIMIZED(cvtScale32f),
1520             (BinaryFunc)cvtScale64f32f, 0
1521         },
1522         {
1523             (BinaryFunc)cvtScale8u64f, (BinaryFunc)cvtScale8s64f, (BinaryFunc)cvtScale16u64f,
1524             (BinaryFunc)cvtScale16s64f, (BinaryFunc)cvtScale32s64f, (BinaryFunc)cvtScale32f64f,
1525             (BinaryFunc)cvtScale64f, 0
1526         },
1527         {
1528             0, 0, 0, 0, 0, 0, 0, 0
1529         }
1530     };
1531
1532     return cvtScaleTab[CV_MAT_DEPTH(ddepth)][CV_MAT_DEPTH(sdepth)];
1533 }
1534
1535 #ifdef HAVE_OPENCL
1536
1537 static bool ocl_convertScaleAbs( InputArray _src, OutputArray _dst, double alpha, double beta )
1538 {
1539     const ocl::Device & d = ocl::Device::getDefault();
1540     int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
1541         kercn = ocl::predictOptimalVectorWidth(_src, _dst), rowsPerWI = d.isIntel() ? 4 : 1;
1542     bool doubleSupport = d.doubleFPConfig() > 0;
1543
1544     if (depth == CV_32F || depth == CV_64F)
1545         return false;
1546
1547     char cvt[2][50];
1548     int wdepth = std::max(depth, CV_32F);
1549     ocl::Kernel k("KF", ocl::core::arithm_oclsrc,
1550                   format("-D OP_CONVERT_SCALE_ABS -D UNARY_OP -D dstT=%s -D srcT1=%s"
1551                          " -D workT=%s -D wdepth=%d -D convertToWT1=%s -D convertToDT=%s"
1552                          " -D workT1=%s -D rowsPerWI=%d%s",
1553                          ocl::typeToStr(CV_8UC(kercn)),
1554                          ocl::typeToStr(CV_MAKE_TYPE(depth, kercn)),
1555                          ocl::typeToStr(CV_MAKE_TYPE(wdepth, kercn)), wdepth,
1556                          ocl::convertTypeStr(depth, wdepth, kercn, cvt[0]),
1557                          ocl::convertTypeStr(wdepth, CV_8U, kercn, cvt[1]),
1558                          ocl::typeToStr(wdepth), rowsPerWI,
1559                          doubleSupport ? " -D DOUBLE_SUPPORT" : ""));
1560     if (k.empty())
1561         return false;
1562
1563     UMat src = _src.getUMat();
1564     _dst.create(src.size(), CV_8UC(cn));
1565     UMat dst = _dst.getUMat();
1566
1567     ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
1568             dstarg = ocl::KernelArg::WriteOnly(dst, cn, kercn);
1569
1570     if (wdepth == CV_32F)
1571         k.args(srcarg, dstarg, (float)alpha, (float)beta);
1572     else if (wdepth == CV_64F)
1573         k.args(srcarg, dstarg, alpha, beta);
1574
1575     size_t globalsize[2] = { src.cols * cn / kercn, (src.rows + rowsPerWI - 1) / rowsPerWI };
1576     return k.run(2, globalsize, NULL, false);
1577 }
1578
1579 #endif
1580
1581 }
1582
1583 void cv::convertScaleAbs( InputArray _src, OutputArray _dst, double alpha, double beta )
1584 {
1585     CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
1586                ocl_convertScaleAbs(_src, _dst, alpha, beta))
1587
1588     Mat src = _src.getMat();
1589     int cn = src.channels();
1590     double scale[] = {alpha, beta};
1591     _dst.create( src.dims, src.size, CV_8UC(cn) );
1592     Mat dst = _dst.getMat();
1593     BinaryFunc func = getCvtScaleAbsFunc(src.depth());
1594     CV_Assert( func != 0 );
1595
1596     if( src.dims <= 2 )
1597     {
1598         Size sz = getContinuousSize(src, dst, cn);
1599         func( src.data, src.step, 0, 0, dst.data, dst.step, sz, scale );
1600     }
1601     else
1602     {
1603         const Mat* arrays[] = {&src, &dst, 0};
1604         uchar* ptrs[2];
1605         NAryMatIterator it(arrays, ptrs);
1606         Size sz((int)it.size*cn, 1);
1607
1608         for( size_t i = 0; i < it.nplanes; i++, ++it )
1609             func( ptrs[0], 0, 0, 0, ptrs[1], 0, sz, scale );
1610     }
1611 }
1612
1613 void cv::Mat::convertTo(OutputArray _dst, int _type, double alpha, double beta) const
1614 {
1615     bool noScale = fabs(alpha-1) < DBL_EPSILON && fabs(beta) < DBL_EPSILON;
1616
1617     if( _type < 0 )
1618         _type = _dst.fixedType() ? _dst.type() : type();
1619     else
1620         _type = CV_MAKETYPE(CV_MAT_DEPTH(_type), channels());
1621
1622     int sdepth = depth(), ddepth = CV_MAT_DEPTH(_type);
1623     if( sdepth == ddepth && noScale )
1624     {
1625         copyTo(_dst);
1626         return;
1627     }
1628
1629     Mat src = *this;
1630
1631     BinaryFunc func = noScale ? getConvertFunc(sdepth, ddepth) : getConvertScaleFunc(sdepth, ddepth);
1632     double scale[] = {alpha, beta};
1633     int cn = channels();
1634     CV_Assert( func != 0 );
1635
1636     if( dims <= 2 )
1637     {
1638         _dst.create( size(), _type );
1639         Mat dst = _dst.getMat();
1640         Size sz = getContinuousSize(src, dst, cn);
1641         func( src.data, src.step, 0, 0, dst.data, dst.step, sz, scale );
1642     }
1643     else
1644     {
1645         _dst.create( dims, size, _type );
1646         Mat dst = _dst.getMat();
1647         const Mat* arrays[] = {&src, &dst, 0};
1648         uchar* ptrs[2];
1649         NAryMatIterator it(arrays, ptrs);
1650         Size sz((int)(it.size*cn), 1);
1651
1652         for( size_t i = 0; i < it.nplanes; i++, ++it )
1653             func(ptrs[0], 1, 0, 0, ptrs[1], 1, sz, scale);
1654     }
1655 }
1656
1657 /****************************************************************************************\
1658 *                                    LUT Transform                                       *
1659 \****************************************************************************************/
1660
1661 namespace cv
1662 {
1663
1664 template<typename T> static void
1665 LUT8u_( const uchar* src, const T* lut, T* dst, int len, int cn, int lutcn )
1666 {
1667     if( lutcn == 1 )
1668     {
1669         for( int i = 0; i < len*cn; i++ )
1670             dst[i] = lut[src[i]];
1671     }
1672     else
1673     {
1674         for( int i = 0; i < len*cn; i += cn )
1675             for( int k = 0; k < cn; k++ )
1676                 dst[i+k] = lut[src[i+k]*cn+k];
1677     }
1678 }
1679
1680 static void LUT8u_8u( const uchar* src, const uchar* lut, uchar* dst, int len, int cn, int lutcn )
1681 {
1682     LUT8u_( src, lut, dst, len, cn, lutcn );
1683 }
1684
1685 static void LUT8u_8s( const uchar* src, const schar* lut, schar* dst, int len, int cn, int lutcn )
1686 {
1687     LUT8u_( src, lut, dst, len, cn, lutcn );
1688 }
1689
1690 static void LUT8u_16u( const uchar* src, const ushort* lut, ushort* dst, int len, int cn, int lutcn )
1691 {
1692     LUT8u_( src, lut, dst, len, cn, lutcn );
1693 }
1694
1695 static void LUT8u_16s( const uchar* src, const short* lut, short* dst, int len, int cn, int lutcn )
1696 {
1697     LUT8u_( src, lut, dst, len, cn, lutcn );
1698 }
1699
1700 static void LUT8u_32s( const uchar* src, const int* lut, int* dst, int len, int cn, int lutcn )
1701 {
1702     LUT8u_( src, lut, dst, len, cn, lutcn );
1703 }
1704
1705 static void LUT8u_32f( const uchar* src, const float* lut, float* dst, int len, int cn, int lutcn )
1706 {
1707     LUT8u_( src, lut, dst, len, cn, lutcn );
1708 }
1709
1710 static void LUT8u_64f( const uchar* src, const double* lut, double* dst, int len, int cn, int lutcn )
1711 {
1712     LUT8u_( src, lut, dst, len, cn, lutcn );
1713 }
1714
1715 typedef void (*LUTFunc)( const uchar* src, const uchar* lut, uchar* dst, int len, int cn, int lutcn );
1716
1717 static LUTFunc lutTab[] =
1718 {
1719     (LUTFunc)LUT8u_8u, (LUTFunc)LUT8u_8s, (LUTFunc)LUT8u_16u, (LUTFunc)LUT8u_16s,
1720     (LUTFunc)LUT8u_32s, (LUTFunc)LUT8u_32f, (LUTFunc)LUT8u_64f, 0
1721 };
1722
1723 #ifdef HAVE_OPENCL
1724
1725 static bool ocl_LUT(InputArray _src, InputArray _lut, OutputArray _dst)
1726 {
1727     int lcn = _lut.channels(), dcn = _src.channels(), ddepth = _lut.depth();
1728
1729     UMat src = _src.getUMat(), lut = _lut.getUMat();
1730     _dst.create(src.size(), CV_MAKETYPE(ddepth, dcn));
1731     UMat dst = _dst.getUMat();
1732     int kercn = lcn == 1 ? std::min(4, ocl::predictOptimalVectorWidth(_dst)) : dcn;
1733
1734     ocl::Kernel k("LUT", ocl::core::lut_oclsrc,
1735                   format("-D dcn=%d -D lcn=%d -D srcT=%s -D dstT=%s", kercn, lcn,
1736                          ocl::typeToStr(src.depth()), ocl::memopTypeToStr(ddepth)));
1737     if (k.empty())
1738         return false;
1739
1740     k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::ReadOnlyNoSize(lut),
1741         ocl::KernelArg::WriteOnly(dst, dcn, kercn));
1742
1743     size_t globalSize[2] = { dst.cols * dcn / kercn, (dst.rows + 3) / 4 };
1744     return k.run(2, globalSize, NULL, false);
1745 }
1746
1747 #endif
1748
1749 #if defined(HAVE_IPP)
1750 namespace ipp {
1751
1752 #if 0 // there are no performance benefits (PR #2653)
1753 class IppLUTParallelBody_LUTC1 : public ParallelLoopBody
1754 {
1755 public:
1756     bool* ok;
1757     const Mat& src_;
1758     const Mat& lut_;
1759     Mat& dst_;
1760
1761     typedef IppStatus (*IppFn)(const Ipp8u* pSrc, int srcStep, void* pDst, int dstStep,
1762                           IppiSize roiSize, const void* pTable, int nBitSize);
1763     IppFn fn;
1764
1765     int width;
1766
1767     IppLUTParallelBody_LUTC1(const Mat& src, const Mat& lut, Mat& dst, bool* _ok)
1768         : ok(_ok), src_(src), lut_(lut), dst_(dst)
1769     {
1770         width = dst.cols * dst.channels();
1771
1772         size_t elemSize1 = CV_ELEM_SIZE1(dst.depth());
1773
1774         fn =
1775                 elemSize1 == 1 ? (IppFn)ippiLUTPalette_8u_C1R :
1776                 elemSize1 == 4 ? (IppFn)ippiLUTPalette_8u32u_C1R :
1777                 NULL;
1778
1779         *ok = (fn != NULL);
1780     }
1781
1782     void operator()( const cv::Range& range ) const
1783     {
1784         if (!*ok)
1785             return;
1786
1787         const int row0 = range.start;
1788         const int row1 = range.end;
1789
1790         Mat src = src_.rowRange(row0, row1);
1791         Mat dst = dst_.rowRange(row0, row1);
1792
1793         IppiSize sz = { width, dst.rows };
1794
1795         CV_DbgAssert(fn != NULL);
1796         if (fn(src.data, (int)src.step[0], dst.data, (int)dst.step[0], sz, lut_.data, 8) < 0)
1797         {
1798             setIppErrorStatus();
1799             *ok = false;
1800         }
1801     }
1802 private:
1803     IppLUTParallelBody_LUTC1(const IppLUTParallelBody_LUTC1&);
1804     IppLUTParallelBody_LUTC1& operator=(const IppLUTParallelBody_LUTC1&);
1805 };
1806 #endif
1807
1808 class IppLUTParallelBody_LUTCN : public ParallelLoopBody
1809 {
1810 public:
1811     bool *ok;
1812     const Mat& src_;
1813     const Mat& lut_;
1814     Mat& dst_;
1815
1816     int lutcn;
1817
1818     uchar* lutBuffer;
1819     uchar* lutTable[4];
1820
1821     IppLUTParallelBody_LUTCN(const Mat& src, const Mat& lut, Mat& dst, bool* _ok)
1822         : ok(_ok), src_(src), lut_(lut), dst_(dst), lutBuffer(NULL)
1823     {
1824         lutcn = lut.channels();
1825         IppiSize sz256 = {256, 1};
1826
1827         size_t elemSize1 = dst.elemSize1();
1828         CV_DbgAssert(elemSize1 == 1);
1829         lutBuffer = (uchar*)ippMalloc(256 * (int)elemSize1 * 4);
1830         lutTable[0] = lutBuffer + 0;
1831         lutTable[1] = lutBuffer + 1 * 256 * elemSize1;
1832         lutTable[2] = lutBuffer + 2 * 256 * elemSize1;
1833         lutTable[3] = lutBuffer + 3 * 256 * elemSize1;
1834
1835         CV_DbgAssert(lutcn == 3 || lutcn == 4);
1836         if (lutcn == 3)
1837         {
1838             IppStatus status = ippiCopy_8u_C3P3R(lut.data, (int)lut.step[0], lutTable, (int)lut.step[0], sz256);
1839             if (status < 0)
1840             {
1841                 setIppErrorStatus();
1842                 return;
1843             }
1844         }
1845         else if (lutcn == 4)
1846         {
1847             IppStatus status = ippiCopy_8u_C4P4R(lut.data, (int)lut.step[0], lutTable, (int)lut.step[0], sz256);
1848             if (status < 0)
1849             {
1850                 setIppErrorStatus();
1851                 return;
1852             }
1853         }
1854
1855         *ok = true;
1856     }
1857
1858     ~IppLUTParallelBody_LUTCN()
1859     {
1860         if (lutBuffer != NULL)
1861             ippFree(lutBuffer);
1862         lutBuffer = NULL;
1863         lutTable[0] = NULL;
1864     }
1865
1866     void operator()( const cv::Range& range ) const
1867     {
1868         if (!*ok)
1869             return;
1870
1871         const int row0 = range.start;
1872         const int row1 = range.end;
1873
1874         Mat src = src_.rowRange(row0, row1);
1875         Mat dst = dst_.rowRange(row0, row1);
1876
1877         if (lutcn == 3)
1878         {
1879             if (ippiLUTPalette_8u_C3R(
1880                     src.data, (int)src.step[0], dst.data, (int)dst.step[0],
1881                     ippiSize(dst.size()), lutTable, 8) >= 0)
1882                 return;
1883         }
1884         else if (lutcn == 4)
1885         {
1886             if (ippiLUTPalette_8u_C4R(
1887                     src.data, (int)src.step[0], dst.data, (int)dst.step[0],
1888                     ippiSize(dst.size()), lutTable, 8) >= 0)
1889                 return;
1890         }
1891         setIppErrorStatus();
1892         *ok = false;
1893     }
1894 private:
1895     IppLUTParallelBody_LUTCN(const IppLUTParallelBody_LUTCN&);
1896     IppLUTParallelBody_LUTCN& operator=(const IppLUTParallelBody_LUTCN&);
1897 };
1898 } // namespace ipp
1899 #endif // IPP
1900
1901 class LUTParallelBody : public ParallelLoopBody
1902 {
1903 public:
1904     bool* ok;
1905     const Mat& src_;
1906     const Mat& lut_;
1907     Mat& dst_;
1908
1909     LUTFunc func;
1910
1911     LUTParallelBody(const Mat& src, const Mat& lut, Mat& dst, bool* _ok)
1912         : ok(_ok), src_(src), lut_(lut), dst_(dst)
1913     {
1914         func = lutTab[lut.depth()];
1915         *ok = (func != NULL);
1916     }
1917
1918     void operator()( const cv::Range& range ) const
1919     {
1920         CV_DbgAssert(*ok);
1921
1922         const int row0 = range.start;
1923         const int row1 = range.end;
1924
1925         Mat src = src_.rowRange(row0, row1);
1926         Mat dst = dst_.rowRange(row0, row1);
1927
1928         int cn = src.channels();
1929         int lutcn = lut_.channels();
1930
1931         const Mat* arrays[] = {&src, &dst, 0};
1932         uchar* ptrs[2];
1933         NAryMatIterator it(arrays, ptrs);
1934         int len = (int)it.size;
1935
1936         for( size_t i = 0; i < it.nplanes; i++, ++it )
1937             func(ptrs[0], lut_.data, ptrs[1], len, cn, lutcn);
1938     }
1939 private:
1940     LUTParallelBody(const LUTParallelBody&);
1941     LUTParallelBody& operator=(const LUTParallelBody&);
1942 };
1943
1944 }
1945
1946 void cv::LUT( InputArray _src, InputArray _lut, OutputArray _dst )
1947 {
1948     int cn = _src.channels(), depth = _src.depth();
1949     int lutcn = _lut.channels();
1950
1951     CV_Assert( (lutcn == cn || lutcn == 1) &&
1952         _lut.total() == 256 && _lut.isContinuous() &&
1953         (depth == CV_8U || depth == CV_8S) );
1954
1955     CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2,
1956                ocl_LUT(_src, _lut, _dst))
1957
1958     Mat src = _src.getMat(), lut = _lut.getMat();
1959     _dst.create(src.dims, src.size, CV_MAKETYPE(_lut.depth(), cn));
1960     Mat dst = _dst.getMat();
1961
1962     if (_src.dims() <= 2)
1963     {
1964         bool ok = false;
1965         Ptr<ParallelLoopBody> body;
1966 #if defined(HAVE_IPP)
1967         size_t elemSize1 = CV_ELEM_SIZE1(dst.depth());
1968 #if 0 // there are no performance benefits (PR #2653)
1969         if (lutcn == 1)
1970         {
1971             ParallelLoopBody* p = new ipp::IppLUTParallelBody_LUTC1(src, lut, dst, &ok);
1972             body.reset(p);
1973         }
1974         else
1975 #endif
1976         if ((lutcn == 3 || lutcn == 4) && elemSize1 == 1)
1977         {
1978             ParallelLoopBody* p = new ipp::IppLUTParallelBody_LUTCN(src, lut, dst, &ok);
1979             body.reset(p);
1980         }
1981 #endif
1982         if (body == NULL || ok == false)
1983         {
1984             ok = false;
1985             ParallelLoopBody* p = new LUTParallelBody(src, lut, dst, &ok);
1986             body.reset(p);
1987         }
1988         if (body != NULL && ok)
1989         {
1990             Range all(0, dst.rows);
1991             if (dst.total()>>18)
1992                 parallel_for_(all, *body, (double)std::max((size_t)1, dst.total()>>16));
1993             else
1994                 (*body)(all);
1995             if (ok)
1996                 return;
1997         }
1998     }
1999
2000     LUTFunc func = lutTab[lut.depth()];
2001     CV_Assert( func != 0 );
2002
2003     const Mat* arrays[] = {&src, &dst, 0};
2004     uchar* ptrs[2];
2005     NAryMatIterator it(arrays, ptrs);
2006     int len = (int)it.size;
2007
2008     for( size_t i = 0; i < it.nplanes; i++, ++it )
2009         func(ptrs[0], lut.data, ptrs[1], len, cn, lutcn);
2010 }
2011
2012 namespace cv {
2013
2014 #ifdef HAVE_OPENCL
2015
2016 static bool ocl_normalize( InputArray _src, InputOutputArray _dst, InputArray _mask, int dtype,
2017                            double scale, double delta )
2018 {
2019     UMat src = _src.getUMat();
2020
2021     if( _mask.empty() )
2022         src.convertTo( _dst, dtype, scale, delta );
2023     else if (src.channels() <= 4)
2024     {
2025         const ocl::Device & dev = ocl::Device::getDefault();
2026
2027         int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype),
2028                 ddepth = CV_MAT_DEPTH(dtype), wdepth = std::max(CV_32F, std::max(sdepth, ddepth)),
2029                 rowsPerWI = dev.isIntel() ? 4 : 1;
2030
2031         float fscale = static_cast<float>(scale), fdelta = static_cast<float>(delta);
2032         bool haveScale = std::fabs(scale - 1) > DBL_EPSILON,
2033                 haveZeroScale = !(std::fabs(scale) > DBL_EPSILON),
2034                 haveDelta = std::fabs(delta) > DBL_EPSILON,
2035                 doubleSupport = dev.doubleFPConfig() > 0;
2036
2037         if (!haveScale && !haveDelta && stype == dtype)
2038         {
2039             _src.copyTo(_dst, _mask);
2040             return true;
2041         }
2042         if (haveZeroScale)
2043         {
2044             _dst.setTo(Scalar(delta), _mask);
2045             return true;
2046         }
2047
2048         if ((sdepth == CV_64F || ddepth == CV_64F) && !doubleSupport)
2049             return false;
2050
2051         char cvt[2][40];
2052         String opts = format("-D srcT=%s -D dstT=%s -D convertToWT=%s -D cn=%d -D rowsPerWI=%d"
2053                              " -D convertToDT=%s -D workT=%s%s%s%s -D srcT1=%s -D dstT1=%s",
2054                              ocl::typeToStr(stype), ocl::typeToStr(dtype),
2055                              ocl::convertTypeStr(sdepth, wdepth, cn, cvt[0]), cn,
2056                              rowsPerWI, ocl::convertTypeStr(wdepth, ddepth, cn, cvt[1]),
2057                              ocl::typeToStr(CV_MAKE_TYPE(wdepth, cn)),
2058                              doubleSupport ? " -D DOUBLE_SUPPORT" : "",
2059                              haveScale ? " -D HAVE_SCALE" : "",
2060                              haveDelta ? " -D HAVE_DELTA" : "",
2061                              ocl::typeToStr(sdepth), ocl::typeToStr(ddepth));
2062
2063         ocl::Kernel k("normalizek", ocl::core::normalize_oclsrc, opts);
2064         if (k.empty())
2065             return false;
2066
2067         UMat mask = _mask.getUMat(), dst = _dst.getUMat();
2068
2069         ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src),
2070                 maskarg = ocl::KernelArg::ReadOnlyNoSize(mask),
2071                 dstarg = ocl::KernelArg::ReadWrite(dst);
2072
2073         if (haveScale)
2074         {
2075             if (haveDelta)
2076                 k.args(srcarg, maskarg, dstarg, fscale, fdelta);
2077             else
2078                 k.args(srcarg, maskarg, dstarg, fscale);
2079         }
2080         else
2081         {
2082             if (haveDelta)
2083                 k.args(srcarg, maskarg, dstarg, fdelta);
2084             else
2085                 k.args(srcarg, maskarg, dstarg);
2086         }
2087
2088         size_t globalsize[2] = { src.cols, (src.rows + rowsPerWI - 1) / rowsPerWI };
2089         return k.run(2, globalsize, NULL, false);
2090     }
2091     else
2092     {
2093         UMat temp;
2094         src.convertTo( temp, dtype, scale, delta );
2095         temp.copyTo( _dst, _mask );
2096     }
2097
2098     return true;
2099 }
2100
2101 #endif
2102
2103 }
2104
2105 void cv::normalize( InputArray _src, InputOutputArray _dst, double a, double b,
2106                     int norm_type, int rtype, InputArray _mask )
2107 {
2108     double scale = 1, shift = 0;
2109     if( norm_type == CV_MINMAX )
2110     {
2111         double smin = 0, smax = 0;
2112         double dmin = MIN( a, b ), dmax = MAX( a, b );
2113         minMaxLoc( _src, &smin, &smax, 0, 0, _mask );
2114         scale = (dmax - dmin)*(smax - smin > DBL_EPSILON ? 1./(smax - smin) : 0);
2115         shift = dmin - smin*scale;
2116     }
2117     else if( norm_type == CV_L2 || norm_type == CV_L1 || norm_type == CV_C )
2118     {
2119         scale = norm( _src, norm_type, _mask );
2120         scale = scale > DBL_EPSILON ? a/scale : 0.;
2121         shift = 0;
2122     }
2123     else
2124         CV_Error( CV_StsBadArg, "Unknown/unsupported norm type" );
2125
2126     int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
2127     if( rtype < 0 )
2128         rtype = _dst.fixedType() ? _dst.depth() : depth;
2129     _dst.createSameSize(_src, CV_MAKETYPE(rtype, cn));
2130
2131     CV_OCL_RUN(_dst.isUMat(),
2132                ocl_normalize(_src, _dst, _mask, rtype, scale, shift))
2133
2134     Mat src = _src.getMat(), dst = _dst.getMat();
2135     if( _mask.empty() )
2136         src.convertTo( dst, rtype, scale, shift );
2137     else
2138     {
2139         Mat temp;
2140         src.convertTo( temp, rtype, scale, shift );
2141         temp.copyTo( dst, _mask );
2142     }
2143 }
2144
2145 CV_IMPL void
2146 cvSplit( const void* srcarr, void* dstarr0, void* dstarr1, void* dstarr2, void* dstarr3 )
2147 {
2148     void* dptrs[] = { dstarr0, dstarr1, dstarr2, dstarr3 };
2149     cv::Mat src = cv::cvarrToMat(srcarr);
2150     int i, j, nz = 0;
2151     for( i = 0; i < 4; i++ )
2152         nz += dptrs[i] != 0;
2153     CV_Assert( nz > 0 );
2154     std::vector<cv::Mat> dvec(nz);
2155     std::vector<int> pairs(nz*2);
2156
2157     for( i = j = 0; i < 4; i++ )
2158     {
2159         if( dptrs[i] != 0 )
2160         {
2161             dvec[j] = cv::cvarrToMat(dptrs[i]);
2162             CV_Assert( dvec[j].size() == src.size() );
2163             CV_Assert( dvec[j].depth() == src.depth() );
2164             CV_Assert( dvec[j].channels() == 1 );
2165             CV_Assert( i < src.channels() );
2166             pairs[j*2] = i;
2167             pairs[j*2+1] = j;
2168             j++;
2169         }
2170     }
2171     if( nz == src.channels() )
2172         cv::split( src, dvec );
2173     else
2174     {
2175         cv::mixChannels( &src, 1, &dvec[0], nz, &pairs[0], nz );
2176     }
2177 }
2178
2179
2180 CV_IMPL void
2181 cvMerge( const void* srcarr0, const void* srcarr1, const void* srcarr2,
2182          const void* srcarr3, void* dstarr )
2183 {
2184     const void* sptrs[] = { srcarr0, srcarr1, srcarr2, srcarr3 };
2185     cv::Mat dst = cv::cvarrToMat(dstarr);
2186     int i, j, nz = 0;
2187     for( i = 0; i < 4; i++ )
2188         nz += sptrs[i] != 0;
2189     CV_Assert( nz > 0 );
2190     std::vector<cv::Mat> svec(nz);
2191     std::vector<int> pairs(nz*2);
2192
2193     for( i = j = 0; i < 4; i++ )
2194     {
2195         if( sptrs[i] != 0 )
2196         {
2197             svec[j] = cv::cvarrToMat(sptrs[i]);
2198             CV_Assert( svec[j].size == dst.size &&
2199                 svec[j].depth() == dst.depth() &&
2200                 svec[j].channels() == 1 && i < dst.channels() );
2201             pairs[j*2] = j;
2202             pairs[j*2+1] = i;
2203             j++;
2204         }
2205     }
2206
2207     if( nz == dst.channels() )
2208         cv::merge( svec, dst );
2209     else
2210     {
2211         cv::mixChannels( &svec[0], nz, &dst, 1, &pairs[0], nz );
2212     }
2213 }
2214
2215
2216 CV_IMPL void
2217 cvMixChannels( const CvArr** src, int src_count,
2218                CvArr** dst, int dst_count,
2219                const int* from_to, int pair_count )
2220 {
2221     cv::AutoBuffer<cv::Mat> buf(src_count + dst_count);
2222
2223     int i;
2224     for( i = 0; i < src_count; i++ )
2225         buf[i] = cv::cvarrToMat(src[i]);
2226     for( i = 0; i < dst_count; i++ )
2227         buf[i+src_count] = cv::cvarrToMat(dst[i]);
2228     cv::mixChannels(&buf[0], src_count, &buf[src_count], dst_count, from_to, pair_count);
2229 }
2230
2231 CV_IMPL void
2232 cvConvertScaleAbs( const void* srcarr, void* dstarr,
2233                    double scale, double shift )
2234 {
2235     cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
2236     CV_Assert( src.size == dst.size && dst.type() == CV_8UC(src.channels()));
2237     cv::convertScaleAbs( src, dst, scale, shift );
2238 }
2239
2240 CV_IMPL void
2241 cvConvertScale( const void* srcarr, void* dstarr,
2242                 double scale, double shift )
2243 {
2244     cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr);
2245
2246     CV_Assert( src.size == dst.size && src.channels() == dst.channels() );
2247     src.convertTo(dst, dst.type(), scale, shift);
2248 }
2249
2250 CV_IMPL void cvLUT( const void* srcarr, void* dstarr, const void* lutarr )
2251 {
2252     cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr), lut = cv::cvarrToMat(lutarr);
2253
2254     CV_Assert( dst.size() == src.size() && dst.type() == CV_MAKETYPE(lut.depth(), src.channels()) );
2255     cv::LUT( src, lut, dst );
2256 }
2257
2258 CV_IMPL void cvNormalize( const CvArr* srcarr, CvArr* dstarr,
2259                           double a, double b, int norm_type, const CvArr* maskarr )
2260 {
2261     cv::Mat src = cv::cvarrToMat(srcarr), dst = cv::cvarrToMat(dstarr), mask;
2262     if( maskarr )
2263         mask = cv::cvarrToMat(maskarr);
2264     CV_Assert( dst.size() == src.size() && src.channels() == dst.channels() );
2265     cv::normalize( src, dst, a, b, norm_type, dst.type(), mask );
2266 }
2267
2268 /* End of file. */