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//                        Intel License Agreement
10//                For Open Source Computer Vision Library
11//
12// Copyright (C) 2000, Intel Corporation, all rights reserved.
13// Third party copyrights are property of their respective owners.
14//
15// Redistribution and use in source and binary forms, with or without modification,
16// are permitted provided that the following conditions are met:
17//
18//   * Redistribution's of source code must retain the above copyright notice,
19//     this list of conditions and the following disclaimer.
20//
21//   * Redistribution's in binary form must reproduce the above copyright notice,
22//     this list of conditions and the following disclaimer in the documentation
23//     and/or other materials provided with the distribution.
24//
25//   * The name of Intel Corporation may not be used to endorse or promote products
26//     derived from this software without specific prior written permission.
27//
28// This software is provided by the copyright holders and contributors "as is" and
29// any express or implied warranties, including, but not limited to, the implied
30// warranties of merchantability and fitness for a particular purpose are disclaimed.
31// In no event shall the Intel Corporation or contributors be liable for any direct,
32// indirect, incidental, special, exemplary, or consequential damages
33// (including, but not limited to, procurement of substitute goods or services;
34// loss of use, data, or profits; or business interruption) however caused
35// and on any theory of liability, whether in contract, strict liability,
36// or tort (including negligence or otherwise) arising in any way out of
37// the use of this software, even if advised of the possibility of such damage.
38//
39//M*/
40
41/********************************* COPYRIGHT NOTICE *******************************\
42  The function for RGB to Lab conversion is based on the MATLAB script
43  RGB2Lab.m translated by Mark Ruzon from C code by Yossi Rubner, 23 September 1997.
44  See the page [http://vision.stanford.edu/~ruzon/software/rgblab.html]
45\**********************************************************************************/
46
47/********************************* COPYRIGHT NOTICE *******************************\
48  Original code for Bayer->BGR/RGB conversion is provided by Dirk Schaefer
49  from MD-Mathematische Dienste GmbH. Below is the copyright notice:
50
51    IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
52    By downloading, copying, installing or using the software you agree
53    to this license. If you do not agree to this license, do not download,
54    install, copy or use the software.
55
56    Contributors License Agreement:
57
58      Copyright (c) 2002,
59      MD-Mathematische Dienste GmbH
60      Im Defdahl 5-10
61      44141 Dortmund
62      Germany
63      www.md-it.de
64
65    Redistribution and use in source and binary forms,
66    with or without modification, are permitted provided
67    that the following conditions are met:
68
69    Redistributions of source code must retain
70    the above copyright notice, this list of conditions and the following disclaimer.
71    Redistributions in binary form must reproduce the above copyright notice,
72    this list of conditions and the following disclaimer in the documentation
73    and/or other materials provided with the distribution.
74    The name of Contributor may not be used to endorse or promote products
75    derived from this software without specific prior written permission.
76
77    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
78    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
79    THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
80    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
81    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
82    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
83    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
84    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
85    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
86    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
87    THE POSSIBILITY OF SUCH DAMAGE.
88\**********************************************************************************/
89
90#include "_cv.h"
91
92typedef CvStatus (CV_STDCALL * CvColorCvtFunc0)(
93    const void* src, int srcstep, void* dst, int dststep, CvSize size );
94
95typedef CvStatus (CV_STDCALL * CvColorCvtFunc1)(
96    const void* src, int srcstep, void* dst, int dststep,
97    CvSize size, int param0 );
98
99typedef CvStatus (CV_STDCALL * CvColorCvtFunc2)(
100    const void* src, int srcstep, void* dst, int dststep,
101    CvSize size, int param0, int param1 );
102
103typedef CvStatus (CV_STDCALL * CvColorCvtFunc3)(
104    const void* src, int srcstep, void* dst, int dststep,
105    CvSize size, int param0, int param1, int param2 );
106
107/****************************************************************************************\
108*                 Various 3/4-channel to 3/4-channel RGB transformations                 *
109\****************************************************************************************/
110
111#define CV_IMPL_BGRX2BGR( flavor, arrtype )                             \
112static CvStatus CV_STDCALL                                              \
113icvBGRx2BGR_##flavor##_CnC3R( const arrtype* src, int srcstep,          \
114                              arrtype* dst, int dststep,                \
115                              CvSize size, int src_cn, int blue_idx )   \
116{                                                                       \
117    int i;                                                              \
118                                                                        \
119    srcstep /= sizeof(src[0]);                                          \
120    dststep /= sizeof(dst[0]);                                          \
121    srcstep -= size.width*src_cn;                                       \
122    size.width *= 3;                                                    \
123                                                                        \
124    for( ; size.height--; src += srcstep, dst += dststep )              \
125    {                                                                   \
126        for( i = 0; i < size.width; i += 3, src += src_cn )             \
127        {                                                               \
128            arrtype t0=src[blue_idx], t1=src[1], t2=src[blue_idx^2];    \
129            dst[i] = t0;                                                \
130            dst[i+1] = t1;                                              \
131            dst[i+2] = t2;                                              \
132        }                                                               \
133    }                                                                   \
134                                                                        \
135    return CV_OK;                                                       \
136}
137
138
139#define CV_IMPL_BGR2BGRX( flavor, arrtype )                             \
140static CvStatus CV_STDCALL                                              \
141icvBGR2BGRx_##flavor##_C3C4R( const arrtype* src, int srcstep,          \
142                              arrtype* dst, int dststep,                \
143                              CvSize size, int blue_idx )               \
144{                                                                       \
145    int i;                                                              \
146                                                                        \
147    srcstep /= sizeof(src[0]);                                          \
148    dststep /= sizeof(dst[0]);                                          \
149    srcstep -= size.width*3;                                            \
150    size.width *= 4;                                                    \
151                                                                        \
152    for( ; size.height--; src += srcstep, dst += dststep )              \
153    {                                                                   \
154        for( i = 0; i < size.width; i += 4, src += 3 )                  \
155        {                                                               \
156            arrtype t0=src[blue_idx], t1=src[1], t2=src[blue_idx^2];    \
157            dst[i] = t0;                                                \
158            dst[i+1] = t1;                                              \
159            dst[i+2] = t2;                                              \
160            dst[i+3] = 0;                                               \
161        }                                                               \
162    }                                                                   \
163                                                                        \
164    return CV_OK;                                                       \
165}
166
167
168#define CV_IMPL_BGRA2RGBA( flavor, arrtype )                            \
169static CvStatus CV_STDCALL                                              \
170icvBGRA2RGBA_##flavor##_C4R( const arrtype* src, int srcstep,           \
171                             arrtype* dst, int dststep, CvSize size )   \
172{                                                                       \
173    int i;                                                              \
174                                                                        \
175    srcstep /= sizeof(src[0]);                                          \
176    dststep /= sizeof(dst[0]);                                          \
177    size.width *= 4;                                                    \
178                                                                        \
179    for( ; size.height--; src += srcstep, dst += dststep )              \
180    {                                                                   \
181        for( i = 0; i < size.width; i += 4 )                            \
182        {                                                               \
183            arrtype t0 = src[2], t1 = src[1], t2 = src[0], t3 = src[3]; \
184            dst[i] = t0;                                                \
185            dst[i+1] = t1;                                              \
186            dst[i+2] = t2;                                              \
187            dst[i+3] = t3;                                              \
188        }                                                               \
189    }                                                                   \
190                                                                        \
191    return CV_OK;                                                       \
192}
193
194
195CV_IMPL_BGRX2BGR( 8u, uchar )
196CV_IMPL_BGRX2BGR( 16u, ushort )
197CV_IMPL_BGRX2BGR( 32f, int )
198CV_IMPL_BGR2BGRX( 8u, uchar )
199CV_IMPL_BGR2BGRX( 16u, ushort )
200CV_IMPL_BGR2BGRX( 32f, int )
201CV_IMPL_BGRA2RGBA( 8u, uchar )
202CV_IMPL_BGRA2RGBA( 16u, ushort )
203CV_IMPL_BGRA2RGBA( 32f, int )
204
205
206/****************************************************************************************\
207*           Transforming 16-bit (565 or 555) RGB to/from 24/32-bit (888[8]) RGB          *
208\****************************************************************************************/
209
210static CvStatus CV_STDCALL
211icvBGR5x52BGRx_8u_C2CnR( const uchar* src, int srcstep,
212                         uchar* dst, int dststep,
213                         CvSize size, int dst_cn,
214                         int blue_idx, int green_bits )
215{
216    int i;
217    assert( green_bits == 5 || green_bits == 6 );
218    dststep -= size.width*dst_cn;
219
220    for( ; size.height--; src += srcstep, dst += dststep )
221    {
222        if( green_bits == 6 )
223            for( i = 0; i < size.width; i++, dst += dst_cn )
224            {
225                unsigned t = ((const ushort*)src)[i];
226                dst[blue_idx] = (uchar)(t << 3);
227                dst[1] = (uchar)((t >> 3) & ~3);
228                dst[blue_idx ^ 2] = (uchar)((t >> 8) & ~7);
229                if( dst_cn == 4 )
230                    dst[3] = 0;
231            }
232        else
233            for( i = 0; i < size.width; i++, dst += dst_cn )
234            {
235                unsigned t = ((const ushort*)src)[i];
236                dst[blue_idx] = (uchar)(t << 3);
237                dst[1] = (uchar)((t >> 2) & ~7);
238                dst[blue_idx ^ 2] = (uchar)((t >> 7) & ~7);
239                if( dst_cn == 4 )
240                    dst[3] = 0;
241            }
242    }
243
244    return CV_OK;
245}
246
247
248static CvStatus CV_STDCALL
249icvBGRx2BGR5x5_8u_CnC2R( const uchar* src, int srcstep,
250                         uchar* dst, int dststep,
251                         CvSize size, int src_cn,
252                         int blue_idx, int green_bits )
253{
254    int i;
255    srcstep -= size.width*src_cn;
256
257    for( ; size.height--; src += srcstep, dst += dststep )
258    {
259        if( green_bits == 6 )
260            for( i = 0; i < size.width; i++, src += src_cn )
261            {
262                int t = (src[blue_idx] >> 3)|((src[1]&~3) << 3)|((src[blue_idx^2]&~7) << 8);
263                ((ushort*)dst)[i] = (ushort)t;
264            }
265        else
266            for( i = 0; i < size.width; i++, src += src_cn )
267            {
268                int t = (src[blue_idx] >> 3)|((src[1]&~7) << 2)|((src[blue_idx^2]&~7) << 7);
269                ((ushort*)dst)[i] = (ushort)t;
270            }
271    }
272
273    return CV_OK;
274}
275
276
277
278/////////////////////////// IPP Color Conversion Functions //////////////////////////////
279
280icvRGB2XYZ_8u_C3R_t  icvRGB2XYZ_8u_C3R_p = 0;
281icvRGB2XYZ_16u_C3R_t icvRGB2XYZ_16u_C3R_p = 0;
282icvRGB2XYZ_32f_C3R_t icvRGB2XYZ_32f_C3R_p = 0;
283icvXYZ2RGB_8u_C3R_t  icvXYZ2RGB_8u_C3R_p = 0;
284icvXYZ2RGB_16u_C3R_t icvXYZ2RGB_16u_C3R_p = 0;
285icvXYZ2RGB_32f_C3R_t icvXYZ2RGB_32f_C3R_p = 0;
286
287icvRGB2HSV_8u_C3R_t  icvRGB2HSV_8u_C3R_p = 0;
288icvHSV2RGB_8u_C3R_t  icvHSV2RGB_8u_C3R_p = 0;
289
290icvBGR2Lab_8u_C3R_t  icvBGR2Lab_8u_C3R_p = 0;
291icvLab2BGR_8u_C3R_t  icvLab2BGR_8u_C3R_p = 0;
292
293icvRGB2HLS_8u_C3R_t  icvRGB2HLS_8u_C3R_p = 0;
294icvRGB2HLS_32f_C3R_t icvRGB2HLS_32f_C3R_p = 0;
295icvHLS2RGB_8u_C3R_t  icvHLS2RGB_8u_C3R_p = 0;
296icvHLS2RGB_32f_C3R_t icvHLS2RGB_32f_C3R_p = 0;
297
298icvRGB2Luv_8u_C3R_t  icvRGB2Luv_8u_C3R_p = 0;
299icvLuv2RGB_8u_C3R_t  icvLuv2RGB_8u_C3R_p = 0;
300
301//icvRGB2Luv_32f_C3R_t icvRGB2Luv_32f_C3R_p = 0;
302//icvLuv2RGB_32f_C3R_t icvLuv2RGB_32f_C3R_p = 0;
303//icvRGB2Luv_32f_C3R_t icvRGB2Luv_32f_C3R_p = 0;
304//icvLuv2RGB_32f_C3R_t icvLuv2RGB_32f_C3R_p = 0;
305
306
307#define CV_IMPL_BGRx2ABC_IPP( flavor, arrtype )                         \
308static CvStatus CV_STDCALL                                              \
309icvBGRx2ABC_IPP_##flavor##_CnC3R( const arrtype* src, int srcstep,      \
310    arrtype* dst, int dststep, CvSize size, int src_cn,                 \
311    int blue_idx, CvColorCvtFunc0 ipp_func )                            \
312{                                                                       \
313    int block_size = MIN(1 << 14, size.width);                          \
314    arrtype* buffer;                                                    \
315    int i, di, k;                                                       \
316    int do_copy = src_cn > 3 || blue_idx != 2 || src == dst;            \
317    CvStatus status = CV_OK;                                            \
318                                                                        \
319    if( !do_copy )                                                      \
320        return ipp_func( src, srcstep, dst, dststep, size );            \
321                                                                        \
322    srcstep /= sizeof(src[0]);                                          \
323    dststep /= sizeof(dst[0]);                                          \
324                                                                        \
325    buffer = (arrtype*)cvStackAlloc( block_size*3*sizeof(buffer[0]) );  \
326    srcstep -= size.width*src_cn;                                       \
327                                                                        \
328    for( ; size.height--; src += srcstep, dst += dststep )              \
329    {                                                                   \
330        for( i = 0; i < size.width; i += block_size )                   \
331        {                                                               \
332            arrtype* dst1 = dst + i*3;                                  \
333            di = MIN(block_size, size.width - i);                       \
334                                                                        \
335            for( k = 0; k < di*3; k += 3, src += src_cn )               \
336            {                                                           \
337                arrtype b = src[blue_idx];                              \
338                arrtype g = src[1];                                     \
339                arrtype r = src[blue_idx^2];                            \
340                buffer[k] = r;                                          \
341                buffer[k+1] = g;                                        \
342                buffer[k+2] = b;                                        \
343            }                                                           \
344                                                                        \
345            status = ipp_func( buffer, CV_STUB_STEP,                    \
346                               dst1, CV_STUB_STEP, cvSize(di,1) );      \
347            if( status < 0 )                                            \
348                return status;                                          \
349        }                                                               \
350    }                                                                   \
351                                                                        \
352    return CV_OK;                                                       \
353}
354
355
356static CvStatus CV_STDCALL
357icvBGRx2ABC_IPP_8u_CnC3R( const uchar* src, int srcstep,
358    uchar* dst, int dststep, CvSize size, int src_cn,
359    int blue_idx, CvColorCvtFunc0 ipp_func )
360{
361    int block_size = MIN(1 << 14, size.width);
362    uchar* buffer;
363    int i, di, k;
364    int do_copy = src_cn > 3 || blue_idx != 2 || src == dst;
365    CvStatus status = CV_OK;
366
367    if( !do_copy )
368        return ipp_func( src, srcstep, dst, dststep, size );
369
370    srcstep /= sizeof(src[0]);
371    dststep /= sizeof(dst[0]);
372
373    buffer = (uchar*)cvStackAlloc( block_size*3*sizeof(buffer[0]) );
374    srcstep -= size.width*src_cn;
375
376    for( ; size.height--; src += srcstep, dst += dststep )
377    {
378        for( i = 0; i < size.width; i += block_size )
379        {
380            uchar* dst1 = dst + i*3;
381            di = MIN(block_size, size.width - i);
382
383            for( k = 0; k < di*3; k += 3, src += src_cn )
384            {
385                uchar b = src[blue_idx];
386                uchar g = src[1];
387                uchar r = src[blue_idx^2];
388                buffer[k] = r;
389                buffer[k+1] = g;
390                buffer[k+2] = b;
391            }
392
393            status = ipp_func( buffer, CV_STUB_STEP,
394                               dst1, CV_STUB_STEP, cvSize(di,1) );
395            if( status < 0 )
396                return status;
397        }
398    }
399
400    return CV_OK;
401}
402
403
404
405//CV_IMPL_BGRx2ABC_IPP( 8u, uchar )
406CV_IMPL_BGRx2ABC_IPP( 16u, ushort )
407CV_IMPL_BGRx2ABC_IPP( 32f, float )
408
409#define CV_IMPL_ABC2BGRx_IPP( flavor, arrtype )                         \
410static CvStatus CV_STDCALL                                              \
411icvABC2BGRx_IPP_##flavor##_C3CnR( const arrtype* src, int srcstep,      \
412    arrtype* dst, int dststep, CvSize size, int dst_cn,                 \
413    int blue_idx, CvColorCvtFunc0 ipp_func )                            \
414{                                                                       \
415    int block_size = MIN(1 << 10, size.width);                          \
416    arrtype* buffer;                                                    \
417    int i, di, k;                                                       \
418    int do_copy = dst_cn > 3 || blue_idx != 2 || src == dst;            \
419    CvStatus status = CV_OK;                                            \
420                                                                        \
421    if( !do_copy )                                                      \
422        return ipp_func( src, srcstep, dst, dststep, size );            \
423                                                                        \
424    srcstep /= sizeof(src[0]);                                          \
425    dststep /= sizeof(dst[0]);                                          \
426                                                                        \
427    buffer = (arrtype*)cvStackAlloc( block_size*3*sizeof(buffer[0]) );  \
428    dststep -= size.width*dst_cn;                                       \
429                                                                        \
430    for( ; size.height--; src += srcstep, dst += dststep )              \
431    {                                                                   \
432        for( i = 0; i < size.width; i += block_size )                   \
433        {                                                               \
434            const arrtype* src1 = src + i*3;                            \
435            di = MIN(block_size, size.width - i);                       \
436                                                                        \
437            status = ipp_func( src1, CV_STUB_STEP,                      \
438                               buffer, CV_STUB_STEP, cvSize(di,1) );    \
439            if( status < 0 )                                            \
440                return status;                                          \
441                                                                        \
442            for( k = 0; k < di*3; k += 3, dst += dst_cn )               \
443            {                                                           \
444                arrtype r = buffer[k];                                  \
445                arrtype g = buffer[k+1];                                \
446                arrtype b = buffer[k+2];                                \
447                dst[blue_idx] = b;                                      \
448                dst[1] = g;                                             \
449                dst[blue_idx^2] = r;                                    \
450                if( dst_cn == 4 )                                       \
451                    dst[3] = 0;                                         \
452            }                                                           \
453        }                                                               \
454    }                                                                   \
455                                                                        \
456    return CV_OK;                                                       \
457}
458
459CV_IMPL_ABC2BGRx_IPP( 8u, uchar )
460CV_IMPL_ABC2BGRx_IPP( 16u, ushort )
461CV_IMPL_ABC2BGRx_IPP( 32f, float )
462
463
464/////////////////////////////////////////////////////////////////////////////////////////
465
466
467/****************************************************************************************\
468*                                 Color to/from Grayscale                                *
469\****************************************************************************************/
470
471#define fix(x,n)      (int)((x)*(1 << (n)) + 0.5)
472#define descale       CV_DESCALE
473
474#define cscGr_32f  0.299f
475#define cscGg_32f  0.587f
476#define cscGb_32f  0.114f
477
478/* BGR/RGB -> Gray */
479#define csc_shift  14
480#define cscGr  fix(cscGr_32f,csc_shift)
481#define cscGg  fix(cscGg_32f,csc_shift)
482#define cscGb  /*fix(cscGb_32f,csc_shift)*/ ((1 << csc_shift) - cscGr - cscGg)
483
484#define CV_IMPL_GRAY2BGRX( flavor, arrtype )                    \
485static CvStatus CV_STDCALL                                      \
486icvGray2BGRx_##flavor##_C1CnR( const arrtype* src, int srcstep, \
487                       arrtype* dst, int dststep, CvSize size,  \
488                       int dst_cn )                             \
489{                                                               \
490    int i;                                                      \
491    srcstep /= sizeof(src[0]);                                  \
492    dststep /= sizeof(src[0]);                                  \
493    dststep -= size.width*dst_cn;                               \
494                                                                \
495    for( ; size.height--; src += srcstep, dst += dststep )      \
496    {                                                           \
497        if( dst_cn == 3 )                                       \
498            for( i = 0; i < size.width; i++, dst += 3 )         \
499                dst[0] = dst[1] = dst[2] = src[i];              \
500        else                                                    \
501            for( i = 0; i < size.width; i++, dst += 4 )         \
502            {                                                   \
503                dst[0] = dst[1] = dst[2] = src[i];              \
504                dst[3] = 0;                                     \
505            }                                                   \
506    }                                                           \
507                                                                \
508    return CV_OK;                                               \
509}
510
511
512CV_IMPL_GRAY2BGRX( 8u, uchar )
513CV_IMPL_GRAY2BGRX( 16u, ushort )
514CV_IMPL_GRAY2BGRX( 32f, float )
515
516
517static CvStatus CV_STDCALL
518icvBGR5x52Gray_8u_C2C1R( const uchar* src, int srcstep,
519                         uchar* dst, int dststep,
520                         CvSize size, int green_bits )
521{
522    int i;
523    assert( green_bits == 5 || green_bits == 6 );
524
525    for( ; size.height--; src += srcstep, dst += dststep )
526    {
527        if( green_bits == 6 )
528            for( i = 0; i < size.width; i++ )
529            {
530                int t = ((ushort*)src)[i];
531                t = ((t << 3) & 0xf8)*cscGb + ((t >> 3) & 0xfc)*cscGg +
532                    ((t >> 8) & 0xf8)*cscGr;
533                dst[i] = (uchar)CV_DESCALE(t,csc_shift);
534            }
535        else
536            for( i = 0; i < size.width; i++ )
537            {
538                int t = ((ushort*)src)[i];
539                t = ((t << 3) & 0xf8)*cscGb + ((t >> 2) & 0xf8)*cscGg +
540                    ((t >> 7) & 0xf8)*cscGr;
541                dst[i] = (uchar)CV_DESCALE(t,csc_shift);
542            }
543    }
544
545    return CV_OK;
546}
547
548
549static CvStatus CV_STDCALL
550icvGray2BGR5x5_8u_C1C2R( const uchar* src, int srcstep,
551                         uchar* dst, int dststep,
552                         CvSize size, int green_bits )
553{
554    int i;
555    assert( green_bits == 5 || green_bits == 6 );
556
557    for( ; size.height--; src += srcstep, dst += dststep )
558    {
559        if( green_bits == 6 )
560            for( i = 0; i < size.width; i++ )
561            {
562                int t = src[i];
563                ((ushort*)dst)[i] = (ushort)((t >> 3)|((t & ~3) << 3)|((t & ~7) << 8));
564            }
565        else
566            for( i = 0; i < size.width; i++ )
567            {
568                int t = src[i] >> 3;
569                ((ushort*)dst)[i] = (ushort)(t|(t << 5)|(t << 10));
570            }
571    }
572
573    return CV_OK;
574}
575
576
577static CvStatus CV_STDCALL
578icvBGRx2Gray_8u_CnC1R( const uchar* src, int srcstep,
579                       uchar* dst, int dststep, CvSize size,
580                       int src_cn, int blue_idx )
581{
582    int i;
583    srcstep -= size.width*src_cn;
584
585    if( size.width*size.height >= 1024 )
586    {
587        int* tab = (int*)cvStackAlloc( 256*3*sizeof(tab[0]) );
588        int r = 0, g = 0, b = (1 << (csc_shift-1));
589
590        for( i = 0; i < 256; i++ )
591        {
592            tab[i] = b;
593            tab[i+256] = g;
594            tab[i+512] = r;
595            g += cscGg;
596            if( !blue_idx )
597                b += cscGb, r += cscGr;
598            else
599                b += cscGr, r += cscGb;
600        }
601
602        for( ; size.height--; src += srcstep, dst += dststep )
603        {
604            for( i = 0; i < size.width; i++, src += src_cn )
605            {
606                int t0 = tab[src[0]] + tab[src[1] + 256] + tab[src[2] + 512];
607                dst[i] = (uchar)(t0 >> csc_shift);
608            }
609        }
610    }
611    else
612    {
613        for( ; size.height--; src += srcstep, dst += dststep )
614        {
615            for( i = 0; i < size.width; i++, src += src_cn )
616            {
617                int t0 = src[blue_idx]*cscGb + src[1]*cscGg + src[blue_idx^2]*cscGr;
618                dst[i] = (uchar)CV_DESCALE(t0, csc_shift);
619            }
620        }
621    }
622    return CV_OK;
623}
624
625
626static CvStatus CV_STDCALL
627icvBGRx2Gray_16u_CnC1R( const ushort* src, int srcstep,
628                        ushort* dst, int dststep, CvSize size,
629                        int src_cn, int blue_idx )
630{
631    int i;
632    int cb = cscGb, cr = cscGr;
633    srcstep /= sizeof(src[0]);
634    dststep /= sizeof(dst[0]);
635    srcstep -= size.width*src_cn;
636
637    if( blue_idx )
638        cb = cscGr, cr = cscGb;
639
640    for( ; size.height--; src += srcstep, dst += dststep )
641        for( i = 0; i < size.width; i++, src += src_cn )
642            dst[i] = (ushort)CV_DESCALE((unsigned)(src[0]*cb +
643                    src[1]*cscGg + src[2]*cr), csc_shift);
644
645    return CV_OK;
646}
647
648
649static CvStatus CV_STDCALL
650icvBGRx2Gray_32f_CnC1R( const float* src, int srcstep,
651                        float* dst, int dststep, CvSize size,
652                        int src_cn, int blue_idx )
653{
654    int i;
655    float cb = cscGb_32f, cr = cscGr_32f;
656    if( blue_idx )
657        cb = cscGr_32f, cr = cscGb_32f;
658
659    srcstep /= sizeof(src[0]);
660    dststep /= sizeof(dst[0]);
661    srcstep -= size.width*src_cn;
662    for( ; size.height--; src += srcstep, dst += dststep )
663        for( i = 0; i < size.width; i++, src += src_cn )
664            dst[i] = src[0]*cb + src[1]*cscGg_32f + src[2]*cr;
665
666    return CV_OK;
667}
668
669
670/****************************************************************************************\
671*                                     RGB <-> YCrCb                                      *
672\****************************************************************************************/
673
674/* BGR/RGB -> YCrCb */
675#define yuvYr_32f cscGr_32f
676#define yuvYg_32f cscGg_32f
677#define yuvYb_32f cscGb_32f
678#define yuvCr_32f 0.713f
679#define yuvCb_32f 0.564f
680
681#define yuv_shift 14
682#define yuvYr  fix(yuvYr_32f,yuv_shift)
683#define yuvYg  fix(yuvYg_32f,yuv_shift)
684#define yuvYb  fix(yuvYb_32f,yuv_shift)
685#define yuvCr  fix(yuvCr_32f,yuv_shift)
686#define yuvCb  fix(yuvCb_32f,yuv_shift)
687
688#define yuv_descale(x)  CV_DESCALE((x), yuv_shift)
689#define yuv_prescale(x) ((x) << yuv_shift)
690
691#define  yuvRCr_32f   1.403f
692#define  yuvGCr_32f   (-0.714f)
693#define  yuvGCb_32f   (-0.344f)
694#define  yuvBCb_32f   1.773f
695
696#define  yuvRCr   fix(yuvRCr_32f,yuv_shift)
697#define  yuvGCr   (-fix(-yuvGCr_32f,yuv_shift))
698#define  yuvGCb   (-fix(-yuvGCb_32f,yuv_shift))
699#define  yuvBCb   fix(yuvBCb_32f,yuv_shift)
700
701#define CV_IMPL_BGRx2YCrCb( flavor, arrtype, worktype, scale_macro, cast_macro,     \
702                            YUV_YB, YUV_YG, YUV_YR, YUV_CR, YUV_CB, YUV_Cx_BIAS )   \
703static CvStatus CV_STDCALL                                                  \
704icvBGRx2YCrCb_##flavor##_CnC3R( const arrtype* src, int srcstep,            \
705    arrtype* dst, int dststep, CvSize size, int src_cn, int blue_idx )      \
706{                                                                           \
707    int i;                                                                  \
708    srcstep /= sizeof(src[0]);                                              \
709    dststep /= sizeof(src[0]);                                              \
710    srcstep -= size.width*src_cn;                                           \
711    size.width *= 3;                                                        \
712                                                                            \
713    for( ; size.height--; src += srcstep, dst += dststep )                  \
714    {                                                                       \
715        for( i = 0; i < size.width; i += 3, src += src_cn )                 \
716        {                                                                   \
717            worktype b = src[blue_idx], r = src[2^blue_idx], y;             \
718            y = scale_macro(b*YUV_YB + src[1]*YUV_YG + r*YUV_YR);           \
719            r = scale_macro((r - y)*YUV_CR) + YUV_Cx_BIAS;                  \
720            b = scale_macro((b - y)*YUV_CB) + YUV_Cx_BIAS;                  \
721            dst[i] = cast_macro(y);                                         \
722            dst[i+1] = cast_macro(r);                                       \
723            dst[i+2] = cast_macro(b);                                       \
724        }                                                                   \
725    }                                                                       \
726                                                                            \
727    return CV_OK;                                                           \
728}
729
730
731CV_IMPL_BGRx2YCrCb( 8u, uchar, int, yuv_descale, CV_CAST_8U,
732                    yuvYb, yuvYg, yuvYr, yuvCr, yuvCb, 128 )
733
734CV_IMPL_BGRx2YCrCb( 16u, ushort, int, yuv_descale, CV_CAST_16U,
735                    yuvYb, yuvYg, yuvYr, yuvCr, yuvCb, 32768 )
736
737CV_IMPL_BGRx2YCrCb( 32f, float, float, CV_NOP, CV_NOP,
738                    yuvYb_32f, yuvYg_32f, yuvYr_32f, yuvCr_32f, yuvCb_32f, 0.5f )
739
740
741#define CV_IMPL_YCrCb2BGRx( flavor, arrtype, worktype, prescale_macro,      \
742    scale_macro, cast_macro, YUV_BCb, YUV_GCr, YUV_GCb, YUV_RCr, YUV_Cx_BIAS)\
743static CvStatus CV_STDCALL                                                  \
744icvYCrCb2BGRx_##flavor##_C3CnR( const arrtype* src, int srcstep,            \
745                                arrtype* dst, int dststep, CvSize size,     \
746                                int dst_cn, int blue_idx )                  \
747{                                                                           \
748    int i;                                                                  \
749    srcstep /= sizeof(src[0]);                                              \
750    dststep /= sizeof(src[0]);                                              \
751    dststep -= size.width*dst_cn;                                           \
752    size.width *= 3;                                                        \
753                                                                            \
754    for( ; size.height--; src += srcstep, dst += dststep )                  \
755    {                                                                       \
756        for( i = 0; i < size.width; i += 3, dst += dst_cn )                 \
757        {                                                                   \
758            worktype Y = prescale_macro(src[i]),                            \
759                     Cr = src[i+1] - YUV_Cx_BIAS,                           \
760                     Cb = src[i+2] - YUV_Cx_BIAS;                           \
761            worktype b, g, r;                                               \
762            b = scale_macro( Y + YUV_BCb*Cb );                              \
763            g = scale_macro( Y + YUV_GCr*Cr + YUV_GCb*Cb );                 \
764            r = scale_macro( Y + YUV_RCr*Cr );                              \
765                                                                            \
766            dst[blue_idx] = cast_macro(b);                                  \
767            dst[1] = cast_macro(g);                                         \
768            dst[blue_idx^2] = cast_macro(r);                                \
769            if( dst_cn == 4 )                                               \
770                dst[3] = 0;                                                 \
771        }                                                                   \
772    }                                                                       \
773                                                                            \
774    return CV_OK;                                                           \
775}
776
777
778CV_IMPL_YCrCb2BGRx( 8u, uchar, int, yuv_prescale, yuv_descale, CV_CAST_8U,
779                    yuvBCb, yuvGCr, yuvGCb, yuvRCr, 128 )
780
781CV_IMPL_YCrCb2BGRx( 16u, ushort, int, yuv_prescale, yuv_descale, CV_CAST_16U,
782                    yuvBCb, yuvGCr, yuvGCb, yuvRCr, 32768 )
783
784CV_IMPL_YCrCb2BGRx( 32f, float, float, CV_NOP, CV_NOP, CV_NOP,
785                    yuvBCb_32f, yuvGCr_32f, yuvGCb_32f, yuvRCr_32f, 0.5f )
786
787
788/****************************************************************************************\
789*                                      RGB <-> XYZ                                       *
790\****************************************************************************************/
791
792#define xyzXr_32f  0.412453f
793#define xyzXg_32f  0.357580f
794#define xyzXb_32f  0.180423f
795
796#define xyzYr_32f  0.212671f
797#define xyzYg_32f  0.715160f
798#define xyzYb_32f  0.072169f
799
800#define xyzZr_32f  0.019334f
801#define xyzZg_32f  0.119193f
802#define xyzZb_32f  0.950227f
803
804#define xyzRx_32f  3.240479f
805#define xyzRy_32f  (-1.53715f)
806#define xyzRz_32f  (-0.498535f)
807
808#define xyzGx_32f  (-0.969256f)
809#define xyzGy_32f  1.875991f
810#define xyzGz_32f  0.041556f
811
812#define xyzBx_32f  0.055648f
813#define xyzBy_32f  (-0.204043f)
814#define xyzBz_32f  1.057311f
815
816#define xyz_shift  10
817#define xyzXr_32s  fix(xyzXr_32f, xyz_shift )
818#define xyzXg_32s  fix(xyzXg_32f, xyz_shift )
819#define xyzXb_32s  fix(xyzXb_32f, xyz_shift )
820
821#define xyzYr_32s  fix(xyzYr_32f, xyz_shift )
822#define xyzYg_32s  fix(xyzYg_32f, xyz_shift )
823#define xyzYb_32s  fix(xyzYb_32f, xyz_shift )
824
825#define xyzZr_32s  fix(xyzZr_32f, xyz_shift )
826#define xyzZg_32s  fix(xyzZg_32f, xyz_shift )
827#define xyzZb_32s  fix(xyzZb_32f, xyz_shift )
828
829#define xyzRx_32s  fix(3.240479f, xyz_shift )
830#define xyzRy_32s  -fix(1.53715f, xyz_shift )
831#define xyzRz_32s  -fix(0.498535f, xyz_shift )
832
833#define xyzGx_32s  -fix(0.969256f, xyz_shift )
834#define xyzGy_32s  fix(1.875991f, xyz_shift )
835#define xyzGz_32s  fix(0.041556f, xyz_shift )
836
837#define xyzBx_32s  fix(0.055648f, xyz_shift )
838#define xyzBy_32s  -fix(0.204043f, xyz_shift )
839#define xyzBz_32s  fix(1.057311f, xyz_shift )
840
841#define xyz_descale(x) CV_DESCALE((x),xyz_shift)
842
843#define CV_IMPL_BGRx2XYZ( flavor, arrtype, worktype,                        \
844                          scale_macro, cast_macro, suffix )                 \
845static CvStatus CV_STDCALL                                                  \
846icvBGRx2XYZ_##flavor##_CnC3R( const arrtype* src, int srcstep,              \
847                              arrtype* dst, int dststep, CvSize size,       \
848                              int src_cn, int blue_idx )                    \
849{                                                                           \
850    int i;                                                                  \
851    worktype t, matrix[] =                                                  \
852    {                                                                       \
853        xyzXb##suffix, xyzXg##suffix, xyzXr##suffix,                        \
854        xyzYb##suffix, xyzYg##suffix, xyzYr##suffix,                        \
855        xyzZb##suffix, xyzZg##suffix, xyzZr##suffix                         \
856    };                                                                      \
857                                                                            \
858    if( icvRGB2XYZ_##flavor##_C3R_p )                                       \
859        return icvBGRx2ABC_IPP_##flavor##_CnC3R( src, srcstep,              \
860            dst, dststep, size, src_cn, blue_idx,                           \
861            icvRGB2XYZ_##flavor##_C3R_p );                                  \
862                                                                            \
863    srcstep /= sizeof(src[0]);                                              \
864    dststep /= sizeof(dst[0]);                                              \
865    srcstep -= size.width*src_cn;                                           \
866    size.width *= 3;                                                        \
867                                                                            \
868    if( blue_idx )                                                          \
869    {                                                                       \
870        CV_SWAP( matrix[0], matrix[2], t );                                 \
871        CV_SWAP( matrix[3], matrix[5], t );                                 \
872        CV_SWAP( matrix[6], matrix[8], t );                                 \
873    }                                                                       \
874                                                                            \
875    for( ; size.height--; src += srcstep, dst += dststep )                  \
876    {                                                                       \
877        for( i = 0; i < size.width; i += 3, src += src_cn )                 \
878        {                                                                   \
879            worktype x = scale_macro(src[0]*matrix[0] +                     \
880                    src[1]*matrix[1] + src[2]*matrix[2]);                   \
881            worktype y = scale_macro(src[0]*matrix[3] +                     \
882                    src[1]*matrix[4] + src[2]*matrix[5]);                   \
883            worktype z = scale_macro(src[0]*matrix[6] +                     \
884                    src[1]*matrix[7] + src[2]*matrix[8]);                   \
885                                                                            \
886            dst[i] = (arrtype)(x);                                          \
887            dst[i+1] = (arrtype)(y);                                        \
888            dst[i+2] = cast_macro(z); /*sum of weights for z > 1*/          \
889        }                                                                   \
890    }                                                                       \
891                                                                            \
892    return CV_OK;                                                           \
893}
894
895
896CV_IMPL_BGRx2XYZ( 8u, uchar, int, xyz_descale, CV_CAST_8U, _32s )
897CV_IMPL_BGRx2XYZ( 16u, ushort, int, xyz_descale, CV_CAST_16U, _32s )
898CV_IMPL_BGRx2XYZ( 32f, float, float, CV_NOP, CV_NOP, _32f )
899
900
901#define CV_IMPL_XYZ2BGRx( flavor, arrtype, worktype, scale_macro,           \
902                          cast_macro, suffix )                              \
903static CvStatus CV_STDCALL                                                  \
904icvXYZ2BGRx_##flavor##_C3CnR( const arrtype* src, int srcstep,              \
905                              arrtype* dst, int dststep, CvSize size,       \
906                              int dst_cn, int blue_idx )                    \
907{                                                                           \
908    int i;                                                                  \
909    worktype t, matrix[] =                                                  \
910    {                                                                       \
911        xyzBx##suffix, xyzBy##suffix, xyzBz##suffix,                        \
912        xyzGx##suffix, xyzGy##suffix, xyzGz##suffix,                        \
913        xyzRx##suffix, xyzRy##suffix, xyzRz##suffix                         \
914    };                                                                      \
915                                                                            \
916    if( icvXYZ2RGB_##flavor##_C3R_p )                                       \
917        return icvABC2BGRx_IPP_##flavor##_C3CnR( src, srcstep,              \
918            dst, dststep, size, dst_cn, blue_idx,                           \
919            icvXYZ2RGB_##flavor##_C3R_p );                                  \
920                                                                            \
921    srcstep /= sizeof(src[0]);                                              \
922    dststep /= sizeof(dst[0]);                                              \
923    dststep -= size.width*dst_cn;                                           \
924    size.width *= 3;                                                        \
925                                                                            \
926    if( blue_idx )                                                          \
927    {                                                                       \
928        CV_SWAP( matrix[0], matrix[6], t );                                 \
929        CV_SWAP( matrix[1], matrix[7], t );                                 \
930        CV_SWAP( matrix[2], matrix[8], t );                                 \
931    }                                                                       \
932                                                                            \
933    for( ; size.height--; src += srcstep, dst += dststep )                  \
934    {                                                                       \
935        for( i = 0; i < size.width; i += 3, dst += dst_cn )                 \
936        {                                                                   \
937            worktype b = scale_macro(src[i]*matrix[0] +                     \
938                    src[i+1]*matrix[1] + src[i+2]*matrix[2]);               \
939            worktype g = scale_macro(src[i]*matrix[3] +                     \
940                    src[i+1]*matrix[4] + src[i+2]*matrix[5]);               \
941            worktype r = scale_macro(src[i]*matrix[6] +                     \
942                    src[i+1]*matrix[7] + src[i+2]*matrix[8]);               \
943                                                                            \
944            dst[0] = cast_macro(b);                                         \
945            dst[1] = cast_macro(g);                                         \
946            dst[2] = cast_macro(r);                                         \
947                                                                            \
948            if( dst_cn == 4 )                                               \
949                dst[3] = 0;                                                 \
950        }                                                                   \
951    }                                                                       \
952                                                                            \
953    return CV_OK;                                                           \
954}
955
956CV_IMPL_XYZ2BGRx( 8u, uchar, int, xyz_descale, CV_CAST_8U, _32s )
957CV_IMPL_XYZ2BGRx( 16u, ushort, int, xyz_descale, CV_CAST_16U, _32s )
958CV_IMPL_XYZ2BGRx( 32f, float, float, CV_NOP, CV_NOP, _32f )
959
960
961/****************************************************************************************\
962*                          Non-linear Color Space Transformations                        *
963\****************************************************************************************/
964
965// driver color space conversion function for 8u arrays that uses 32f function
966// with appropriate pre- and post-scaling.
967static CvStatus CV_STDCALL
968icvABC2BGRx_8u_C3CnR( const uchar* src, int srcstep, uchar* dst, int dststep,
969                      CvSize size, int dst_cn, int blue_idx, CvColorCvtFunc2 cvtfunc_32f,
970                     const float* pre_coeffs, int postscale )
971{
972    int block_size = MIN(1 << 8, size.width);
973    float* buffer = (float*)cvStackAlloc( block_size*3*sizeof(buffer[0]) );
974    int i, di, k;
975    CvStatus status = CV_OK;
976
977    dststep -= size.width*dst_cn;
978
979    for( ; size.height--; src += srcstep, dst += dststep )
980    {
981        for( i = 0; i < size.width; i += block_size )
982        {
983            const uchar* src1 = src + i*3;
984            di = MIN(block_size, size.width - i);
985
986            for( k = 0; k < di*3; k += 3 )
987            {
988                float a = CV_8TO32F(src1[k])*pre_coeffs[0] + pre_coeffs[1];
989                float b = CV_8TO32F(src1[k+1])*pre_coeffs[2] + pre_coeffs[3];
990                float c = CV_8TO32F(src1[k+2])*pre_coeffs[4] + pre_coeffs[5];
991                buffer[k] = a;
992                buffer[k+1] = b;
993                buffer[k+2] = c;
994            }
995
996            status = cvtfunc_32f( buffer, 0, buffer, 0, cvSize(di,1), 3, blue_idx );
997            if( status < 0 )
998                return status;
999
1000            if( postscale )
1001            {
1002                for( k = 0; k < di*3; k += 3, dst += dst_cn )
1003                {
1004                    int b = cvRound(buffer[k]*255.);
1005                    int g = cvRound(buffer[k+1]*255.);
1006                    int r = cvRound(buffer[k+2]*255.);
1007
1008                    dst[0] = CV_CAST_8U(b);
1009                    dst[1] = CV_CAST_8U(g);
1010                    dst[2] = CV_CAST_8U(r);
1011                    if( dst_cn == 4 )
1012                        dst[3] = 0;
1013                }
1014            }
1015            else
1016            {
1017                for( k = 0; k < di*3; k += 3, dst += dst_cn )
1018                {
1019                    int b = cvRound(buffer[k]);
1020                    int g = cvRound(buffer[k+1]);
1021                    int r = cvRound(buffer[k+2]);
1022
1023                    dst[0] = CV_CAST_8U(b);
1024                    dst[1] = CV_CAST_8U(g);
1025                    dst[2] = CV_CAST_8U(r);
1026                    if( dst_cn == 4 )
1027                        dst[3] = 0;
1028                }
1029            }
1030        }
1031    }
1032
1033    return CV_OK;
1034}
1035
1036
1037// driver color space conversion function for 8u arrays that uses 32f function
1038// with appropriate pre- and post-scaling.
1039static CvStatus CV_STDCALL
1040icvBGRx2ABC_8u_CnC3R( const uchar* src, int srcstep, uchar* dst, int dststep,
1041                      CvSize size, int src_cn, int blue_idx, CvColorCvtFunc2 cvtfunc_32f,
1042                      int prescale, const float* post_coeffs )
1043{
1044    int block_size = MIN(1 << 8, size.width);
1045    float* buffer = (float*)cvStackAlloc( block_size*3*sizeof(buffer[0]) );
1046    int i, di, k;
1047    CvStatus status = CV_OK;
1048
1049    srcstep -= size.width*src_cn;
1050
1051    for( ; size.height--; src += srcstep, dst += dststep )
1052    {
1053        for( i = 0; i < size.width; i += block_size )
1054        {
1055            uchar* dst1 = dst + i*3;
1056            di = MIN(block_size, size.width - i);
1057
1058            if( prescale )
1059            {
1060                for( k = 0; k < di*3; k += 3, src += src_cn )
1061                {
1062                    float b = CV_8TO32F(src[0])*0.0039215686274509803f;
1063                    float g = CV_8TO32F(src[1])*0.0039215686274509803f;
1064                    float r = CV_8TO32F(src[2])*0.0039215686274509803f;
1065
1066                    buffer[k] = b;
1067                    buffer[k+1] = g;
1068                    buffer[k+2] = r;
1069                }
1070            }
1071            else
1072            {
1073                for( k = 0; k < di*3; k += 3, src += src_cn )
1074                {
1075                    float b = CV_8TO32F(src[0]);
1076                    float g = CV_8TO32F(src[1]);
1077                    float r = CV_8TO32F(src[2]);
1078
1079                    buffer[k] = b;
1080                    buffer[k+1] = g;
1081                    buffer[k+2] = r;
1082                }
1083            }
1084
1085            status = cvtfunc_32f( buffer, 0, buffer, 0, cvSize(di,1), 3, blue_idx );
1086            if( status < 0 )
1087                return status;
1088
1089            for( k = 0; k < di*3; k += 3 )
1090            {
1091                int a = cvRound( buffer[k]*post_coeffs[0] + post_coeffs[1] );
1092                int b = cvRound( buffer[k+1]*post_coeffs[2] + post_coeffs[3] );
1093                int c = cvRound( buffer[k+2]*post_coeffs[4] + post_coeffs[5] );
1094                dst1[k] = CV_CAST_8U(a);
1095                dst1[k+1] = CV_CAST_8U(b);
1096                dst1[k+2] = CV_CAST_8U(c);
1097            }
1098        }
1099    }
1100
1101    return CV_OK;
1102}
1103
1104
1105/****************************************************************************************\
1106*                                      RGB <-> HSV                                       *
1107\****************************************************************************************/
1108
1109static const uchar icvHue255To180[] =
1110{
1111      0,   1,   1,   2,   3,   4,   4,   5,   6,   6,   7,   8,   8,   9,  10,  11,
1112     11,  12,  13,  13,  14,  15,  16,  16,  17,  18,  18,  19,  20,  20,  21,  22,
1113     23,  23,  24,  25,  25,  26,  27,  28,  28,  29,  30,  30,  31,  32,  32,  33,
1114     34,  35,  35,  36,  37,  37,  38,  39,  40,  40,  41,  42,  42,  43,  44,  44,
1115     45,  46,  47,  47,  48,  49,  49,  50,  51,  52,  52,  53,  54,  54,  55,  56,
1116     56,  57,  58,  59,  59,  60,  61,  61,  62,  63,  64,  64,  65,  66,  66,  67,
1117     68,  68,  69,  70,  71,  71,  72,  73,  73,  74,  75,  76,  76,  77,  78,  78,
1118     79,  80,  80,  81,  82,  83,  83,  84,  85,  85,  86,  87,  88,  88,  89,  90,
1119     90,  91,  92,  92,  93,  94,  95,  95,  96,  97,  97,  98,  99, 100, 100, 101,
1120    102, 102, 103, 104, 104, 105, 106, 107, 107, 108, 109, 109, 110, 111, 112, 112,
1121    113, 114, 114, 115, 116, 116, 117, 118, 119, 119, 120, 121, 121, 122, 123, 124,
1122    124, 125, 126, 126, 127, 128, 128, 129, 130, 131, 131, 132, 133, 133, 134, 135,
1123    136, 136, 137, 138, 138, 139, 140, 140, 141, 142, 143, 143, 144, 145, 145, 146,
1124    147, 148, 148, 149, 150, 150, 151, 152, 152, 153, 154, 155, 155, 156, 157, 157,
1125    158, 159, 160, 160, 161, 162, 162, 163, 164, 164, 165, 166, 167, 167, 168, 169,
1126    169, 170, 171, 172, 172, 173, 174, 174, 175, 176, 176, 177, 178, 179, 179, 180
1127};
1128
1129
1130static const uchar icvHue180To255[] =
1131{
1132      0,   1,   3,   4,   6,   7,   9,  10,  11,  13,  14,  16,  17,  18,  20,  21,
1133     23,  24,  26,  27,  28,  30,  31,  33,  34,  35,  37,  38,  40,  41,  43,  44,
1134     45,  47,  48,  50,  51,  52,  54,  55,  57,  58,  60,  61,  62,  64,  65,  67,
1135     68,  69,  71,  72,  74,  75,  77,  78,  79,  81,  82,  84,  85,  86,  88,  89,
1136     91,  92,  94,  95,  96,  98,  99, 101, 102, 103, 105, 106, 108, 109, 111, 112,
1137    113, 115, 116, 118, 119, 120, 122, 123, 125, 126, 128, 129, 130, 132, 133, 135,
1138    136, 137, 139, 140, 142, 143, 145, 146, 147, 149, 150, 152, 153, 154, 156, 157,
1139    159, 160, 162, 163, 164, 166, 167, 169, 170, 171, 173, 174, 176, 177, 179, 180,
1140    181, 183, 184, 186, 187, 188, 190, 191, 193, 194, 196, 197, 198, 200, 201, 203,
1141    204, 205, 207, 208, 210, 211, 213, 214, 215, 217, 218, 220, 221, 222, 224, 225,
1142    227, 228, 230, 231, 232, 234, 235, 237, 238, 239, 241, 242, 244, 245, 247, 248,
1143    249, 251, 252, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1144    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1145    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1146    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1147    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1148};
1149
1150
1151static CvStatus CV_STDCALL
1152icvBGRx2HSV_8u_CnC3R( const uchar* src, int srcstep, uchar* dst, int dststep,
1153                      CvSize size, int src_cn, int blue_idx )
1154{
1155    const int hsv_shift = 12;
1156
1157    static const int div_table[] = {
1158        0, 1044480, 522240, 348160, 261120, 208896, 174080, 149211,
1159        130560, 116053, 104448, 94953, 87040, 80345, 74606, 69632,
1160        65280, 61440, 58027, 54973, 52224, 49737, 47476, 45412,
1161        43520, 41779, 40172, 38684, 37303, 36017, 34816, 33693,
1162        32640, 31651, 30720, 29842, 29013, 28229, 27486, 26782,
1163        26112, 25475, 24869, 24290, 23738, 23211, 22706, 22223,
1164        21760, 21316, 20890, 20480, 20086, 19707, 19342, 18991,
1165        18651, 18324, 18008, 17703, 17408, 17123, 16846, 16579,
1166        16320, 16069, 15825, 15589, 15360, 15137, 14921, 14711,
1167        14507, 14308, 14115, 13926, 13743, 13565, 13391, 13221,
1168        13056, 12895, 12738, 12584, 12434, 12288, 12145, 12006,
1169        11869, 11736, 11605, 11478, 11353, 11231, 11111, 10995,
1170        10880, 10768, 10658, 10550, 10445, 10341, 10240, 10141,
1171        10043, 9947, 9854, 9761, 9671, 9582, 9495, 9410,
1172        9326, 9243, 9162, 9082, 9004, 8927, 8852, 8777,
1173        8704, 8632, 8561, 8492, 8423, 8356, 8290, 8224,
1174        8160, 8097, 8034, 7973, 7913, 7853, 7795, 7737,
1175        7680, 7624, 7569, 7514, 7461, 7408, 7355, 7304,
1176        7253, 7203, 7154, 7105, 7057, 7010, 6963, 6917,
1177        6872, 6827, 6782, 6739, 6695, 6653, 6611, 6569,
1178        6528, 6487, 6447, 6408, 6369, 6330, 6292, 6254,
1179        6217, 6180, 6144, 6108, 6073, 6037, 6003, 5968,
1180        5935, 5901, 5868, 5835, 5803, 5771, 5739, 5708,
1181        5677, 5646, 5615, 5585, 5556, 5526, 5497, 5468,
1182        5440, 5412, 5384, 5356, 5329, 5302, 5275, 5249,
1183        5222, 5196, 5171, 5145, 5120, 5095, 5070, 5046,
1184        5022, 4998, 4974, 4950, 4927, 4904, 4881, 4858,
1185        4836, 4813, 4791, 4769, 4748, 4726, 4705, 4684,
1186        4663, 4642, 4622, 4601, 4581, 4561, 4541, 4522,
1187        4502, 4483, 4464, 4445, 4426, 4407, 4389, 4370,
1188        4352, 4334, 4316, 4298, 4281, 4263, 4246, 4229,
1189        4212, 4195, 4178, 4161, 4145, 4128, 4112, 4096
1190    };
1191
1192    int i;
1193    if( icvRGB2HSV_8u_C3R_p )
1194    {
1195        CvStatus status = icvBGRx2ABC_IPP_8u_CnC3R( src, srcstep, dst, dststep, size,
1196                                                src_cn, blue_idx, icvRGB2HSV_8u_C3R_p );
1197        if( status >= 0 )
1198        {
1199            size.width *= 3;
1200            for( ; size.height--; dst += dststep )
1201            {
1202                for( i = 0; i <= size.width - 12; i += 12 )
1203                {
1204                    uchar t0 = icvHue255To180[dst[i]], t1 = icvHue255To180[dst[i+3]];
1205                    dst[i] = t0; dst[i+3] = t1;
1206                    t0 = icvHue255To180[dst[i+6]]; t1 = icvHue255To180[dst[i+9]];
1207                    dst[i+6] = t0; dst[i+9] = t1;
1208                }
1209                for( ; i < size.width; i += 3 )
1210                    dst[i] = icvHue255To180[dst[i]];
1211            }
1212        }
1213        return status;
1214    }
1215
1216    srcstep -= size.width*src_cn;
1217    size.width *= 3;
1218
1219    for( ; size.height--; src += srcstep, dst += dststep )
1220    {
1221        for( i = 0; i < size.width; i += 3, src += src_cn )
1222        {
1223            int b = (src)[blue_idx], g = (src)[1], r = (src)[2^blue_idx];
1224            int h, s, v = b;
1225            int vmin = b, diff;
1226            int vr, vg;
1227
1228            CV_CALC_MAX_8U( v, g );
1229            CV_CALC_MAX_8U( v, r );
1230            CV_CALC_MIN_8U( vmin, g );
1231            CV_CALC_MIN_8U( vmin, r );
1232
1233            diff = v - vmin;
1234            vr = v == r ? -1 : 0;
1235            vg = v == g ? -1 : 0;
1236
1237            s = diff * div_table[v] >> hsv_shift;
1238            h = (vr & (g - b)) +
1239                (~vr & ((vg & (b - r + 2 * diff)) + ((~vg) & (r - g + 4 * diff))));
1240            h = ((h * div_table[diff] * 15 + (1 << (hsv_shift + 6))) >> (7 + hsv_shift))\
1241                + (h < 0 ? 30*6 : 0);
1242
1243            dst[i] = (uchar)h;
1244            dst[i+1] = (uchar)s;
1245            dst[i+2] = (uchar)v;
1246        }
1247    }
1248
1249    return CV_OK;
1250}
1251
1252
1253static CvStatus CV_STDCALL
1254icvBGRx2HSV_32f_CnC3R( const float* src, int srcstep,
1255                       float* dst, int dststep,
1256                       CvSize size, int src_cn, int blue_idx )
1257{
1258    int i;
1259    srcstep /= sizeof(src[0]);
1260    dststep /= sizeof(dst[0]);
1261    srcstep -= size.width*src_cn;
1262    size.width *= 3;
1263
1264    for( ; size.height--; src += srcstep, dst += dststep )
1265    {
1266        for( i = 0; i < size.width; i += 3, src += src_cn )
1267        {
1268            float b = src[blue_idx], g = src[1], r = src[2^blue_idx];
1269            float h, s, v;
1270
1271            float vmin, diff;
1272
1273            v = vmin = r;
1274            if( v < g ) v = g;
1275            if( v < b ) v = b;
1276            if( vmin > g ) vmin = g;
1277            if( vmin > b ) vmin = b;
1278
1279            diff = v - vmin;
1280            s = diff/(float)(fabs(v) + FLT_EPSILON);
1281            diff = (float)(60./(diff + FLT_EPSILON));
1282            if( v == r )
1283                h = (g - b)*diff;
1284            else if( v == g )
1285                h = (b - r)*diff + 120.f;
1286            else
1287                h = (r - g)*diff + 240.f;
1288
1289            if( h < 0 ) h += 360.f;
1290
1291            dst[i] = h;
1292            dst[i+1] = s;
1293            dst[i+2] = v;
1294        }
1295    }
1296
1297    return CV_OK;
1298}
1299
1300
1301static CvStatus CV_STDCALL
1302icvHSV2BGRx_32f_C3CnR( const float* src, int srcstep, float* dst,
1303                       int dststep, CvSize size, int dst_cn, int blue_idx )
1304{
1305    int i;
1306    srcstep /= sizeof(src[0]);
1307    dststep /= sizeof(dst[0]);
1308    dststep -= size.width*dst_cn;
1309    size.width *= 3;
1310
1311    for( ; size.height--; src += srcstep, dst += dststep )
1312    {
1313        for( i = 0; i < size.width; i += 3, dst += dst_cn )
1314        {
1315            float h = src[i], s = src[i+1], v = src[i+2];
1316            float b, g, r;
1317
1318            if( s == 0 )
1319                b = g = r = v;
1320            else
1321            {
1322                static const int sector_data[][3]=
1323                    {{1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0}};
1324                float tab[4];
1325                int sector;
1326                h *= 0.016666666666666666f; // h /= 60;
1327                if( h < 0 )
1328                    do h += 6; while( h < 0 );
1329                else if( h >= 6 )
1330                    do h -= 6; while( h >= 6 );
1331                sector = cvFloor(h);
1332                h -= sector;
1333
1334                tab[0] = v;
1335                tab[1] = v*(1.f - s);
1336                tab[2] = v*(1.f - s*h);
1337                tab[3] = v*(1.f - s*(1.f - h));
1338
1339                b = tab[sector_data[sector][0]];
1340                g = tab[sector_data[sector][1]];
1341                r = tab[sector_data[sector][2]];
1342            }
1343
1344            dst[blue_idx] = b;
1345            dst[1] = g;
1346            dst[blue_idx^2] = r;
1347            if( dst_cn == 4 )
1348                dst[3] = 0;
1349        }
1350    }
1351
1352    return CV_OK;
1353}
1354
1355
1356static CvStatus CV_STDCALL
1357icvHSV2BGRx_8u_C3CnR( const uchar* src, int srcstep, uchar* dst, int dststep,
1358                      CvSize size, int dst_cn, int blue_idx )
1359{
1360    static const float pre_coeffs[] = { 2.f, 0.f, 0.0039215686274509803f, 0.f, 1.f, 0.f };
1361
1362    if( icvHSV2RGB_8u_C3R_p )
1363    {
1364        int block_size = MIN(1 << 14, size.width);
1365        uchar* buffer;
1366        int i, di, k;
1367        CvStatus status = CV_OK;
1368
1369        buffer = (uchar*)cvStackAlloc( block_size*3*sizeof(buffer[0]) );
1370        dststep -= size.width*dst_cn;
1371
1372        for( ; size.height--; src += srcstep, dst += dststep )
1373        {
1374            for( i = 0; i < size.width; i += block_size )
1375            {
1376                const uchar* src1 = src + i*3;
1377                di = MIN(block_size, size.width - i);
1378                for( k = 0; k < di*3; k += 3 )
1379                {
1380                    uchar h = icvHue180To255[src1[k]];
1381                    uchar s = src1[k+1];
1382                    uchar v = src1[k+2];
1383                    buffer[k] = h;
1384                    buffer[k+1] = s;
1385                    buffer[k+2] = v;
1386                }
1387
1388                status = icvHSV2RGB_8u_C3R_p( buffer, di*3,
1389                                buffer, di*3, cvSize(di,1) );
1390                if( status < 0 )
1391                    return status;
1392
1393                for( k = 0; k < di*3; k += 3, dst += dst_cn )
1394                {
1395                    uchar r = buffer[k];
1396                    uchar g = buffer[k+1];
1397                    uchar b = buffer[k+2];
1398                    dst[blue_idx] = b;
1399                    dst[1] = g;
1400                    dst[blue_idx^2] = r;
1401                    if( dst_cn == 4 )
1402                        dst[3] = 0;
1403                }
1404            }
1405        }
1406
1407        return CV_OK;
1408    }
1409
1410    return icvABC2BGRx_8u_C3CnR( src, srcstep, dst, dststep, size, dst_cn, blue_idx,
1411                                 (CvColorCvtFunc2)icvHSV2BGRx_32f_C3CnR, pre_coeffs, 0 );
1412}
1413
1414
1415/****************************************************************************************\
1416*                                     RGB <-> HLS                                        *
1417\****************************************************************************************/
1418
1419static CvStatus CV_STDCALL
1420icvBGRx2HLS_32f_CnC3R( const float* src, int srcstep, float* dst, int dststep,
1421                       CvSize size, int src_cn, int blue_idx )
1422{
1423    int i;
1424
1425    if( icvRGB2HLS_32f_C3R_p )
1426    {
1427        CvStatus status = icvBGRx2ABC_IPP_32f_CnC3R( src, srcstep, dst, dststep, size,
1428                                                     src_cn, blue_idx, icvRGB2HLS_32f_C3R_p );
1429        if( status >= 0 )
1430        {
1431            size.width *= 3;
1432            dststep /= sizeof(dst[0]);
1433
1434            for( ; size.height--; dst += dststep )
1435            {
1436                for( i = 0; i <= size.width - 12; i += 12 )
1437                {
1438                    float t0 = dst[i]*360.f, t1 = dst[i+3]*360.f;
1439                    dst[i] = t0; dst[i+3] = t1;
1440                    t0 = dst[i+6]*360.f; t1 = dst[i+9]*360.f;
1441                    dst[i+6] = t0; dst[i+9] = t1;
1442                }
1443                for( ; i < size.width; i += 3 )
1444                    dst[i] = dst[i]*360.f;
1445            }
1446        }
1447        return status;
1448    }
1449
1450    srcstep /= sizeof(src[0]);
1451    dststep /= sizeof(dst[0]);
1452    srcstep -= size.width*src_cn;
1453    size.width *= 3;
1454
1455    for( ; size.height--; src += srcstep, dst += dststep )
1456    {
1457        for( i = 0; i < size.width; i += 3, src += src_cn )
1458        {
1459            float b = src[blue_idx], g = src[1], r = src[2^blue_idx];
1460            float h = 0.f, s = 0.f, l;
1461            float vmin, vmax, diff;
1462
1463            vmax = vmin = r;
1464            if( vmax < g ) vmax = g;
1465            if( vmax < b ) vmax = b;
1466            if( vmin > g ) vmin = g;
1467            if( vmin > b ) vmin = b;
1468
1469            diff = vmax - vmin;
1470            l = (vmax + vmin)*0.5f;
1471
1472            if( diff > FLT_EPSILON )
1473            {
1474                s = l < 0.5f ? diff/(vmax + vmin) : diff/(2 - vmax - vmin);
1475                diff = 60.f/diff;
1476
1477                if( vmax == r )
1478                    h = (g - b)*diff;
1479                else if( vmax == g )
1480                    h = (b - r)*diff + 120.f;
1481                else
1482                    h = (r - g)*diff + 240.f;
1483
1484                if( h < 0.f ) h += 360.f;
1485            }
1486
1487            dst[i] = h;
1488            dst[i+1] = l;
1489            dst[i+2] = s;
1490        }
1491    }
1492
1493    return CV_OK;
1494}
1495
1496
1497static CvStatus CV_STDCALL
1498icvHLS2BGRx_32f_C3CnR( const float* src, int srcstep, float* dst, int dststep,
1499                       CvSize size, int dst_cn, int blue_idx )
1500{
1501    int i;
1502    srcstep /= sizeof(src[0]);
1503    dststep /= sizeof(dst[0]);
1504
1505    if( icvHLS2RGB_32f_C3R_p )
1506    {
1507        int block_size = MIN(1 << 10, size.width);
1508        float* buffer;
1509        int di, k;
1510        CvStatus status = CV_OK;
1511
1512        buffer = (float*)cvStackAlloc( block_size*3*sizeof(buffer[0]) );
1513        dststep -= size.width*dst_cn;
1514
1515        for( ; size.height--; src += srcstep, dst += dststep )
1516        {
1517            for( i = 0; i < size.width; i += block_size )
1518            {
1519                const float* src1 = src + i*3;
1520                di = MIN(block_size, size.width - i);
1521                for( k = 0; k < di*3; k += 3 )
1522                {
1523                    float h = src1[k]*0.0027777777777777779f; // /360.
1524                    float s = src1[k+1], v = src1[k+2];
1525                    buffer[k] = h; buffer[k+1] = s; buffer[k+2] = v;
1526                }
1527
1528                status = icvHLS2RGB_32f_C3R_p( buffer, di*3*sizeof(dst[0]),
1529                                buffer, di*3*sizeof(dst[0]), cvSize(di,1) );
1530                if( status < 0 )
1531                    return status;
1532
1533                for( k = 0; k < di*3; k += 3, dst += dst_cn )
1534                {
1535                    float r = buffer[k], g = buffer[k+1], b = buffer[k+2];
1536                    dst[blue_idx] = b; dst[1] = g; dst[blue_idx^2] = r;
1537                    if( dst_cn == 4 )
1538                        dst[3] = 0;
1539                }
1540            }
1541        }
1542
1543        return CV_OK;
1544    }
1545
1546    dststep -= size.width*dst_cn;
1547    size.width *= 3;
1548
1549    for( ; size.height--; src += srcstep, dst += dststep )
1550    {
1551        for( i = 0; i < size.width; i += 3, dst += dst_cn )
1552        {
1553            float h = src[i], l = src[i+1], s = src[i+2];
1554            float b, g, r;
1555
1556            if( s == 0 )
1557                b = g = r = l;
1558            else
1559            {
1560                static const int sector_data[][3]=
1561                    {{1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0}};
1562                float tab[4];
1563                int sector;
1564
1565                float p2 = l <= 0.5f ? l*(1 + s) : l + s - l*s;
1566                float p1 = 2*l - p2;
1567
1568                h *= 0.016666666666666666f; // h /= 60;
1569                if( h < 0 )
1570                    do h += 6; while( h < 0 );
1571                else if( h >= 6 )
1572                    do h -= 6; while( h >= 6 );
1573
1574                assert( 0 <= h && h < 6 );
1575                sector = cvFloor(h);
1576                h -= sector;
1577
1578                tab[0] = p2;
1579                tab[1] = p1;
1580                tab[2] = p1 + (p2 - p1)*(1-h);
1581                tab[3] = p1 + (p2 - p1)*h;
1582
1583                b = tab[sector_data[sector][0]];
1584                g = tab[sector_data[sector][1]];
1585                r = tab[sector_data[sector][2]];
1586            }
1587
1588            dst[blue_idx] = b;
1589            dst[1] = g;
1590            dst[blue_idx^2] = r;
1591            if( dst_cn == 4 )
1592                dst[3] = 0;
1593        }
1594    }
1595
1596    return CV_OK;
1597}
1598
1599static CvStatus CV_STDCALL
1600icvBGRx2HLS_8u_CnC3R( const uchar* src, int srcstep, uchar* dst, int dststep,
1601                      CvSize size, int src_cn, int blue_idx )
1602{
1603    static const float post_coeffs[] = { 0.5f, 0.f, 255.f, 0.f, 255.f, 0.f };
1604
1605    if( icvRGB2HLS_8u_C3R_p )
1606    {
1607        CvStatus status = icvBGRx2ABC_IPP_8u_CnC3R( src, srcstep, dst, dststep, size,
1608                                                    src_cn, blue_idx, icvRGB2HLS_8u_C3R_p );
1609        if( status >= 0 )
1610        {
1611            size.width *= 3;
1612            for( ; size.height--; dst += dststep )
1613            {
1614                int i;
1615                for( i = 0; i <= size.width - 12; i += 12 )
1616                {
1617                    uchar t0 = icvHue255To180[dst[i]], t1 = icvHue255To180[dst[i+3]];
1618                    dst[i] = t0; dst[i+3] = t1;
1619                    t0 = icvHue255To180[dst[i+6]]; t1 = icvHue255To180[dst[i+9]];
1620                    dst[i+6] = t0; dst[i+9] = t1;
1621                }
1622                for( ; i < size.width; i += 3 )
1623                    dst[i] = icvHue255To180[dst[i]];
1624            }
1625        }
1626        return status;
1627    }
1628
1629    return icvBGRx2ABC_8u_CnC3R( src, srcstep, dst, dststep, size, src_cn, blue_idx,
1630                                 (CvColorCvtFunc2)icvBGRx2HLS_32f_CnC3R, 1, post_coeffs );
1631}
1632
1633
1634static CvStatus CV_STDCALL
1635icvHLS2BGRx_8u_C3CnR( const uchar* src, int srcstep, uchar* dst, int dststep,
1636                      CvSize size, int dst_cn, int blue_idx )
1637{
1638    static const float pre_coeffs[] = { 2.f, 0.f, 0.0039215686274509803f, 0.f,
1639                                        0.0039215686274509803f, 0.f };
1640
1641    if( icvHLS2RGB_8u_C3R_p )
1642    {
1643        int block_size = MIN(1 << 14, size.width);
1644        uchar* buffer;
1645        int i, di, k;
1646        CvStatus status = CV_OK;
1647
1648        buffer = (uchar*)cvStackAlloc( block_size*3*sizeof(buffer[0]) );
1649        dststep -= size.width*dst_cn;
1650
1651        for( ; size.height--; src += srcstep, dst += dststep )
1652        {
1653            for( i = 0; i < size.width; i += block_size )
1654            {
1655                const uchar* src1 = src + i*3;
1656                di = MIN(block_size, size.width - i);
1657                for( k = 0; k < di*3; k += 3 )
1658                {
1659                    uchar h = icvHue180To255[src1[k]];
1660                    uchar l = src1[k+1];
1661                    uchar s = src1[k+2];
1662                    buffer[k] = h;
1663                    buffer[k+1] = l;
1664                    buffer[k+2] = s;
1665                }
1666
1667                status = icvHLS2RGB_8u_C3R_p( buffer, di*3,
1668                                buffer, di*3, cvSize(di,1) );
1669                if( status < 0 )
1670                    return status;
1671
1672                for( k = 0; k < di*3; k += 3, dst += dst_cn )
1673                {
1674                    uchar r = buffer[k];
1675                    uchar g = buffer[k+1];
1676                    uchar b = buffer[k+2];
1677                    dst[blue_idx] = b;
1678                    dst[1] = g;
1679                    dst[blue_idx^2] = r;
1680                    if( dst_cn == 4 )
1681                        dst[3] = 0;
1682                }
1683            }
1684        }
1685
1686        return CV_OK;
1687    }
1688
1689    return icvABC2BGRx_8u_C3CnR( src, srcstep, dst, dststep, size, dst_cn, blue_idx,
1690                                 (CvColorCvtFunc2)icvHLS2BGRx_32f_C3CnR, pre_coeffs, 1 );
1691}
1692
1693
1694/****************************************************************************************\
1695*                                     RGB <-> L*a*b*                                     *
1696\****************************************************************************************/
1697
1698#define  labXr_32f  0.433953f /* = xyzXr_32f / 0.950456 */
1699#define  labXg_32f  0.376219f /* = xyzXg_32f / 0.950456 */
1700#define  labXb_32f  0.189828f /* = xyzXb_32f / 0.950456 */
1701
1702#define  labYr_32f  0.212671f /* = xyzYr_32f */
1703#define  labYg_32f  0.715160f /* = xyzYg_32f */
1704#define  labYb_32f  0.072169f /* = xyzYb_32f */
1705
1706#define  labZr_32f  0.017758f /* = xyzZr_32f / 1.088754 */
1707#define  labZg_32f  0.109477f /* = xyzZg_32f / 1.088754 */
1708#define  labZb_32f  0.872766f /* = xyzZb_32f / 1.088754 */
1709
1710#define  labRx_32f  3.0799327f  /* = xyzRx_32f * 0.950456 */
1711#define  labRy_32f  (-1.53715f) /* = xyzRy_32f */
1712#define  labRz_32f  (-0.542782f)/* = xyzRz_32f * 1.088754 */
1713
1714#define  labGx_32f  (-0.921235f)/* = xyzGx_32f * 0.950456 */
1715#define  labGy_32f  1.875991f   /* = xyzGy_32f */
1716#define  labGz_32f  0.04524426f /* = xyzGz_32f * 1.088754 */
1717
1718#define  labBx_32f  0.0528909755f /* = xyzBx_32f * 0.950456 */
1719#define  labBy_32f  (-0.204043f)  /* = xyzBy_32f */
1720#define  labBz_32f  1.15115158f   /* = xyzBz_32f * 1.088754 */
1721
1722#define  labT_32f   0.008856f
1723
1724#define labT   fix(labT_32f*255,lab_shift)
1725
1726#undef lab_shift
1727#define lab_shift 10
1728#define labXr  fix(labXr_32f,lab_shift)
1729#define labXg  fix(labXg_32f,lab_shift)
1730#define labXb  fix(labXb_32f,lab_shift)
1731
1732#define labYr  fix(labYr_32f,lab_shift)
1733#define labYg  fix(labYg_32f,lab_shift)
1734#define labYb  fix(labYb_32f,lab_shift)
1735
1736#define labZr  fix(labZr_32f,lab_shift)
1737#define labZg  fix(labZg_32f,lab_shift)
1738#define labZb  fix(labZb_32f,lab_shift)
1739
1740#define labSmallScale_32f  7.787f
1741#define labSmallShift_32f  0.13793103448275862f  /* 16/116 */
1742#define labLScale_32f      116.f
1743#define labLShift_32f      16.f
1744#define labLScale2_32f     903.3f
1745
1746#define labSmallScale fix(31.27 /* labSmallScale_32f*(1<<lab_shift)/255 */,lab_shift)
1747#define labSmallShift fix(141.24138 /* labSmallScale_32f*(1<<lab) */,lab_shift)
1748#define labLScale fix(295.8 /* labLScale_32f*255/100 */,lab_shift)
1749#define labLShift fix(41779.2 /* labLShift_32f*1024*255/100 */,lab_shift)
1750#define labLScale2 fix(labLScale2_32f*0.01,lab_shift)
1751
1752/* 1024*(([0..511]./255)**(1./3)) */
1753static ushort icvLabCubeRootTab[] = {
1754       0,  161,  203,  232,  256,  276,  293,  308,  322,  335,  347,  359,  369,  379,  389,  398,
1755     406,  415,  423,  430,  438,  445,  452,  459,  465,  472,  478,  484,  490,  496,  501,  507,
1756     512,  517,  523,  528,  533,  538,  542,  547,  552,  556,  561,  565,  570,  574,  578,  582,
1757     586,  590,  594,  598,  602,  606,  610,  614,  617,  621,  625,  628,  632,  635,  639,  642,
1758     645,  649,  652,  655,  659,  662,  665,  668,  671,  674,  677,  680,  684,  686,  689,  692,
1759     695,  698,  701,  704,  707,  710,  712,  715,  718,  720,  723,  726,  728,  731,  734,  736,
1760     739,  741,  744,  747,  749,  752,  754,  756,  759,  761,  764,  766,  769,  771,  773,  776,
1761     778,  780,  782,  785,  787,  789,  792,  794,  796,  798,  800,  803,  805,  807,  809,  811,
1762     813,  815,  818,  820,  822,  824,  826,  828,  830,  832,  834,  836,  838,  840,  842,  844,
1763     846,  848,  850,  852,  854,  856,  857,  859,  861,  863,  865,  867,  869,  871,  872,  874,
1764     876,  878,  880,  882,  883,  885,  887,  889,  891,  892,  894,  896,  898,  899,  901,  903,
1765     904,  906,  908,  910,  911,  913,  915,  916,  918,  920,  921,  923,  925,  926,  928,  929,
1766     931,  933,  934,  936,  938,  939,  941,  942,  944,  945,  947,  949,  950,  952,  953,  955,
1767     956,  958,  959,  961,  962,  964,  965,  967,  968,  970,  971,  973,  974,  976,  977,  979,
1768     980,  982,  983,  985,  986,  987,  989,  990,  992,  993,  995,  996,  997,  999, 1000, 1002,
1769    1003, 1004, 1006, 1007, 1009, 1010, 1011, 1013, 1014, 1015, 1017, 1018, 1019, 1021, 1022, 1024,
1770    1025, 1026, 1028, 1029, 1030, 1031, 1033, 1034, 1035, 1037, 1038, 1039, 1041, 1042, 1043, 1044,
1771    1046, 1047, 1048, 1050, 1051, 1052, 1053, 1055, 1056, 1057, 1058, 1060, 1061, 1062, 1063, 1065,
1772    1066, 1067, 1068, 1070, 1071, 1072, 1073, 1074, 1076, 1077, 1078, 1079, 1081, 1082, 1083, 1084,
1773    1085, 1086, 1088, 1089, 1090, 1091, 1092, 1094, 1095, 1096, 1097, 1098, 1099, 1101, 1102, 1103,
1774    1104, 1105, 1106, 1107, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1117, 1118, 1119, 1120, 1121,
1775    1122, 1123, 1124, 1125, 1127, 1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1138, 1139,
1776    1140, 1141, 1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1154, 1155, 1156,
1777    1157, 1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172,
1778    1173, 1174, 1175, 1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188,
1779    1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204,
1780    1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1215, 1216, 1217, 1218, 1219,
1781    1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1230, 1231, 1232, 1233, 1234,
1782    1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249,
1783    1250, 1251, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1259, 1260, 1261, 1262, 1263,
1784    1264, 1265, 1266, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1273, 1274, 1275, 1276, 1277,
1785    1278, 1279, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1285, 1286, 1287, 1288, 1289, 1290, 1291
1786};
1787
1788
1789static CvStatus CV_STDCALL
1790icvBGRx2Lab_8u_CnC3R( const uchar* src, int srcstep, uchar* dst, int dststep,
1791                      CvSize size, int src_cn, int blue_idx )
1792{
1793    int i;
1794
1795    /*if( icvBGR2Lab_8u_C3R_p )
1796        return icvBGRx2ABC_IPP_8u_CnC3R( src, srcstep, dst, dststep, size,
1797                                         src_cn, blue_idx^2, icvBGR2Lab_8u_C3R_p );*/
1798
1799    srcstep -= size.width*src_cn;
1800    size.width *= 3;
1801
1802    for( ; size.height--; src += srcstep, dst += dststep )
1803    {
1804        for( i = 0; i < size.width; i += 3, src += src_cn )
1805        {
1806            int b = src[blue_idx], g = src[1], r = src[2^blue_idx];
1807            int x, y, z, f;
1808            int L, a;
1809
1810            x = b*labXb + g*labXg + r*labXr;
1811            y = b*labYb + g*labYg + r*labYr;
1812            z = b*labZb + g*labZg + r*labZr;
1813
1814            f = x > labT;
1815            x = CV_DESCALE( x, lab_shift );
1816
1817            if( f )
1818                assert( (unsigned)x < 512 ), x = icvLabCubeRootTab[x];
1819            else
1820                x = CV_DESCALE(x*labSmallScale + labSmallShift,lab_shift);
1821
1822            f = z > labT;
1823            z = CV_DESCALE( z, lab_shift );
1824
1825            if( f )
1826                assert( (unsigned)z < 512 ), z = icvLabCubeRootTab[z];
1827            else
1828                z = CV_DESCALE(z*labSmallScale + labSmallShift,lab_shift);
1829
1830            f = y > labT;
1831            y = CV_DESCALE( y, lab_shift );
1832
1833            if( f )
1834            {
1835                assert( (unsigned)y < 512 ), y = icvLabCubeRootTab[y];
1836                L = CV_DESCALE(y*labLScale - labLShift, 2*lab_shift );
1837            }
1838            else
1839            {
1840                L = CV_DESCALE(y*labLScale2,lab_shift);
1841                y = CV_DESCALE(y*labSmallScale + labSmallShift,lab_shift);
1842            }
1843
1844            a = CV_DESCALE( 500*(x - y), lab_shift ) + 128;
1845            b = CV_DESCALE( 200*(y - z), lab_shift ) + 128;
1846
1847            dst[i] = CV_CAST_8U(L);
1848            dst[i+1] = CV_CAST_8U(a);
1849            dst[i+2] = CV_CAST_8U(b);
1850        }
1851    }
1852
1853    return CV_OK;
1854}
1855
1856
1857static CvStatus CV_STDCALL
1858icvBGRx2Lab_32f_CnC3R( const float* src, int srcstep, float* dst, int dststep,
1859                       CvSize size, int src_cn, int blue_idx )
1860{
1861    int i;
1862    srcstep /= sizeof(src[0]);
1863    dststep /= sizeof(dst[0]);
1864    srcstep -= size.width*src_cn;
1865    size.width *= 3;
1866
1867    for( ; size.height--; src += srcstep, dst += dststep )
1868    {
1869        for( i = 0; i < size.width; i += 3, src += src_cn )
1870        {
1871            float b = src[blue_idx], g = src[1], r = src[2^blue_idx];
1872            float x, y, z;
1873            float L, a;
1874
1875            x = b*labXb_32f + g*labXg_32f + r*labXr_32f;
1876            y = b*labYb_32f + g*labYg_32f + r*labYr_32f;
1877            z = b*labZb_32f + g*labZg_32f + r*labZr_32f;
1878
1879            if( x > labT_32f )
1880                x = cvCbrt(x);
1881            else
1882                x = x*labSmallScale_32f + labSmallShift_32f;
1883
1884            if( z > labT_32f )
1885                z = cvCbrt(z);
1886            else
1887                z = z*labSmallScale_32f + labSmallShift_32f;
1888
1889            if( y > labT_32f )
1890            {
1891                y = cvCbrt(y);
1892                L = y*labLScale_32f - labLShift_32f;
1893            }
1894            else
1895            {
1896                L = y*labLScale2_32f;
1897                y = y*labSmallScale_32f + labSmallShift_32f;
1898            }
1899
1900            a = 500.f*(x - y);
1901            b = 200.f*(y - z);
1902
1903            dst[i] = L;
1904            dst[i+1] = a;
1905            dst[i+2] = b;
1906        }
1907    }
1908
1909    return CV_OK;
1910}
1911
1912
1913static CvStatus CV_STDCALL
1914icvLab2BGRx_32f_C3CnR( const float* src, int srcstep, float* dst, int dststep,
1915                       CvSize size, int dst_cn, int blue_idx )
1916{
1917    int i;
1918    srcstep /= sizeof(src[0]);
1919    dststep /= sizeof(dst[0]);
1920    dststep -= size.width*dst_cn;
1921    size.width *= 3;
1922
1923    for( ; size.height--; src += srcstep, dst += dststep )
1924    {
1925        for( i = 0; i < size.width; i += 3, dst += dst_cn )
1926        {
1927            float L = src[i], a = src[i+1], b = src[i+2];
1928            float x, y, z;
1929            float g, r;
1930
1931            L = (L + labLShift_32f)*(1.f/labLScale_32f);
1932            x = (L + a*0.002f);
1933            z = (L - b*0.005f);
1934            y = L*L*L;
1935            x = x*x*x;
1936            z = z*z*z;
1937
1938            b = x*labBx_32f + y*labBy_32f + z*labBz_32f;
1939            g = x*labGx_32f + y*labGy_32f + z*labGz_32f;
1940            r = x*labRx_32f + y*labRy_32f + z*labRz_32f;
1941
1942            dst[blue_idx] = b;
1943            dst[1] = g;
1944            dst[blue_idx^2] = r;
1945            if( dst_cn == 4 )
1946                dst[3] = 0;
1947        }
1948    }
1949
1950    return CV_OK;
1951}
1952
1953
1954static CvStatus CV_STDCALL
1955icvLab2BGRx_8u_C3CnR( const uchar* src, int srcstep, uchar* dst, int dststep,
1956                      CvSize size, int dst_cn, int blue_idx )
1957{
1958    // L: [0..255] -> [0..100]
1959    // a: [0..255] -> [-128..127]
1960    // b: [0..255] -> [-128..127]
1961    static const float pre_coeffs[] = { 0.39215686274509809f, 0.f, 1.f, -128.f, 1.f, -128.f };
1962
1963    if( icvLab2BGR_8u_C3R_p )
1964        return icvABC2BGRx_IPP_8u_C3CnR( src, srcstep, dst, dststep, size,
1965                                         dst_cn, blue_idx^2, icvLab2BGR_8u_C3R_p );
1966
1967    return icvABC2BGRx_8u_C3CnR( src, srcstep, dst, dststep, size, dst_cn, blue_idx,
1968                                 (CvColorCvtFunc2)icvLab2BGRx_32f_C3CnR, pre_coeffs, 1 );
1969}
1970
1971
1972/****************************************************************************************\
1973*                                     RGB <-> L*u*v*                                     *
1974\****************************************************************************************/
1975
1976#define luvUn_32f  0.19793943f
1977#define luvVn_32f  0.46831096f
1978#define luvYmin_32f  0.05882353f /* 15/255 */
1979
1980static CvStatus CV_STDCALL
1981icvBGRx2Luv_32f_CnC3R( const float* src, int srcstep, float* dst, int dststep,
1982                       CvSize size, int src_cn, int blue_idx )
1983{
1984    int i;
1985
1986    /*if( icvRGB2Luv_32f_C3R_p )
1987        return icvBGRx2ABC_IPP_32f_CnC3R( src, srcstep, dst, dststep, size,
1988                                          src_cn, blue_idx, icvRGB2Luv_32f_C3R_p );*/
1989
1990    srcstep /= sizeof(src[0]);
1991    dststep /= sizeof(dst[0]);
1992    srcstep -= size.width*src_cn;
1993    size.width *= 3;
1994
1995    for( ; size.height--; src += srcstep, dst += dststep )
1996    {
1997        for( i = 0; i < size.width; i += 3, src += src_cn )
1998        {
1999            float b = src[blue_idx], g = src[1], r = src[2^blue_idx];
2000            float x, y, z;
2001            float L, u, v, t;
2002
2003            x = b*xyzXb_32f + g*xyzXg_32f + r*xyzXr_32f;
2004            y = b*xyzYb_32f + g*xyzYg_32f + r*xyzYr_32f;
2005            z = b*xyzZb_32f + g*xyzZg_32f + r*xyzZr_32f;
2006
2007            if( !x && !y && !z )
2008                L = u = v = 0.f;
2009            else
2010            {
2011                if( y > labT_32f )
2012                    L = labLScale_32f * cvCbrt(y) - labLShift_32f;
2013                else
2014                    L = labLScale2_32f * y;
2015
2016                t = 1.f / (x + 15 * y + 3 * z);
2017                u = 4.0f * x * t;
2018                v = 9.0f * y * t;
2019
2020                u = 13*L*(u - luvUn_32f);
2021                v = 13*L*(v - luvVn_32f);
2022            }
2023
2024            dst[i] = L;
2025            dst[i+1] = u;
2026            dst[i+2] = v;
2027        }
2028    }
2029
2030    return CV_OK;
2031}
2032
2033
2034static CvStatus CV_STDCALL
2035icvLuv2BGRx_32f_C3CnR( const float* src, int srcstep, float* dst, int dststep,
2036                       CvSize size, int dst_cn, int blue_idx )
2037{
2038    int i;
2039
2040    /*if( icvLuv2RGB_32f_C3R_p )
2041        return icvABC2BGRx_IPP_32f_C3CnR( src, srcstep, dst, dststep, size,
2042                                          dst_cn, blue_idx, icvLuv2RGB_32f_C3R_p );*/
2043
2044    srcstep /= sizeof(src[0]);
2045    dststep /= sizeof(dst[0]);
2046    dststep -= size.width*dst_cn;
2047    size.width *= 3;
2048
2049    for( ; size.height--; src += srcstep, dst += dststep )
2050    {
2051        for( i = 0; i < size.width; i += 3, dst += dst_cn )
2052        {
2053            float L = src[i], u = src[i+1], v = src[i+2];
2054            float x, y, z, t, u1, v1, b, g, r;
2055
2056            if( L >= 8 )
2057            {
2058                t = (L + labLShift_32f) * (1.f/labLScale_32f);
2059                y = t*t*t;
2060            }
2061            else
2062            {
2063                y = L * (1.f/labLScale2_32f);
2064                L = MAX( L, 0.001f );
2065            }
2066
2067            t = 1.f/(13.f * L);
2068            u1 = u*t + luvUn_32f;
2069            v1 = v*t + luvVn_32f;
2070            x = 2.25f * u1 * y / v1 ;
2071            z = (12 - 3 * u1 - 20 * v1) * y / (4 * v1);
2072
2073            b = xyzBx_32f*x + xyzBy_32f*y + xyzBz_32f*z;
2074            g = xyzGx_32f*x + xyzGy_32f*y + xyzGz_32f*z;
2075            r = xyzRx_32f*x + xyzRy_32f*y + xyzRz_32f*z;
2076
2077            dst[blue_idx] = b;
2078            dst[1] = g;
2079            dst[blue_idx^2] = r;
2080            if( dst_cn == 4 )
2081                dst[3] = 0.f;
2082        }
2083    }
2084
2085    return CV_OK;
2086}
2087
2088
2089static CvStatus CV_STDCALL
2090icvBGRx2Luv_8u_CnC3R( const uchar* src, int srcstep, uchar* dst, int dststep,
2091                      CvSize size, int src_cn, int blue_idx )
2092{
2093    // L: [0..100] -> [0..255]
2094    // u: [-134..220] -> [0..255]
2095    // v: [-140..122] -> [0..255]
2096    //static const float post_coeffs[] = { 2.55f, 0.f, 1.f, 83.f, 1.f, 140.f };
2097    static const float post_coeffs[] = { 2.55f, 0.f, 0.72033898305084743f, 96.525423728813564f,
2098                                         0.99609375f, 139.453125f };
2099
2100    if( icvRGB2Luv_8u_C3R_p )
2101        return icvBGRx2ABC_IPP_8u_CnC3R( src, srcstep, dst, dststep, size,
2102                                         src_cn, blue_idx, icvRGB2Luv_8u_C3R_p );
2103
2104    return icvBGRx2ABC_8u_CnC3R( src, srcstep, dst, dststep, size, src_cn, blue_idx,
2105                                 (CvColorCvtFunc2)icvBGRx2Luv_32f_CnC3R, 1, post_coeffs );
2106}
2107
2108
2109static CvStatus CV_STDCALL
2110icvLuv2BGRx_8u_C3CnR( const uchar* src, int srcstep, uchar* dst, int dststep,
2111                      CvSize size, int dst_cn, int blue_idx )
2112{
2113    // L: [0..255] -> [0..100]
2114    // u: [0..255] -> [-134..220]
2115    // v: [0..255] -> [-140..122]
2116    static const float pre_coeffs[] = { 0.39215686274509809f, 0.f, 1.388235294117647f, -134.f,
2117                                        1.003921568627451f, -140.f };
2118
2119    if( icvLuv2RGB_8u_C3R_p )
2120        return icvABC2BGRx_IPP_8u_C3CnR( src, srcstep, dst, dststep, size,
2121                                         dst_cn, blue_idx, icvLuv2RGB_8u_C3R_p );
2122
2123    return icvABC2BGRx_8u_C3CnR( src, srcstep, dst, dststep, size, dst_cn, blue_idx,
2124                                 (CvColorCvtFunc2)icvLuv2BGRx_32f_C3CnR, pre_coeffs, 1 );
2125}
2126
2127/****************************************************************************************\
2128*                            Bayer Pattern -> RGB conversion                             *
2129\****************************************************************************************/
2130
2131static CvStatus CV_STDCALL
2132icvBayer2BGR_8u_C1C3R( const uchar* bayer0, int bayer_step,
2133                       uchar *dst0, int dst_step,
2134                       CvSize size, int code )
2135{
2136    int blue = code == CV_BayerBG2BGR || code == CV_BayerGB2BGR ? -1 : 1;
2137    int start_with_green = code == CV_BayerGB2BGR || code == CV_BayerGR2BGR;
2138
2139    memset( dst0, 0, size.width*3*sizeof(dst0[0]) );
2140    memset( dst0 + (size.height - 1)*dst_step, 0, size.width*3*sizeof(dst0[0]) );
2141    dst0 += dst_step + 3 + 1;
2142    size.height -= 2;
2143    size.width -= 2;
2144
2145    for( ; size.height-- > 0; bayer0 += bayer_step, dst0 += dst_step )
2146    {
2147        int t0, t1;
2148        const uchar* bayer = bayer0;
2149        uchar* dst = dst0;
2150        const uchar* bayer_end = bayer + size.width;
2151
2152        dst[-4] = dst[-3] = dst[-2] = dst[size.width*3-1] =
2153            dst[size.width*3] = dst[size.width*3+1] = 0;
2154
2155        if( size.width <= 0 )
2156            continue;
2157
2158        if( start_with_green )
2159        {
2160            t0 = (bayer[1] + bayer[bayer_step*2+1] + 1) >> 1;
2161            t1 = (bayer[bayer_step] + bayer[bayer_step+2] + 1) >> 1;
2162            dst[-blue] = (uchar)t0;
2163            dst[0] = bayer[bayer_step+1];
2164            dst[blue] = (uchar)t1;
2165            bayer++;
2166            dst += 3;
2167        }
2168
2169        if( blue > 0 )
2170        {
2171            for( ; bayer <= bayer_end - 2; bayer += 2, dst += 6 )
2172            {
2173                t0 = (bayer[0] + bayer[2] + bayer[bayer_step*2] +
2174                      bayer[bayer_step*2+2] + 2) >> 2;
2175                t1 = (bayer[1] + bayer[bayer_step] +
2176                      bayer[bayer_step+2] + bayer[bayer_step*2+1]+2) >> 2;
2177                dst[-1] = (uchar)t0;
2178                dst[0] = (uchar)t1;
2179                dst[1] = bayer[bayer_step+1];
2180
2181                t0 = (bayer[2] + bayer[bayer_step*2+2] + 1) >> 1;
2182                t1 = (bayer[bayer_step+1] + bayer[bayer_step+3] + 1) >> 1;
2183                dst[2] = (uchar)t0;
2184                dst[3] = bayer[bayer_step+2];
2185                dst[4] = (uchar)t1;
2186            }
2187        }
2188        else
2189        {
2190            for( ; bayer <= bayer_end - 2; bayer += 2, dst += 6 )
2191            {
2192                t0 = (bayer[0] + bayer[2] + bayer[bayer_step*2] +
2193                      bayer[bayer_step*2+2] + 2) >> 2;
2194                t1 = (bayer[1] + bayer[bayer_step] +
2195                      bayer[bayer_step+2] + bayer[bayer_step*2+1]+2) >> 2;
2196                dst[1] = (uchar)t0;
2197                dst[0] = (uchar)t1;
2198                dst[-1] = bayer[bayer_step+1];
2199
2200                t0 = (bayer[2] + bayer[bayer_step*2+2] + 1) >> 1;
2201                t1 = (bayer[bayer_step+1] + bayer[bayer_step+3] + 1) >> 1;
2202                dst[4] = (uchar)t0;
2203                dst[3] = bayer[bayer_step+2];
2204                dst[2] = (uchar)t1;
2205            }
2206        }
2207
2208        if( bayer < bayer_end )
2209        {
2210            t0 = (bayer[0] + bayer[2] + bayer[bayer_step*2] +
2211                  bayer[bayer_step*2+2] + 2) >> 2;
2212            t1 = (bayer[1] + bayer[bayer_step] +
2213                  bayer[bayer_step+2] + bayer[bayer_step*2+1]+2) >> 2;
2214            dst[-blue] = (uchar)t0;
2215            dst[0] = (uchar)t1;
2216            dst[blue] = bayer[bayer_step+1];
2217            bayer++;
2218            dst += 3;
2219        }
2220
2221        blue = -blue;
2222        start_with_green = !start_with_green;
2223    }
2224
2225    return CV_OK;
2226}
2227
2228
2229/****************************************************************************************\
2230*                                   The main function                                    *
2231\****************************************************************************************/
2232
2233CV_IMPL void
2234cvCvtColor( const CvArr* srcarr, CvArr* dstarr, int code )
2235{
2236    CV_FUNCNAME( "cvCvtColor" );
2237
2238    __BEGIN__;
2239
2240    CvMat srcstub, *src = (CvMat*)srcarr;
2241    CvMat dststub, *dst = (CvMat*)dstarr;
2242    CvSize size;
2243    int src_step, dst_step;
2244    int src_cn, dst_cn, depth;
2245    CvColorCvtFunc0 func0 = 0;
2246    CvColorCvtFunc1 func1 = 0;
2247    CvColorCvtFunc2 func2 = 0;
2248    CvColorCvtFunc3 func3 = 0;
2249    int param[] = { 0, 0, 0, 0 };
2250
2251    CV_CALL( src = cvGetMat( srcarr, &srcstub ));
2252    CV_CALL( dst = cvGetMat( dstarr, &dststub ));
2253
2254    if( !CV_ARE_SIZES_EQ( src, dst ))
2255        CV_ERROR( CV_StsUnmatchedSizes, "" );
2256
2257    if( !CV_ARE_DEPTHS_EQ( src, dst ))
2258        CV_ERROR( CV_StsUnmatchedFormats, "" );
2259
2260    depth = CV_MAT_DEPTH(src->type);
2261    if( depth != CV_8U && depth != CV_16U && depth != CV_32F )
2262        CV_ERROR( CV_StsUnsupportedFormat, "" );
2263
2264    src_cn = CV_MAT_CN( src->type );
2265    dst_cn = CV_MAT_CN( dst->type );
2266    size = cvGetMatSize( src );
2267    src_step = src->step;
2268    dst_step = dst->step;
2269
2270    if( CV_IS_MAT_CONT(src->type & dst->type) &&
2271        code != CV_BayerBG2BGR && code != CV_BayerGB2BGR &&
2272        code != CV_BayerRG2BGR && code != CV_BayerGR2BGR )
2273    {
2274        size.width *= size.height;
2275        size.height = 1;
2276        src_step = dst_step = CV_STUB_STEP;
2277    }
2278
2279    switch( code )
2280    {
2281    case CV_BGR2BGRA:
2282    case CV_RGB2BGRA:
2283        if( src_cn != 3 || dst_cn != 4 )
2284            CV_ERROR( CV_BadNumChannels,
2285            "Incorrect number of channels for this conversion code" );
2286
2287        func1 = depth == CV_8U ? (CvColorCvtFunc1)icvBGR2BGRx_8u_C3C4R :
2288                depth == CV_16U ? (CvColorCvtFunc1)icvBGR2BGRx_16u_C3C4R :
2289                depth == CV_32F ? (CvColorCvtFunc1)icvBGR2BGRx_32f_C3C4R : 0;
2290        param[0] = code == CV_BGR2BGRA ? 0 : 2; // blue_idx
2291        break;
2292
2293    case CV_BGRA2BGR:
2294    case CV_RGBA2BGR:
2295    case CV_RGB2BGR:
2296        if( (src_cn != 3 && src_cn != 4) || dst_cn != 3 )
2297            CV_ERROR( CV_BadNumChannels,
2298            "Incorrect number of channels for this conversion code" );
2299
2300        func2 = depth == CV_8U ? (CvColorCvtFunc2)icvBGRx2BGR_8u_CnC3R :
2301                depth == CV_16U ? (CvColorCvtFunc2)icvBGRx2BGR_16u_CnC3R :
2302                depth == CV_32F ? (CvColorCvtFunc2)icvBGRx2BGR_32f_CnC3R : 0;
2303        param[0] = src_cn;
2304        param[1] = code == CV_BGRA2BGR ? 0 : 2; // blue_idx
2305        break;
2306
2307    case CV_BGRA2RGBA:
2308        if( src_cn != 4 || dst_cn != 4 )
2309            CV_ERROR( CV_BadNumChannels,
2310            "Incorrect number of channels for this conversion code" );
2311
2312        func0 = depth == CV_8U ? (CvColorCvtFunc0)icvBGRA2RGBA_8u_C4R :
2313                depth == CV_16U ? (CvColorCvtFunc0)icvBGRA2RGBA_16u_C4R :
2314                depth == CV_32F ? (CvColorCvtFunc0)icvBGRA2RGBA_32f_C4R : 0;
2315        break;
2316
2317    case CV_BGR2BGR565:
2318    case CV_BGR2BGR555:
2319    case CV_RGB2BGR565:
2320    case CV_RGB2BGR555:
2321    case CV_BGRA2BGR565:
2322    case CV_BGRA2BGR555:
2323    case CV_RGBA2BGR565:
2324    case CV_RGBA2BGR555:
2325        if( (src_cn != 3 && src_cn != 4) || dst_cn != 2 )
2326            CV_ERROR( CV_BadNumChannels,
2327            "Incorrect number of channels for this conversion code" );
2328
2329        if( depth != CV_8U )
2330            CV_ERROR( CV_BadDepth,
2331            "Conversion to/from 16-bit packed RGB format "
2332            "is only possible for 8-bit images (8-bit grayscale, 888 BGR/RGB or 8888 BGRA/RGBA)" );
2333
2334        func3 = (CvColorCvtFunc3)icvBGRx2BGR5x5_8u_CnC2R;
2335        param[0] = src_cn;
2336        param[1] = code == CV_BGR2BGR565 || code == CV_BGR2BGR555 ||
2337                   code == CV_BGRA2BGR565 || code == CV_BGRA2BGR555 ? 0 : 2; // blue_idx
2338        param[2] = code == CV_BGR2BGR565 || code == CV_RGB2BGR565 ||
2339                   code == CV_BGRA2BGR565 || code == CV_RGBA2BGR565 ? 6 : 5; // green_bits
2340        break;
2341
2342    case CV_BGR5652BGR:
2343    case CV_BGR5552BGR:
2344    case CV_BGR5652RGB:
2345    case CV_BGR5552RGB:
2346    case CV_BGR5652BGRA:
2347    case CV_BGR5552BGRA:
2348    case CV_BGR5652RGBA:
2349    case CV_BGR5552RGBA:
2350        if( src_cn != 2 || (dst_cn != 3 && dst_cn != 4))
2351            CV_ERROR( CV_BadNumChannels,
2352            "Incorrect number of channels for this conversion code" );
2353
2354        if( depth != CV_8U )
2355            CV_ERROR( CV_BadDepth,
2356            "Conversion to/from 16-bit packed BGR format "
2357            "is only possible for 8-bit images (8-bit grayscale, 888 BGR/BGR or 8888 BGRA/BGRA)" );
2358
2359        func3 = (CvColorCvtFunc3)icvBGR5x52BGRx_8u_C2CnR;
2360        param[0] = dst_cn;
2361        param[1] = code == CV_BGR5652BGR || code == CV_BGR5552BGR ||
2362                   code == CV_BGR5652BGRA || code == CV_BGR5552BGRA ? 0 : 2; // blue_idx
2363        param[2] = code == CV_BGR5652BGR || code == CV_BGR5652RGB ||
2364                   code == CV_BGR5652BGRA || code == CV_BGR5652RGBA ? 6 : 5; // green_bits
2365        break;
2366
2367    case CV_BGR2GRAY:
2368    case CV_BGRA2GRAY:
2369    case CV_RGB2GRAY:
2370    case CV_RGBA2GRAY:
2371        if( (src_cn != 3 && src_cn != 4) || dst_cn != 1 )
2372            CV_ERROR( CV_BadNumChannels,
2373            "Incorrect number of channels for this conversion code" );
2374
2375        func2 = depth == CV_8U ? (CvColorCvtFunc2)icvBGRx2Gray_8u_CnC1R :
2376                depth == CV_16U ? (CvColorCvtFunc2)icvBGRx2Gray_16u_CnC1R :
2377                depth == CV_32F ? (CvColorCvtFunc2)icvBGRx2Gray_32f_CnC1R : 0;
2378
2379        param[0] = src_cn;
2380        param[1] = code == CV_BGR2GRAY || code == CV_BGRA2GRAY ? 0 : 2;
2381        break;
2382
2383    case CV_BGR5652GRAY:
2384    case CV_BGR5552GRAY:
2385        if( src_cn != 2 || dst_cn != 1 )
2386            CV_ERROR( CV_BadNumChannels,
2387            "Incorrect number of channels for this conversion code" );
2388
2389        if( depth != CV_8U )
2390            CV_ERROR( CV_BadDepth,
2391            "Conversion to/from 16-bit packed BGR format "
2392            "is only possible for 8-bit images (888 BGR/BGR or 8888 BGRA/BGRA)" );
2393
2394        func2 = (CvColorCvtFunc2)icvBGR5x52Gray_8u_C2C1R;
2395
2396        param[0] = code == CV_BGR5652GRAY ? 6 : 5; // green_bits
2397        break;
2398
2399    case CV_GRAY2BGR:
2400    case CV_GRAY2BGRA:
2401        if( src_cn != 1 || (dst_cn != 3 && dst_cn != 4))
2402            CV_ERROR( CV_BadNumChannels,
2403            "Incorrect number of channels for this conversion code" );
2404
2405        func1 = depth == CV_8U ? (CvColorCvtFunc1)icvGray2BGRx_8u_C1CnR :
2406                depth == CV_16U ? (CvColorCvtFunc1)icvGray2BGRx_16u_C1CnR :
2407                depth == CV_32F ? (CvColorCvtFunc1)icvGray2BGRx_32f_C1CnR : 0;
2408
2409        param[0] = dst_cn;
2410        break;
2411
2412    case CV_GRAY2BGR565:
2413    case CV_GRAY2BGR555:
2414        if( src_cn != 1 || dst_cn != 2 )
2415            CV_ERROR( CV_BadNumChannels,
2416            "Incorrect number of channels for this conversion code" );
2417
2418        if( depth != CV_8U )
2419            CV_ERROR( CV_BadDepth,
2420            "Conversion to/from 16-bit packed BGR format "
2421            "is only possible for 8-bit images (888 BGR/BGR or 8888 BGRA/BGRA)" );
2422
2423        func2 = (CvColorCvtFunc2)icvGray2BGR5x5_8u_C1C2R;
2424        param[0] = code == CV_GRAY2BGR565 ? 6 : 5; // green_bits
2425        break;
2426
2427    case CV_BGR2YCrCb:
2428    case CV_RGB2YCrCb:
2429    case CV_BGR2XYZ:
2430    case CV_RGB2XYZ:
2431    case CV_BGR2HSV:
2432    case CV_RGB2HSV:
2433    case CV_BGR2Lab:
2434    case CV_RGB2Lab:
2435    case CV_BGR2Luv:
2436    case CV_RGB2Luv:
2437    case CV_BGR2HLS:
2438    case CV_RGB2HLS:
2439        if( (src_cn != 3 && src_cn != 4) || dst_cn != 3 )
2440            CV_ERROR( CV_BadNumChannels,
2441            "Incorrect number of channels for this conversion code" );
2442
2443        if( depth == CV_8U )
2444            func2 = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? (CvColorCvtFunc2)icvBGRx2YCrCb_8u_CnC3R :
2445                    code == CV_BGR2XYZ || code == CV_RGB2XYZ ? (CvColorCvtFunc2)icvBGRx2XYZ_8u_CnC3R :
2446                    code == CV_BGR2HSV || code == CV_RGB2HSV ? (CvColorCvtFunc2)icvBGRx2HSV_8u_CnC3R :
2447                    code == CV_BGR2Lab || code == CV_RGB2Lab ? (CvColorCvtFunc2)icvBGRx2Lab_8u_CnC3R :
2448                    code == CV_BGR2Luv || code == CV_RGB2Luv ? (CvColorCvtFunc2)icvBGRx2Luv_8u_CnC3R :
2449                    code == CV_BGR2HLS || code == CV_RGB2HLS ? (CvColorCvtFunc2)icvBGRx2HLS_8u_CnC3R : 0;
2450        else if( depth == CV_16U )
2451            func2 = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? (CvColorCvtFunc2)icvBGRx2YCrCb_16u_CnC3R :
2452                    code == CV_BGR2XYZ || code == CV_RGB2XYZ ? (CvColorCvtFunc2)icvBGRx2XYZ_16u_CnC3R : 0;
2453        else if( depth == CV_32F )
2454            func2 = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? (CvColorCvtFunc2)icvBGRx2YCrCb_32f_CnC3R :
2455                    code == CV_BGR2XYZ || code == CV_RGB2XYZ ? (CvColorCvtFunc2)icvBGRx2XYZ_32f_CnC3R :
2456                    code == CV_BGR2HSV || code == CV_RGB2HSV ? (CvColorCvtFunc2)icvBGRx2HSV_32f_CnC3R :
2457                    code == CV_BGR2Lab || code == CV_RGB2Lab ? (CvColorCvtFunc2)icvBGRx2Lab_32f_CnC3R :
2458                    code == CV_BGR2Luv || code == CV_RGB2Luv ? (CvColorCvtFunc2)icvBGRx2Luv_32f_CnC3R :
2459                    code == CV_BGR2HLS || code == CV_RGB2HLS ? (CvColorCvtFunc2)icvBGRx2HLS_32f_CnC3R : 0;
2460
2461        param[0] = src_cn;
2462        param[1] = code == CV_BGR2XYZ || code == CV_BGR2YCrCb || code == CV_BGR2HSV ||
2463                   code == CV_BGR2Lab || code == CV_BGR2Luv || code == CV_BGR2HLS ? 0 : 2;
2464        break;
2465
2466    case CV_YCrCb2BGR:
2467    case CV_YCrCb2RGB:
2468    case CV_XYZ2BGR:
2469    case CV_XYZ2RGB:
2470    case CV_HSV2BGR:
2471    case CV_HSV2RGB:
2472    case CV_Lab2BGR:
2473    case CV_Lab2RGB:
2474    case CV_Luv2BGR:
2475    case CV_Luv2RGB:
2476    case CV_HLS2BGR:
2477    case CV_HLS2RGB:
2478        if( src_cn != 3 || (dst_cn != 3 && dst_cn != 4) )
2479            CV_ERROR( CV_BadNumChannels,
2480            "Incorrect number of channels for this conversion code" );
2481
2482        if( depth == CV_8U )
2483            func2 = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? (CvColorCvtFunc2)icvYCrCb2BGRx_8u_C3CnR :
2484                    code == CV_XYZ2BGR || code == CV_XYZ2RGB ? (CvColorCvtFunc2)icvXYZ2BGRx_8u_C3CnR :
2485                    code == CV_HSV2BGR || code == CV_HSV2RGB ? (CvColorCvtFunc2)icvHSV2BGRx_8u_C3CnR :
2486                    code == CV_HLS2BGR || code == CV_HLS2RGB ? (CvColorCvtFunc2)icvHLS2BGRx_8u_C3CnR :
2487                    code == CV_Lab2BGR || code == CV_Lab2RGB ? (CvColorCvtFunc2)icvLab2BGRx_8u_C3CnR :
2488                    code == CV_Luv2BGR || code == CV_Luv2RGB ? (CvColorCvtFunc2)icvLuv2BGRx_8u_C3CnR : 0;
2489        else if( depth == CV_16U )
2490            func2 = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? (CvColorCvtFunc2)icvYCrCb2BGRx_16u_C3CnR :
2491                    code == CV_XYZ2BGR || code == CV_XYZ2RGB ? (CvColorCvtFunc2)icvXYZ2BGRx_16u_C3CnR : 0;
2492        else if( depth == CV_32F )
2493            func2 = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? (CvColorCvtFunc2)icvYCrCb2BGRx_32f_C3CnR :
2494                    code == CV_XYZ2BGR || code == CV_XYZ2RGB ? (CvColorCvtFunc2)icvXYZ2BGRx_32f_C3CnR :
2495                    code == CV_HSV2BGR || code == CV_HSV2RGB ? (CvColorCvtFunc2)icvHSV2BGRx_32f_C3CnR :
2496                    code == CV_HLS2BGR || code == CV_HLS2RGB ? (CvColorCvtFunc2)icvHLS2BGRx_32f_C3CnR :
2497                    code == CV_Lab2BGR || code == CV_Lab2RGB ? (CvColorCvtFunc2)icvLab2BGRx_32f_C3CnR :
2498                    code == CV_Luv2BGR || code == CV_Luv2RGB ? (CvColorCvtFunc2)icvLuv2BGRx_32f_C3CnR : 0;
2499
2500        param[0] = dst_cn;
2501        param[1] = code == CV_XYZ2BGR || code == CV_YCrCb2BGR || code == CV_HSV2BGR ||
2502                   code == CV_Lab2BGR || code == CV_Luv2BGR || code == CV_HLS2BGR ? 0 : 2;
2503        break;
2504
2505    case CV_BayerBG2BGR:
2506    case CV_BayerGB2BGR:
2507    case CV_BayerRG2BGR:
2508    case CV_BayerGR2BGR:
2509        if( src_cn != 1 || dst_cn != 3 )
2510            CV_ERROR( CV_BadNumChannels,
2511            "Incorrect number of channels for this conversion code" );
2512
2513        if( depth != CV_8U )
2514            CV_ERROR( CV_BadDepth,
2515            "Bayer pattern can be converted only to 8-bit 3-channel BGR/RGB image" );
2516
2517        func1 = (CvColorCvtFunc1)icvBayer2BGR_8u_C1C3R;
2518        param[0] = code; // conversion code
2519        break;
2520    default:
2521        CV_ERROR( CV_StsBadFlag, "Unknown/unsupported color conversion code" );
2522    }
2523
2524    if( func0 )
2525    {
2526        IPPI_CALL( func0( src->data.ptr, src_step, dst->data.ptr, dst_step, size ));
2527    }
2528    else if( func1 )
2529    {
2530        IPPI_CALL( func1( src->data.ptr, src_step,
2531            dst->data.ptr, dst_step, size, param[0] ));
2532    }
2533    else if( func2 )
2534    {
2535        IPPI_CALL( func2( src->data.ptr, src_step,
2536            dst->data.ptr, dst_step, size, param[0], param[1] ));
2537    }
2538    else if( func3 )
2539    {
2540        IPPI_CALL( func3( src->data.ptr, src_step,
2541            dst->data.ptr, dst_step, size, param[0], param[1], param[2] ));
2542    }
2543    else
2544        CV_ERROR( CV_StsUnsupportedFormat, "The image format is not supported" );
2545
2546    __END__;
2547}
2548
2549/* End of file. */
2550
2551
2552