Update to 2.0.0 tree from current Fremantle build
[opencv] / src / highgui / utils.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        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 "_highgui.h"
43 #include "utils.h"
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
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
69 void icvCvt_BGR2Gray_16u_C3C1R( const ushort* rgb, int rgb_step,
70                                 ushort* gray, int gray_step,
71                                 CvSize size, 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 += 3 )
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*3;
84     }
85 }
86
87
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
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
122 void icvCvt_BGRA2BGR_8u_C4C3R( const uchar* bgra, int bgra_step,
123                                uchar* bgr, int bgr_step,
124                                CvSize size, int _swap_rb )
125 {
126     int i;
127     int swap_rb = _swap_rb ? 2 : 0;
128     for( ; size.height--; )
129     {
130         for( i = 0; i < size.width; i++, bgr += 3, bgra += 4 )
131         {
132             uchar t0 = bgra[swap_rb], t1 = bgra[1];
133             bgr[0] = t0; bgr[1] = t1;
134             t0 = bgra[swap_rb^2]; bgr[2] = t0;
135         }
136         bgr += bgr_step - size.width*3;
137         bgra += bgra_step - size.width*4;
138     }
139 }
140
141
142 void icvCvt_BGRA2RGBA_8u_C4R( const uchar* bgra, int bgra_step,
143                               uchar* rgba, int rgba_step, CvSize size )
144 {
145     int i;
146     for( ; size.height--; )
147     {
148         for( i = 0; i < size.width; i++, bgra += 4, rgba += 4 )
149         {
150             uchar t0 = bgra[0], t1 = bgra[1];
151             uchar t2 = bgra[2], t3 = bgra[3];
152             rgba[0] = t2; rgba[1] = t1;
153             rgba[2] = t0; rgba[3] = t3;
154         }
155         bgra += bgra_step - size.width*4;
156         rgba += rgba_step - size.width*4;
157     }
158 }
159
160
161 void icvCvt_BGR2RGB_8u_C3R( const uchar* bgr, int bgr_step,
162                             uchar* rgb, int rgb_step, CvSize size )
163 {
164     int i;
165     for( ; size.height--; )
166     {
167         for( i = 0; i < size.width; i++, bgr += 3, rgb += 3 )
168         {
169             uchar t0 = bgr[0], t1 = bgr[1], t2 = bgr[2];
170             rgb[2] = t0; rgb[1] = t1; rgb[0] = t2;
171         }
172         bgr += bgr_step - size.width*3;
173         rgb += rgb_step - size.width*3;
174     }
175 }
176
177
178 void icvCvt_BGR2RGB_16u_C3R( const ushort* bgr, int bgr_step,
179                              ushort* rgb, int rgb_step, CvSize size )
180 {
181     int i;
182     for( ; size.height--; )
183     {
184         for( i = 0; i < size.width; i++, bgr += 3, rgb += 3 )
185         {
186             ushort t0 = bgr[0], t1 = bgr[1], t2 = bgr[2];
187             rgb[2] = t0; rgb[1] = t1; rgb[0] = t2;
188         }
189         bgr += bgr_step - size.width*3;
190         rgb += rgb_step - size.width*3;
191     }
192 }
193
194
195 typedef unsigned short ushort;
196
197 void icvCvt_BGR5552Gray_8u_C2C1R( const uchar* bgr555, int bgr555_step,
198                                   uchar* gray, int gray_step, CvSize size )
199 {
200     int i;
201     for( ; size.height--; gray += gray_step, bgr555 += bgr555_step )
202     {
203         for( i = 0; i < size.width; i++ )
204         {
205             int t = descale( ((((ushort*)bgr555)[i] << 3) & 0xf8)*cB +
206                              ((((ushort*)bgr555)[i] >> 2) & 0xf8)*cG +
207                              ((((ushort*)bgr555)[i] >> 7) & 0xf8)*cR, SCALE );
208             gray[i] = (uchar)t;
209         }
210     }
211 }
212
213
214 void icvCvt_BGR5652Gray_8u_C2C1R( const uchar* bgr565, int bgr565_step,
215                                   uchar* gray, int gray_step, CvSize size )
216 {
217     int i;
218     for( ; size.height--; gray += gray_step, bgr565 += bgr565_step )
219     {
220         for( i = 0; i < size.width; i++ )
221         {
222             int t = descale( ((((ushort*)bgr565)[i] << 3) & 0xf8)*cB +
223                              ((((ushort*)bgr565)[i] >> 3) & 0xfc)*cG +
224                              ((((ushort*)bgr565)[i] >> 8) & 0xf8)*cR, SCALE );
225             gray[i] = (uchar)t;
226         }
227     }
228 }
229
230
231 void icvCvt_BGR5552BGR_8u_C2C3R( const uchar* bgr555, int bgr555_step,
232                                  uchar* bgr, int bgr_step, CvSize size )
233 {
234     int i;
235     for( ; size.height--; bgr555 += bgr555_step )
236     {
237         for( i = 0; i < size.width; i++, bgr += 3 )
238         {
239             int t0 = (((ushort*)bgr555)[i] << 3) & 0xf8;
240             int t1 = (((ushort*)bgr555)[i] >> 2) & 0xf8;
241             int t2 = (((ushort*)bgr555)[i] >> 7) & 0xf8;
242             bgr[0] = (uchar)t0; bgr[1] = (uchar)t1; bgr[2] = (uchar)t2;
243         }
244         bgr += bgr_step - size.width*3;
245     }
246 }
247
248
249 void icvCvt_BGR5652BGR_8u_C2C3R( const uchar* bgr565, int bgr565_step,
250                                  uchar* bgr, int bgr_step, CvSize size )
251 {
252     int i;
253     for( ; size.height--; bgr565 += bgr565_step )
254     {
255         for( i = 0; i < size.width; i++, bgr += 3 )
256         {
257             int t0 = (((ushort*)bgr565)[i] << 3) & 0xf8;
258             int t1 = (((ushort*)bgr565)[i] >> 3) & 0xfc;
259             int t2 = (((ushort*)bgr565)[i] >> 8) & 0xf8;
260             bgr[0] = (uchar)t0; bgr[1] = (uchar)t1; bgr[2] = (uchar)t2;
261         }
262         bgr += bgr_step - size.width*3;
263     }
264 }
265
266
267 void icvCvt_CMYK2BGR_8u_C4C3R( const uchar* cmyk, int cmyk_step,
268                                uchar* bgr, int bgr_step, CvSize size )
269 {
270     int i;
271     for( ; size.height--; )
272     {
273         for( i = 0; i < size.width; i++, bgr += 3, cmyk += 4 )
274         {
275             int c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3];
276             c = k - ((255 - c)*k>>8);
277             m = k - ((255 - m)*k>>8);
278             y = k - ((255 - y)*k>>8);
279             bgr[2] = (uchar)c; bgr[1] = (uchar)m; bgr[0] = (uchar)y;
280         }
281         bgr += bgr_step - size.width*3;
282         cmyk += cmyk_step - size.width*4;
283     }
284 }
285
286
287 void icvCvt_CMYK2Gray_8u_C4C1R( const uchar* cmyk, int cmyk_step,
288                                 uchar* gray, int gray_step, CvSize size )
289 {
290     int i;
291     for( ; size.height--; )
292     {
293         for( i = 0; i < size.width; i++, cmyk += 4 )
294         {
295             int c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3];
296             c = k - ((255 - c)*k>>8);
297             m = k - ((255 - m)*k>>8);
298             y = k - ((255 - y)*k>>8);
299             int t = descale( y*cB + m*cG + c*cR, SCALE );
300             gray[i] = (uchar)t;
301         }
302         gray += gray_step;
303         cmyk += cmyk_step - size.width*4;
304     }
305 }
306
307
308 void CvtPaletteToGray( const PaletteEntry* palette, uchar* grayPalette, int entries )
309 {
310     int i;
311     for( i = 0; i < entries; i++ )
312     {
313         icvCvt_BGR2Gray_8u_C3C1R( (uchar*)(palette + i), 0, grayPalette + i, 0, cvSize(1,1) );
314     }
315 }
316
317
318 void  FillGrayPalette( PaletteEntry* palette, int bpp, bool negative )
319 {
320     int i, length = 1 << bpp;
321     int xor_mask = negative ? 255 : 0;
322
323     for( i = 0; i < length; i++ )
324     {
325         int val = (i * 255/(length - 1)) ^ xor_mask;
326         palette[i].b = palette[i].g = palette[i].r = (uchar)val;
327         palette[i].a = 0;
328     }
329 }
330
331
332 bool  IsColorPalette( PaletteEntry* palette, int bpp )
333 {
334     int i, length = 1 << bpp;
335
336     for( i = 0; i < length; i++ )
337     {
338         if( palette[i].b != palette[i].g ||
339             palette[i].b != palette[i].r )
340             return true;
341     }
342
343     return false;
344 }
345
346
347 uchar* FillUniColor( uchar* data, uchar*& line_end,
348                      int step, int width3,
349                      int& y, int height,
350                      int count3, PaletteEntry clr )
351 {
352     do
353     {
354         uchar* end = data + count3;
355
356         if( end > line_end )
357             end = line_end;
358
359         count3 -= (int)(end - data);
360
361         for( ; data < end; data += 3 )
362         {
363             WRITE_PIX( data, clr );
364         }
365
366         if( data >= line_end )
367         {
368             line_end += step;
369             data = line_end - width3;
370             if( ++y >= height  ) break;
371         }
372     }
373     while( count3 > 0 );
374
375     return data;
376 }
377
378
379 uchar* FillUniGray( uchar* data, uchar*& line_end,
380                     int step, int width,
381                     int& y, int height,
382                     int count, uchar clr )
383 {
384     do
385     {
386         uchar* end = data + count;
387
388         if( end > line_end )
389             end = line_end;
390
391         count -= (int)(end - data);
392
393         for( ; data < end; data++ )
394         {
395             *data = clr;
396         }
397
398         if( data >= line_end )
399         {
400             line_end += step;
401             data = line_end - width;
402             if( ++y >= height  ) break;
403         }
404     }
405     while( count > 0 );
406
407     return data;
408 }
409
410
411 uchar* FillColorRow8( uchar* data, uchar* indices, int len, PaletteEntry* palette )
412 {
413     uchar* end = data + len*3;
414     while( (data += 3) < end )
415     {
416         *((PaletteEntry*)(data-3)) = palette[*indices++];
417     }
418     PaletteEntry clr = palette[indices[0]];
419     WRITE_PIX( data - 3, clr );
420     return data;
421 }
422
423
424 uchar* FillGrayRow8( uchar* data, uchar* indices, int len, uchar* palette )
425 {
426     int i;
427     for( i = 0; i < len; i++ )
428     {
429         data[i] = palette[indices[i]];
430     }
431     return data + len;
432 }
433
434
435 uchar* FillColorRow4( uchar* data, uchar* indices, int len, PaletteEntry* palette )
436 {
437     uchar* end = data + len*3;
438
439     while( (data += 6) < end )
440     {
441         int idx = *indices++;
442         *((PaletteEntry*)(data-6)) = palette[idx >> 4];
443         *((PaletteEntry*)(data-3)) = palette[idx & 15];
444     }
445
446     int idx = indices[0];
447     PaletteEntry clr = palette[idx >> 4];
448     WRITE_PIX( data - 6, clr );
449
450     if( data == end )
451     {
452         clr = palette[idx & 15];
453         WRITE_PIX( data - 3, clr );
454     }
455     return end;
456 }
457
458
459 uchar* FillGrayRow4( uchar* data, uchar* indices, int len, uchar* palette )
460 {
461     uchar* end = data + len;
462     while( (data += 2) < end )
463     {
464         int idx = *indices++;
465         data[-2] = palette[idx >> 4];
466         data[-1] = palette[idx & 15];
467     }
468
469     int idx = indices[0];
470     uchar clr = palette[idx >> 4];
471     data[-2] = clr;
472
473     if( data == end )
474     {
475         clr = palette[idx & 15];
476         data[-1] = clr;
477     }
478     return end;
479 }
480
481
482 uchar* FillColorRow1( uchar* data, uchar* indices, int len, PaletteEntry* palette )
483 {
484     uchar* end = data + len*3;
485
486     while( (data += 24) < end )
487     {
488         int idx = *indices++;
489         *((PaletteEntry*)(data - 24)) = palette[(idx & 128) != 0];
490         *((PaletteEntry*)(data - 21)) = palette[(idx & 64) != 0];
491         *((PaletteEntry*)(data - 18)) = palette[(idx & 32) != 0];
492         *((PaletteEntry*)(data - 15)) = palette[(idx & 16) != 0];
493         *((PaletteEntry*)(data - 12)) = palette[(idx & 8) != 0];
494         *((PaletteEntry*)(data - 9)) = palette[(idx & 4) != 0];
495         *((PaletteEntry*)(data - 6)) = palette[(idx & 2) != 0];
496         *((PaletteEntry*)(data - 3)) = palette[(idx & 1) != 0];
497     }
498
499     int idx = indices[0] << 24;
500     for( data -= 24; data < end; data += 3, idx += idx )
501     {
502         PaletteEntry clr = palette[idx < 0];
503         WRITE_PIX( data, clr );
504     }
505
506     return data;
507 }
508
509
510 uchar* FillGrayRow1( uchar* data, uchar* indices, int len, uchar* palette )
511 {
512     uchar* end = data + len;
513
514     while( (data += 8) < end )
515     {
516         int idx = *indices++;
517         *((uchar*)(data - 8)) = palette[(idx & 128) != 0];
518         *((uchar*)(data - 7)) = palette[(idx & 64) != 0];
519         *((uchar*)(data - 6)) = palette[(idx & 32) != 0];
520         *((uchar*)(data - 5)) = palette[(idx & 16) != 0];
521         *((uchar*)(data - 4)) = palette[(idx & 8) != 0];
522         *((uchar*)(data - 3)) = palette[(idx & 4) != 0];
523         *((uchar*)(data - 2)) = palette[(idx & 2) != 0];
524         *((uchar*)(data - 1)) = palette[(idx & 1) != 0];
525     }
526
527     int idx = indices[0] << 24;
528     for( data -= 8; data < end; data++, idx += idx )
529     {
530         data[0] = palette[idx < 0];
531     }
532
533     return data;
534 }
535
536
537 CV_IMPL void
538 cvConvertImage( const CvArr* srcarr, CvArr* dstarr, int flags )
539 {
540     CvMat* temp = 0;
541
542     CV_FUNCNAME( "cvConvertImage" );
543
544     __BEGIN__;
545
546     CvMat srcstub, *src;
547     CvMat dststub, *dst;
548     int src_cn, dst_cn, swap_rb = flags & CV_CVTIMG_SWAP_RB;
549
550     CV_CALL( src = cvGetMat( srcarr, &srcstub ));
551     CV_CALL( dst = cvGetMat( dstarr, &dststub ));
552
553     src_cn = CV_MAT_CN( src->type );
554     dst_cn = CV_MAT_CN( dst->type );
555
556     if( src_cn != 1 && src_cn != 3 && src_cn != 4 )
557         CV_ERROR( CV_BadNumChannels, "Source image must have 1, 3 or 4 channels" );
558
559     if( CV_MAT_DEPTH( dst->type ) != CV_8U )
560         CV_ERROR( CV_BadDepth, "Destination image must be 8u" );
561
562     if( CV_MAT_CN(dst->type) != 1 && CV_MAT_CN(dst->type) != 3 )
563         CV_ERROR( CV_BadNumChannels, "Destination image must have 1 or 3 channels" );
564
565     if( !CV_ARE_DEPTHS_EQ( src, dst ))
566     {
567         int src_depth = CV_MAT_DEPTH(src->type);
568         double scale = src_depth <= CV_8S ? 1 : src_depth <= CV_32S ? 1./256 : 255;
569         double shift = src_depth == CV_8S || src_depth == CV_16S ? 128 : 0;
570
571         if( !CV_ARE_CNS_EQ( src, dst ))
572         {
573             temp = cvCreateMat( src->height, src->width,
574                 (src->type & CV_MAT_CN_MASK)|(dst->type & CV_MAT_DEPTH_MASK));
575             cvConvertScale( src, temp, scale, shift );
576             src = temp;
577         }
578         else
579         {
580             cvConvertScale( src, dst, scale, shift );
581             src = dst;
582         }
583     }
584
585     if( src_cn != dst_cn || (src_cn == 3 && swap_rb) )
586     {
587         uchar *s = src->data.ptr, *d = dst->data.ptr;
588         int s_step = src->step, d_step = dst->step;
589         int code = src_cn*10 + dst_cn;
590         CvSize size = { src->cols, src->rows };
591
592         if( CV_IS_MAT_CONT(src->type & dst->type) )
593         {
594             size.width *= size.height;
595             size.height = 1;
596             s_step = d_step = CV_STUB_STEP;
597         }
598
599         switch( code )
600         {
601         case 13:
602             icvCvt_Gray2BGR_8u_C1C3R( s, s_step, d, d_step, size );
603             break;
604         case 31:
605             icvCvt_BGR2Gray_8u_C3C1R( s, s_step, d, d_step, size, swap_rb );
606             break;
607         case 33:
608             assert( swap_rb );
609             icvCvt_RGB2BGR_8u_C3R( s, s_step, d, d_step, size );
610             break;
611         case 41:
612             icvCvt_BGRA2Gray_8u_C4C1R( s, s_step, d, d_step, size, swap_rb );
613             break;
614         case 43:
615             icvCvt_BGRA2BGR_8u_C4C3R( s, s_step, d, d_step, size, swap_rb );
616             break;
617         default:
618             CV_ERROR( CV_StsUnsupportedFormat, "Unsupported combination of input/output formats" );
619         }
620         src = dst;
621     }
622
623     if( flags & CV_CVTIMG_FLIP )
624     {
625         CV_CALL( cvFlip( src, dst, 0 ));
626     }
627     else if( src != dst )
628     {
629         CV_CALL( cvCopy( src, dst ));
630     }
631
632     __END__;
633
634     cvReleaseMat( &temp );
635 }