Update the changelog
[opencv] / cv / src / cvcolor.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //                        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
92 typedef CvStatus (CV_STDCALL * CvColorCvtFunc0)(
93     const void* src, int srcstep, void* dst, int dststep, CvSize size );
94
95 typedef CvStatus (CV_STDCALL * CvColorCvtFunc1)(
96     const void* src, int srcstep, void* dst, int dststep,
97     CvSize size, int param0 );
98
99 typedef CvStatus (CV_STDCALL * CvColorCvtFunc2)(
100     const void* src, int srcstep, void* dst, int dststep,
101     CvSize size, int param0, int param1 );
102
103 typedef 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 )                             \
112 static CvStatus CV_STDCALL                                              \
113 icvBGRx2BGR_##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 )                             \
140 static CvStatus CV_STDCALL                                              \
141 icvBGR2BGRx_##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 )                            \
169 static CvStatus CV_STDCALL                                              \
170 icvBGRA2RGBA_##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
195 CV_IMPL_BGRX2BGR( 8u, uchar )
196 CV_IMPL_BGRX2BGR( 16u, ushort )
197 CV_IMPL_BGRX2BGR( 32f, int )
198 CV_IMPL_BGR2BGRX( 8u, uchar )
199 CV_IMPL_BGR2BGRX( 16u, ushort )
200 CV_IMPL_BGR2BGRX( 32f, int )
201 CV_IMPL_BGRA2RGBA( 8u, uchar )
202 CV_IMPL_BGRA2RGBA( 16u, ushort )
203 CV_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
210 static CvStatus CV_STDCALL
211 icvBGR5x52BGRx_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
248 static CvStatus CV_STDCALL
249 icvBGRx2BGR5x5_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
280 icvRGB2XYZ_8u_C3R_t  icvRGB2XYZ_8u_C3R_p = 0;
281 icvRGB2XYZ_16u_C3R_t icvRGB2XYZ_16u_C3R_p = 0;
282 icvRGB2XYZ_32f_C3R_t icvRGB2XYZ_32f_C3R_p = 0;
283 icvXYZ2RGB_8u_C3R_t  icvXYZ2RGB_8u_C3R_p = 0;
284 icvXYZ2RGB_16u_C3R_t icvXYZ2RGB_16u_C3R_p = 0;
285 icvXYZ2RGB_32f_C3R_t icvXYZ2RGB_32f_C3R_p = 0;
286
287 icvRGB2HSV_8u_C3R_t  icvRGB2HSV_8u_C3R_p = 0;
288 icvHSV2RGB_8u_C3R_t  icvHSV2RGB_8u_C3R_p = 0;
289
290 icvBGR2Lab_8u_C3R_t  icvBGR2Lab_8u_C3R_p = 0;
291 icvLab2BGR_8u_C3R_t  icvLab2BGR_8u_C3R_p = 0;
292
293 icvRGB2HLS_8u_C3R_t  icvRGB2HLS_8u_C3R_p = 0;
294 icvRGB2HLS_32f_C3R_t icvRGB2HLS_32f_C3R_p = 0;
295 icvHLS2RGB_8u_C3R_t  icvHLS2RGB_8u_C3R_p = 0;
296 icvHLS2RGB_32f_C3R_t icvHLS2RGB_32f_C3R_p = 0;
297
298 icvRGB2Luv_8u_C3R_t  icvRGB2Luv_8u_C3R_p = 0;
299 icvLuv2RGB_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 )                         \
308 static CvStatus CV_STDCALL                                              \
309 icvBGRx2ABC_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
356 static CvStatus CV_STDCALL
357 icvBGRx2ABC_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 )
406 CV_IMPL_BGRx2ABC_IPP( 16u, ushort )
407 CV_IMPL_BGRx2ABC_IPP( 32f, float )
408
409 #define CV_IMPL_ABC2BGRx_IPP( flavor, arrtype )                         \
410 static CvStatus CV_STDCALL                                              \
411 icvABC2BGRx_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
459 CV_IMPL_ABC2BGRx_IPP( 8u, uchar )
460 CV_IMPL_ABC2BGRx_IPP( 16u, ushort )
461 CV_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 )                    \
485 static CvStatus CV_STDCALL                                      \
486 icvGray2BGRx_##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
512 CV_IMPL_GRAY2BGRX( 8u, uchar )
513 CV_IMPL_GRAY2BGRX( 16u, ushort )
514 CV_IMPL_GRAY2BGRX( 32f, float )
515
516
517 static CvStatus CV_STDCALL
518 icvBGR5x52Gray_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
549 static CvStatus CV_STDCALL
550 icvGray2BGR5x5_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
577 static CvStatus CV_STDCALL
578 icvBGRx2Gray_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
626 static CvStatus CV_STDCALL
627 icvBGRx2Gray_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
649 static CvStatus CV_STDCALL
650 icvBGRx2Gray_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 )   \
703 static CvStatus CV_STDCALL                                                  \
704 icvBGRx2YCrCb_##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
731 CV_IMPL_BGRx2YCrCb( 8u, uchar, int, yuv_descale, CV_CAST_8U,
732                     yuvYb, yuvYg, yuvYr, yuvCr, yuvCb, 128 )
733
734 CV_IMPL_BGRx2YCrCb( 16u, ushort, int, yuv_descale, CV_CAST_16U,
735                     yuvYb, yuvYg, yuvYr, yuvCr, yuvCb, 32768 )
736
737 CV_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)\
743 static CvStatus CV_STDCALL                                                  \
744 icvYCrCb2BGRx_##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
778 CV_IMPL_YCrCb2BGRx( 8u, uchar, int, yuv_prescale, yuv_descale, CV_CAST_8U,
779                     yuvBCb, yuvGCr, yuvGCb, yuvRCr, 128 )
780
781 CV_IMPL_YCrCb2BGRx( 16u, ushort, int, yuv_prescale, yuv_descale, CV_CAST_16U,
782                     yuvBCb, yuvGCr, yuvGCb, yuvRCr, 32768 )
783
784 CV_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 )                 \
845 static CvStatus CV_STDCALL                                                  \
846 icvBGRx2XYZ_##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
896 CV_IMPL_BGRx2XYZ( 8u, uchar, int, xyz_descale, CV_CAST_8U, _32s )
897 CV_IMPL_BGRx2XYZ( 16u, ushort, int, xyz_descale, CV_CAST_16U, _32s )
898 CV_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 )                              \
903 static CvStatus CV_STDCALL                                                  \
904 icvXYZ2BGRx_##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
956 CV_IMPL_XYZ2BGRx( 8u, uchar, int, xyz_descale, CV_CAST_8U, _32s )
957 CV_IMPL_XYZ2BGRx( 16u, ushort, int, xyz_descale, CV_CAST_16U, _32s )
958 CV_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.
967 static CvStatus CV_STDCALL
968 icvABC2BGRx_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.
1039 static CvStatus CV_STDCALL
1040 icvBGRx2ABC_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
1109 static 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
1130 static 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
1151 static CvStatus CV_STDCALL
1152 icvBGRx2HSV_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
1253 static CvStatus CV_STDCALL
1254 icvBGRx2HSV_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
1301 static CvStatus CV_STDCALL
1302 icvHSV2BGRx_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
1356 static CvStatus CV_STDCALL
1357 icvHSV2BGRx_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
1419 static CvStatus CV_STDCALL
1420 icvBGRx2HLS_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
1497 static CvStatus CV_STDCALL
1498 icvHLS2BGRx_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
1599 static CvStatus CV_STDCALL
1600 icvBGRx2HLS_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
1634 static CvStatus CV_STDCALL
1635 icvHLS2BGRx_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)) */
1753 static 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
1789 static CvStatus CV_STDCALL
1790 icvBGRx2Lab_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
1857 static CvStatus CV_STDCALL
1858 icvBGRx2Lab_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
1913 static CvStatus CV_STDCALL
1914 icvLab2BGRx_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
1954 static CvStatus CV_STDCALL
1955 icvLab2BGRx_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
1980 static CvStatus CV_STDCALL
1981 icvBGRx2Luv_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
2034 static CvStatus CV_STDCALL
2035 icvLuv2BGRx_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
2089 static CvStatus CV_STDCALL
2090 icvBGRx2Luv_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
2109 static CvStatus CV_STDCALL
2110 icvLuv2BGRx_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
2131 static CvStatus CV_STDCALL
2132 icvBayer2BGR_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
2233 CV_IMPL void
2234 cvCvtColor( 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