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