• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41 
42 #include "precomp.hpp"
43 #include "utils.hpp"
44 
45 #define  SCALE  14
46 #define  cR  (int)(0.299*(1 << SCALE) + 0.5)
47 #define  cG  (int)(0.587*(1 << SCALE) + 0.5)
48 #define  cB  ((1 << SCALE) - cR - cG)
49 
icvCvt_BGR2Gray_8u_C3C1R(const uchar * rgb,int rgb_step,uchar * gray,int gray_step,CvSize size,int _swap_rb)50 void icvCvt_BGR2Gray_8u_C3C1R( const uchar* rgb, int rgb_step,
51                                uchar* gray, int gray_step,
52                                CvSize size, int _swap_rb )
53 {
54     int i;
55     int swap_rb = _swap_rb ? 2 : 0;
56     for( ; size.height--; gray += gray_step )
57     {
58         for( i = 0; i < size.width; i++, rgb += 3 )
59         {
60             int t = descale( rgb[swap_rb]*cB + rgb[1]*cG + rgb[swap_rb^2]*cR, SCALE );
61             gray[i] = (uchar)t;
62         }
63 
64         rgb += rgb_step - size.width*3;
65     }
66 }
67 
68 
icvCvt_BGRA2Gray_16u_CnC1R(const ushort * rgb,int rgb_step,ushort * gray,int gray_step,CvSize size,int ncn,int _swap_rb)69 void icvCvt_BGRA2Gray_16u_CnC1R( const ushort* rgb, int rgb_step,
70                                 ushort* gray, int gray_step,
71                                 CvSize size, int ncn, int _swap_rb )
72 {
73     int i;
74     int swap_rb = _swap_rb ? 2 : 0;
75     for( ; size.height--; gray += gray_step )
76     {
77         for( i = 0; i < size.width; i++, rgb += ncn )
78         {
79             int t = descale( rgb[swap_rb]*cB + rgb[1]*cG + rgb[swap_rb^2]*cR, SCALE );
80             gray[i] = (ushort)t;
81         }
82 
83         rgb += rgb_step - size.width*ncn;
84     }
85 }
86 
87 
icvCvt_BGRA2Gray_8u_C4C1R(const uchar * rgba,int rgba_step,uchar * gray,int gray_step,CvSize size,int _swap_rb)88 void icvCvt_BGRA2Gray_8u_C4C1R( const uchar* rgba, int rgba_step,
89                                 uchar* gray, int gray_step,
90                                 CvSize size, int _swap_rb )
91 {
92     int i;
93     int swap_rb = _swap_rb ? 2 : 0;
94     for( ; size.height--; gray += gray_step )
95     {
96         for( i = 0; i < size.width; i++, rgba += 4 )
97         {
98             int t = descale( rgba[swap_rb]*cB + rgba[1]*cG + rgba[swap_rb^2]*cR, SCALE );
99             gray[i] = (uchar)t;
100         }
101 
102         rgba += rgba_step - size.width*4;
103     }
104 }
105 
106 
icvCvt_Gray2BGR_8u_C1C3R(const uchar * gray,int gray_step,uchar * bgr,int bgr_step,CvSize size)107 void icvCvt_Gray2BGR_8u_C1C3R( const uchar* gray, int gray_step,
108                                uchar* bgr, int bgr_step, CvSize size )
109 {
110     int i;
111     for( ; size.height--; gray += gray_step )
112     {
113         for( i = 0; i < size.width; i++, bgr += 3 )
114         {
115             bgr[0] = bgr[1] = bgr[2] = gray[i];
116         }
117         bgr += bgr_step - size.width*3;
118     }
119 }
120 
121 
icvCvt_Gray2BGR_16u_C1C3R(const ushort * gray,int gray_step,ushort * bgr,int bgr_step,CvSize size)122 void icvCvt_Gray2BGR_16u_C1C3R( const ushort* gray, int gray_step,
123                               ushort* bgr, int bgr_step, CvSize size )
124 {
125     int i;
126     for( ; size.height--; gray += gray_step/sizeof(gray[0]) )
127     {
128         for( i = 0; i < size.width; i++, bgr += 3 )
129         {
130             bgr[0] = bgr[1] = bgr[2] = gray[i];
131         }
132         bgr += bgr_step/sizeof(bgr[0]) - size.width*3;
133     }
134 }
135 
136 
icvCvt_BGRA2BGR_8u_C4C3R(const uchar * bgra,int bgra_step,uchar * bgr,int bgr_step,CvSize size,int _swap_rb)137 void icvCvt_BGRA2BGR_8u_C4C3R( const uchar* bgra, int bgra_step,
138                                uchar* bgr, int bgr_step,
139                                CvSize size, int _swap_rb )
140 {
141     int i;
142     int swap_rb = _swap_rb ? 2 : 0;
143     for( ; size.height--; )
144     {
145         for( i = 0; i < size.width; i++, bgr += 3, bgra += 4 )
146         {
147             uchar t0 = bgra[swap_rb], t1 = bgra[1];
148             bgr[0] = t0; bgr[1] = t1;
149             t0 = bgra[swap_rb^2]; bgr[2] = t0;
150         }
151         bgr += bgr_step - size.width*3;
152         bgra += bgra_step - size.width*4;
153     }
154 }
155 
156 
icvCvt_BGRA2BGR_16u_C4C3R(const ushort * bgra,int bgra_step,ushort * bgr,int bgr_step,CvSize size,int _swap_rb)157 void icvCvt_BGRA2BGR_16u_C4C3R( const ushort* bgra, int bgra_step,
158                               ushort* bgr, int bgr_step,
159                               CvSize size, int _swap_rb )
160 {
161     int i;
162     int swap_rb = _swap_rb ? 2 : 0;
163     for( ; size.height--; )
164     {
165         for( i = 0; i < size.width; i++, bgr += 3, bgra += 4 )
166         {
167             ushort t0 = bgra[swap_rb], t1 = bgra[1];
168             bgr[0] = t0; bgr[1] = t1;
169             t0 = bgra[swap_rb^2]; bgr[2] = t0;
170         }
171         bgr += bgr_step/sizeof(bgr[0]) - size.width*3;
172         bgra += bgra_step/sizeof(bgra[0]) - size.width*4;
173     }
174 }
175 
176 
icvCvt_BGRA2RGBA_8u_C4R(const uchar * bgra,int bgra_step,uchar * rgba,int rgba_step,CvSize size)177 void icvCvt_BGRA2RGBA_8u_C4R( const uchar* bgra, int bgra_step,
178                               uchar* rgba, int rgba_step, CvSize size )
179 {
180     int i;
181     for( ; size.height--; )
182     {
183         for( i = 0; i < size.width; i++, bgra += 4, rgba += 4 )
184         {
185             uchar t0 = bgra[0], t1 = bgra[1];
186             uchar t2 = bgra[2], t3 = bgra[3];
187             rgba[0] = t2; rgba[1] = t1;
188             rgba[2] = t0; rgba[3] = t3;
189         }
190         bgra += bgra_step - size.width*4;
191         rgba += rgba_step - size.width*4;
192     }
193 }
194 
icvCvt_BGRA2RGBA_16u_C4R(const ushort * bgra,int bgra_step,ushort * rgba,int rgba_step,CvSize size)195 void icvCvt_BGRA2RGBA_16u_C4R( const ushort* bgra, int bgra_step,
196                                ushort* rgba, int rgba_step, CvSize size )
197 {
198  int i;
199  for( ; size.height--; )
200  {
201      for( i = 0; i < size.width; i++, bgra += 4, rgba += 4 )
202      {
203          ushort t0 = bgra[0], t1 = bgra[1];
204          ushort t2 = bgra[2], t3 = bgra[3];
205 
206          rgba[0] = t2; rgba[1] = t1;
207          rgba[2] = t0; rgba[3] = t3;
208      }
209      bgra += bgra_step/sizeof(bgra[0]) - size.width*4;
210      rgba += rgba_step/sizeof(rgba[0]) - size.width*4;
211  }
212 }
213 
214 
icvCvt_BGR2RGB_8u_C3R(const uchar * bgr,int bgr_step,uchar * rgb,int rgb_step,CvSize size)215 void icvCvt_BGR2RGB_8u_C3R( const uchar* bgr, int bgr_step,
216                             uchar* rgb, int rgb_step, CvSize size )
217 {
218     int i;
219     for( ; size.height--; )
220     {
221         for( i = 0; i < size.width; i++, bgr += 3, rgb += 3 )
222         {
223             uchar t0 = bgr[0], t1 = bgr[1], t2 = bgr[2];
224             rgb[2] = t0; rgb[1] = t1; rgb[0] = t2;
225         }
226         bgr += bgr_step - size.width*3;
227         rgb += rgb_step - size.width*3;
228     }
229 }
230 
231 
icvCvt_BGR2RGB_16u_C3R(const ushort * bgr,int bgr_step,ushort * rgb,int rgb_step,CvSize size)232 void icvCvt_BGR2RGB_16u_C3R( const ushort* bgr, int bgr_step,
233                              ushort* rgb, int rgb_step, CvSize size )
234 {
235     int i;
236     for( ; size.height--; )
237     {
238         for( i = 0; i < size.width; i++, bgr += 3, rgb += 3 )
239         {
240             ushort t0 = bgr[0], t1 = bgr[1], t2 = bgr[2];
241             rgb[2] = t0; rgb[1] = t1; rgb[0] = t2;
242         }
243         bgr += bgr_step - size.width*3;
244         rgb += rgb_step - size.width*3;
245     }
246 }
247 
248 
249 typedef unsigned short ushort;
250 
icvCvt_BGR5552Gray_8u_C2C1R(const uchar * bgr555,int bgr555_step,uchar * gray,int gray_step,CvSize size)251 void icvCvt_BGR5552Gray_8u_C2C1R( const uchar* bgr555, int bgr555_step,
252                                   uchar* gray, int gray_step, CvSize size )
253 {
254     int i;
255     for( ; size.height--; gray += gray_step, bgr555 += bgr555_step )
256     {
257         for( i = 0; i < size.width; i++ )
258         {
259             int t = descale( ((((ushort*)bgr555)[i] << 3) & 0xf8)*cB +
260                              ((((ushort*)bgr555)[i] >> 2) & 0xf8)*cG +
261                              ((((ushort*)bgr555)[i] >> 7) & 0xf8)*cR, SCALE );
262             gray[i] = (uchar)t;
263         }
264     }
265 }
266 
267 
icvCvt_BGR5652Gray_8u_C2C1R(const uchar * bgr565,int bgr565_step,uchar * gray,int gray_step,CvSize size)268 void icvCvt_BGR5652Gray_8u_C2C1R( const uchar* bgr565, int bgr565_step,
269                                   uchar* gray, int gray_step, CvSize size )
270 {
271     int i;
272     for( ; size.height--; gray += gray_step, bgr565 += bgr565_step )
273     {
274         for( i = 0; i < size.width; i++ )
275         {
276             int t = descale( ((((ushort*)bgr565)[i] << 3) & 0xf8)*cB +
277                              ((((ushort*)bgr565)[i] >> 3) & 0xfc)*cG +
278                              ((((ushort*)bgr565)[i] >> 8) & 0xf8)*cR, SCALE );
279             gray[i] = (uchar)t;
280         }
281     }
282 }
283 
284 
icvCvt_BGR5552BGR_8u_C2C3R(const uchar * bgr555,int bgr555_step,uchar * bgr,int bgr_step,CvSize size)285 void icvCvt_BGR5552BGR_8u_C2C3R( const uchar* bgr555, int bgr555_step,
286                                  uchar* bgr, int bgr_step, CvSize size )
287 {
288     int i;
289     for( ; size.height--; bgr555 += bgr555_step )
290     {
291         for( i = 0; i < size.width; i++, bgr += 3 )
292         {
293             int t0 = (((ushort*)bgr555)[i] << 3) & 0xf8;
294             int t1 = (((ushort*)bgr555)[i] >> 2) & 0xf8;
295             int t2 = (((ushort*)bgr555)[i] >> 7) & 0xf8;
296             bgr[0] = (uchar)t0; bgr[1] = (uchar)t1; bgr[2] = (uchar)t2;
297         }
298         bgr += bgr_step - size.width*3;
299     }
300 }
301 
302 
icvCvt_BGR5652BGR_8u_C2C3R(const uchar * bgr565,int bgr565_step,uchar * bgr,int bgr_step,CvSize size)303 void icvCvt_BGR5652BGR_8u_C2C3R( const uchar* bgr565, int bgr565_step,
304                                  uchar* bgr, int bgr_step, CvSize size )
305 {
306     int i;
307     for( ; size.height--; bgr565 += bgr565_step )
308     {
309         for( i = 0; i < size.width; i++, bgr += 3 )
310         {
311             int t0 = (((ushort*)bgr565)[i] << 3) & 0xf8;
312             int t1 = (((ushort*)bgr565)[i] >> 3) & 0xfc;
313             int t2 = (((ushort*)bgr565)[i] >> 8) & 0xf8;
314             bgr[0] = (uchar)t0; bgr[1] = (uchar)t1; bgr[2] = (uchar)t2;
315         }
316         bgr += bgr_step - size.width*3;
317     }
318 }
319 
320 
icvCvt_CMYK2BGR_8u_C4C3R(const uchar * cmyk,int cmyk_step,uchar * bgr,int bgr_step,CvSize size)321 void icvCvt_CMYK2BGR_8u_C4C3R( const uchar* cmyk, int cmyk_step,
322                                uchar* bgr, int bgr_step, CvSize size )
323 {
324     int i;
325     for( ; size.height--; )
326     {
327         for( i = 0; i < size.width; i++, bgr += 3, cmyk += 4 )
328         {
329             int c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3];
330             c = k - ((255 - c)*k>>8);
331             m = k - ((255 - m)*k>>8);
332             y = k - ((255 - y)*k>>8);
333             bgr[2] = (uchar)c; bgr[1] = (uchar)m; bgr[0] = (uchar)y;
334         }
335         bgr += bgr_step - size.width*3;
336         cmyk += cmyk_step - size.width*4;
337     }
338 }
339 
340 
icvCvt_CMYK2Gray_8u_C4C1R(const uchar * cmyk,int cmyk_step,uchar * gray,int gray_step,CvSize size)341 void icvCvt_CMYK2Gray_8u_C4C1R( const uchar* cmyk, int cmyk_step,
342                                 uchar* gray, int gray_step, CvSize size )
343 {
344     int i;
345     for( ; size.height--; )
346     {
347         for( i = 0; i < size.width; i++, cmyk += 4 )
348         {
349             int c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3];
350             c = k - ((255 - c)*k>>8);
351             m = k - ((255 - m)*k>>8);
352             y = k - ((255 - y)*k>>8);
353             int t = descale( y*cB + m*cG + c*cR, SCALE );
354             gray[i] = (uchar)t;
355         }
356         gray += gray_step;
357         cmyk += cmyk_step - size.width*4;
358     }
359 }
360 
361 
CvtPaletteToGray(const PaletteEntry * palette,uchar * grayPalette,int entries)362 void CvtPaletteToGray( const PaletteEntry* palette, uchar* grayPalette, int entries )
363 {
364     int i;
365     for( i = 0; i < entries; i++ )
366     {
367         icvCvt_BGR2Gray_8u_C3C1R( (uchar*)(palette + i), 0, grayPalette + i, 0, cvSize(1,1) );
368     }
369 }
370 
371 
FillGrayPalette(PaletteEntry * palette,int bpp,bool negative)372 void  FillGrayPalette( PaletteEntry* palette, int bpp, bool negative )
373 {
374     int i, length = 1 << bpp;
375     int xor_mask = negative ? 255 : 0;
376 
377     for( i = 0; i < length; i++ )
378     {
379         int val = (i * 255/(length - 1)) ^ xor_mask;
380         palette[i].b = palette[i].g = palette[i].r = (uchar)val;
381         palette[i].a = 0;
382     }
383 }
384 
385 
IsColorPalette(PaletteEntry * palette,int bpp)386 bool  IsColorPalette( PaletteEntry* palette, int bpp )
387 {
388     int i, length = 1 << bpp;
389 
390     for( i = 0; i < length; i++ )
391     {
392         if( palette[i].b != palette[i].g ||
393             palette[i].b != palette[i].r )
394             return true;
395     }
396 
397     return false;
398 }
399 
400 
FillUniColor(uchar * data,uchar * & line_end,int step,int width3,int & y,int height,int count3,PaletteEntry clr)401 uchar* FillUniColor( uchar* data, uchar*& line_end,
402                      int step, int width3,
403                      int& y, int height,
404                      int count3, PaletteEntry clr )
405 {
406     do
407     {
408         uchar* end = data + count3;
409 
410         if( end > line_end )
411             end = line_end;
412 
413         count3 -= (int)(end - data);
414 
415         for( ; data < end; data += 3 )
416         {
417             WRITE_PIX( data, clr );
418         }
419 
420         if( data >= line_end )
421         {
422             line_end += step;
423             data = line_end - width3;
424             if( ++y >= height  ) break;
425         }
426     }
427     while( count3 > 0 );
428 
429     return data;
430 }
431 
432 
FillUniGray(uchar * data,uchar * & line_end,int step,int width,int & y,int height,int count,uchar clr)433 uchar* FillUniGray( uchar* data, uchar*& line_end,
434                     int step, int width,
435                     int& y, int height,
436                     int count, uchar clr )
437 {
438     do
439     {
440         uchar* end = data + count;
441 
442         if( end > line_end )
443             end = line_end;
444 
445         count -= (int)(end - data);
446 
447         for( ; data < end; data++ )
448         {
449             *data = clr;
450         }
451 
452         if( data >= line_end )
453         {
454             line_end += step;
455             data = line_end - width;
456             if( ++y >= height  ) break;
457         }
458     }
459     while( count > 0 );
460 
461     return data;
462 }
463 
464 
FillColorRow8(uchar * data,uchar * indices,int len,PaletteEntry * palette)465 uchar* FillColorRow8( uchar* data, uchar* indices, int len, PaletteEntry* palette )
466 {
467     uchar* end = data + len*3;
468     while( (data += 3) < end )
469     {
470         *((PaletteEntry*)(data-3)) = palette[*indices++];
471     }
472     PaletteEntry clr = palette[indices[0]];
473     WRITE_PIX( data - 3, clr );
474     return data;
475 }
476 
477 
FillGrayRow8(uchar * data,uchar * indices,int len,uchar * palette)478 uchar* FillGrayRow8( uchar* data, uchar* indices, int len, uchar* palette )
479 {
480     int i;
481     for( i = 0; i < len; i++ )
482     {
483         data[i] = palette[indices[i]];
484     }
485     return data + len;
486 }
487 
488 
FillColorRow4(uchar * data,uchar * indices,int len,PaletteEntry * palette)489 uchar* FillColorRow4( uchar* data, uchar* indices, int len, PaletteEntry* palette )
490 {
491     uchar* end = data + len*3;
492 
493     while( (data += 6) < end )
494     {
495         int idx = *indices++;
496         *((PaletteEntry*)(data-6)) = palette[idx >> 4];
497         *((PaletteEntry*)(data-3)) = palette[idx & 15];
498     }
499 
500     int idx = indices[0];
501     PaletteEntry clr = palette[idx >> 4];
502     WRITE_PIX( data - 6, clr );
503 
504     if( data == end )
505     {
506         clr = palette[idx & 15];
507         WRITE_PIX( data - 3, clr );
508     }
509     return end;
510 }
511 
512 
FillGrayRow4(uchar * data,uchar * indices,int len,uchar * palette)513 uchar* FillGrayRow4( uchar* data, uchar* indices, int len, uchar* palette )
514 {
515     uchar* end = data + len;
516     while( (data += 2) < end )
517     {
518         int idx = *indices++;
519         data[-2] = palette[idx >> 4];
520         data[-1] = palette[idx & 15];
521     }
522 
523     int idx = indices[0];
524     uchar clr = palette[idx >> 4];
525     data[-2] = clr;
526 
527     if( data == end )
528     {
529         clr = palette[idx & 15];
530         data[-1] = clr;
531     }
532     return end;
533 }
534 
535 
FillColorRow1(uchar * data,uchar * indices,int len,PaletteEntry * palette)536 uchar* FillColorRow1( uchar* data, uchar* indices, int len, PaletteEntry* palette )
537 {
538     uchar* end = data + len*3;
539 
540     while( (data += 24) < end )
541     {
542         int idx = *indices++;
543         *((PaletteEntry*)(data - 24)) = palette[(idx & 128) != 0];
544         *((PaletteEntry*)(data - 21)) = palette[(idx & 64) != 0];
545         *((PaletteEntry*)(data - 18)) = palette[(idx & 32) != 0];
546         *((PaletteEntry*)(data - 15)) = palette[(idx & 16) != 0];
547         *((PaletteEntry*)(data - 12)) = palette[(idx & 8) != 0];
548         *((PaletteEntry*)(data - 9)) = palette[(idx & 4) != 0];
549         *((PaletteEntry*)(data - 6)) = palette[(idx & 2) != 0];
550         *((PaletteEntry*)(data - 3)) = palette[(idx & 1) != 0];
551     }
552 
553     int idx = indices[0] << 24;
554     for( data -= 24; data < end; data += 3, idx += idx )
555     {
556         PaletteEntry clr = palette[idx < 0];
557         WRITE_PIX( data, clr );
558     }
559 
560     return data;
561 }
562 
563 
FillGrayRow1(uchar * data,uchar * indices,int len,uchar * palette)564 uchar* FillGrayRow1( uchar* data, uchar* indices, int len, uchar* palette )
565 {
566     uchar* end = data + len;
567 
568     while( (data += 8) < end )
569     {
570         int idx = *indices++;
571         *((uchar*)(data - 8)) = palette[(idx & 128) != 0];
572         *((uchar*)(data - 7)) = palette[(idx & 64) != 0];
573         *((uchar*)(data - 6)) = palette[(idx & 32) != 0];
574         *((uchar*)(data - 5)) = palette[(idx & 16) != 0];
575         *((uchar*)(data - 4)) = palette[(idx & 8) != 0];
576         *((uchar*)(data - 3)) = palette[(idx & 4) != 0];
577         *((uchar*)(data - 2)) = palette[(idx & 2) != 0];
578         *((uchar*)(data - 1)) = palette[(idx & 1) != 0];
579     }
580 
581     int idx = indices[0] << 24;
582     for( data -= 8; data < end; data++, idx += idx )
583     {
584         data[0] = palette[idx < 0];
585     }
586 
587     return data;
588 }
589 
590 
591 CV_IMPL void
cvConvertImage(const CvArr * srcarr,CvArr * dstarr,int flags)592 cvConvertImage( const CvArr* srcarr, CvArr* dstarr, int flags )
593 {
594     CvMat* temp = 0;
595 
596     CV_FUNCNAME( "cvConvertImage" );
597 
598     __BEGIN__;
599 
600     CvMat srcstub, *src;
601     CvMat dststub, *dst;
602     int src_cn, dst_cn, swap_rb = flags & CV_CVTIMG_SWAP_RB;
603 
604     CV_CALL( src = cvGetMat( srcarr, &srcstub ));
605     CV_CALL( dst = cvGetMat( dstarr, &dststub ));
606 
607     src_cn = CV_MAT_CN( src->type );
608     dst_cn = CV_MAT_CN( dst->type );
609 
610     if( src_cn != 1 && src_cn != 3 && src_cn != 4 )
611         CV_ERROR( CV_BadNumChannels, "Source image must have 1, 3 or 4 channels" );
612 
613     if( CV_MAT_DEPTH( dst->type ) != CV_8U )
614         CV_ERROR( CV_BadDepth, "Destination image must be 8u" );
615 
616     if( CV_MAT_CN(dst->type) != 1 && CV_MAT_CN(dst->type) != 3 )
617         CV_ERROR( CV_BadNumChannels, "Destination image must have 1 or 3 channels" );
618 
619     if( !CV_ARE_DEPTHS_EQ( src, dst ))
620     {
621         int src_depth = CV_MAT_DEPTH(src->type);
622         double scale = src_depth <= CV_8S ? 1 : src_depth <= CV_32S ? 1./256 : 255;
623         double shift = src_depth == CV_8S || src_depth == CV_16S ? 128 : 0;
624 
625         if( !CV_ARE_CNS_EQ( src, dst ))
626         {
627             temp = cvCreateMat( src->height, src->width,
628                 (src->type & CV_MAT_CN_MASK)|(dst->type & CV_MAT_DEPTH_MASK));
629             cvConvertScale( src, temp, scale, shift );
630             src = temp;
631         }
632         else
633         {
634             cvConvertScale( src, dst, scale, shift );
635             src = dst;
636         }
637     }
638 
639     if( src_cn != dst_cn || (src_cn == 3 && swap_rb) )
640     {
641         uchar *s = src->data.ptr, *d = dst->data.ptr;
642         int s_step = src->step, d_step = dst->step;
643         int code = src_cn*10 + dst_cn;
644         CvSize size(src->cols, src->rows);
645 
646         if( CV_IS_MAT_CONT(src->type & dst->type) )
647         {
648             size.width *= size.height;
649             size.height = 1;
650             s_step = d_step = /*CV_STUB_STEP*/ (1 << 30);
651         }
652 
653         switch( code )
654         {
655         case 13:
656             icvCvt_Gray2BGR_8u_C1C3R( s, s_step, d, d_step, size );
657             break;
658         case 31:
659             icvCvt_BGR2Gray_8u_C3C1R( s, s_step, d, d_step, size, swap_rb );
660             break;
661         case 33:
662             assert( swap_rb );
663             icvCvt_RGB2BGR_8u_C3R( s, s_step, d, d_step, size );
664             break;
665         case 41:
666             icvCvt_BGRA2Gray_8u_C4C1R( s, s_step, d, d_step, size, swap_rb );
667             break;
668         case 43:
669             icvCvt_BGRA2BGR_8u_C4C3R( s, s_step, d, d_step, size, swap_rb );
670             break;
671         default:
672             CV_ERROR( CV_StsUnsupportedFormat, "Unsupported combination of input/output formats" );
673         }
674         src = dst;
675     }
676 
677     if( flags & CV_CVTIMG_FLIP )
678     {
679         CV_CALL( cvFlip( src, dst, 0 ));
680     }
681     else if( src != dst )
682     {
683         CV_CALL( cvCopy( src, dst ));
684     }
685 
686     __END__;
687 
688     cvReleaseMat( &temp );
689 }
690