92ce32fe6384dd0bb6930f50f10a20f328fa9375
[opencv] / src / cv / cvutils.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 "_cv.h"
43
44 CV_IMPL CvSeq* cvPointSeqFromMat( int seq_kind, const CvArr* arr,
45                                   CvContour* contour_header, CvSeqBlock* block )
46 {
47     CvSeq* contour = 0;
48
49     CV_FUNCNAME( "cvPointSeqFromMat" );
50
51     assert( arr != 0 && contour_header != 0 && block != 0 );
52
53     __BEGIN__;
54     
55     int eltype;
56     CvMat* mat = (CvMat*)arr;
57     
58     if( !CV_IS_MAT( mat ))
59         CV_ERROR( CV_StsBadArg, "Input array is not a valid matrix" ); 
60
61     eltype = CV_MAT_TYPE( mat->type );
62     if( eltype != CV_32SC2 && eltype != CV_32FC2 )
63         CV_ERROR( CV_StsUnsupportedFormat,
64         "The matrix can not be converted to point sequence because of "
65         "inappropriate element type" );
66
67     if( (mat->width != 1 && mat->height != 1) || !CV_IS_MAT_CONT(mat->type))
68         CV_ERROR( CV_StsBadArg,
69         "The matrix converted to point sequence must be "
70         "1-dimensional and continuous" );
71
72     CV_CALL( cvMakeSeqHeaderForArray(
73             (seq_kind & (CV_SEQ_KIND_MASK|CV_SEQ_FLAG_CLOSED)) | eltype,
74             sizeof(CvContour), CV_ELEM_SIZE(eltype), mat->data.ptr,
75             mat->width*mat->height, (CvSeq*)contour_header, block ));
76
77     contour = (CvSeq*)contour_header;
78
79     __END__;
80
81     return contour;
82 }
83
84
85 typedef CvStatus (CV_STDCALL * CvCopyNonConstBorderFunc)(
86     const void*, int, CvSize, void*, int, CvSize, int, int );
87
88 typedef CvStatus (CV_STDCALL * CvCopyNonConstBorderFuncI)(
89     const void*, int, CvSize, CvSize, int, int );
90
91 CvStatus CV_STDCALL
92 icvCopyReplicateBorder_8u( const uchar* src, int srcstep, CvSize srcroi,
93                            uchar* dst, int dststep, CvSize dstroi,
94                            int top, int left, int cn, const uchar* )
95 {
96     const int isz = (int)sizeof(int);
97     int i, j;
98
99     if( (cn | srcstep | dststep | (size_t)src | (size_t)dst) % isz == 0 )
100     {
101         const int* isrc = (const int*)src;
102         int* idst = (int*)dst;
103         
104         cn /= isz;
105         srcstep /= isz;
106         dststep /= isz;
107
108         srcroi.width *= cn;
109         dstroi.width *= cn;
110         left *= cn;
111
112         for( i = 0; i < dstroi.height; i++, idst += dststep )
113         {
114             if( idst + left != isrc )
115                 memcpy( idst + left, isrc, srcroi.width*sizeof(idst[0]) );
116             for( j = left - 1; j >= 0; j-- )
117                 idst[j] = idst[j + cn];
118             for( j = left+srcroi.width; j < dstroi.width; j++ )
119                 idst[j] = idst[j - cn];
120             if( i >= top && i < top + srcroi.height - 1 )
121                 isrc += srcstep;
122         }
123     }
124     else
125     {
126         srcroi.width *= cn;
127         dstroi.width *= cn;
128         left *= cn;
129
130         for( i = 0; i < dstroi.height; i++, dst += dststep )
131         {
132             if( dst + left != src )
133                 memcpy( dst + left, src, srcroi.width );
134             for( j = left - 1; j >= 0; j-- )
135                 dst[j] = dst[j + cn];
136             for( j = left+srcroi.width; j < dstroi.width; j++ )
137                 dst[j] = dst[j - cn];
138             if( i >= top && i < top + srcroi.height - 1 )
139                 src += srcstep;
140         }
141     }
142
143     return CV_OK;
144 }
145
146
147 static CvStatus CV_STDCALL
148 icvCopyReflect101Border_8u( const uchar* src, int srcstep, CvSize srcroi,
149                             uchar* dst, int dststep, CvSize dstroi,
150                             int top, int left, int cn )
151 {
152     const int isz = (int)sizeof(int);
153     int i, j, k, t, dj, tab_size, int_mode = 0;
154     const int* isrc = (const int*)src;
155     int* idst = (int*)dst, *tab;
156
157     if( (cn | srcstep | dststep | (size_t)src | (size_t)dst) % isz == 0 )
158     {
159         cn /= isz;
160         srcstep /= isz;
161         dststep /= isz;
162
163         int_mode = 1;
164     }
165
166     srcroi.width *= cn;
167     dstroi.width *= cn;
168     left *= cn;
169
170     tab_size = dstroi.width - srcroi.width;
171     tab = (int*)cvStackAlloc( tab_size*sizeof(tab[0]) );
172
173     if( srcroi.width == 1 )
174     {
175         for( k = 0; k < cn; k++ )
176             for( i = 0; i < tab_size; i += cn )
177                 tab[i + k] = k + left;
178     }
179     else
180     {
181         j = dj = cn;
182         for( i = left - cn; i >= 0; i -= cn )
183         {
184             for( k = 0; k < cn; k++ )
185                 tab[i + k] = j + k + left;
186             if( (unsigned)(j += dj) >= (unsigned)srcroi.width )
187                 j -= 2*dj, dj = -dj;
188         }
189         
190         j = srcroi.width - cn*2;
191         dj = -cn;
192         for( i = left; i < tab_size; i += cn )
193         {
194             for( k = 0; k < cn; k++ )
195                 tab[i + k] = j + k + left;
196             if( (unsigned)(j += dj) >= (unsigned)srcroi.width )
197                 j -= 2*dj, dj = -dj;
198         }
199     }
200
201     if( int_mode )
202     {
203         idst += top*dststep;
204         for( i = 0; i < srcroi.height; i++, isrc += srcstep, idst += dststep )
205         {
206             if( idst + left != isrc )
207                 memcpy( idst + left, isrc, srcroi.width*sizeof(idst[0]) );
208             for( j = 0; j < left; j++ )
209             {
210                 k = tab[j]; 
211                 idst[j] = idst[k];
212             }
213             for( ; j < tab_size; j++ )
214             {
215                 k = tab[j];
216                 idst[j + srcroi.width] = idst[k];
217             }
218         }
219         isrc -= srcroi.height*srcstep;
220         idst -= (top + srcroi.height)*dststep;
221     }
222     else
223     {
224         dst += top*dststep;
225         for( i = 0; i < srcroi.height; i++, src += srcstep, dst += dststep )
226         {
227             if( dst + left != src )
228                 memcpy( dst + left, src, srcroi.width );
229             for( j = 0; j < left; j++ )
230             {
231                 k = tab[j]; 
232                 dst[j] = dst[k];
233             }
234             for( ; j < tab_size; j++ )
235             {
236                 k = tab[j];
237                 dst[j + srcroi.width] = dst[k];
238             }
239         }
240         src -= srcroi.height*srcstep;
241         dst -= (top + srcroi.height)*dststep;
242     }
243
244     for( t = 0; t < 2; t++ )
245     {
246         int i1, i2, di;
247         if( t == 0 )
248             i1 = top-1, i2 = 0, di = -1, j = 1, dj = 1;
249         else
250             i1 = top+srcroi.height, i2=dstroi.height, di = 1, j = srcroi.height-2, dj = -1;
251         
252         for( i = i1; i != i2; i += di )
253         {
254             if( int_mode )
255             {
256                 const int* s = idst + i*dststep;
257                 int* d = idst + (j+top)*dststep;
258                 for( k = 0; k < dstroi.width; k++ )
259                     d[k] = s[k];
260             }
261             else
262             {
263                 const uchar* s = dst + i*dststep;
264                 uchar* d = dst + (j+top)*dststep;
265                 for( k = 0; k < dstroi.width; k++ )
266                     d[k] = s[k];
267             }
268
269             if( (unsigned)(j += dj) >= (unsigned)srcroi.height )
270                 j -= 2*dj, dj = -dj;
271         }
272     }
273
274     return CV_OK;
275 }
276
277
278 static CvStatus CV_STDCALL
279 icvCopyConstBorder_8u( const uchar* src, int srcstep, CvSize srcroi,
280                        uchar* dst, int dststep, CvSize dstroi,
281                        int top, int left, int cn, const uchar* value )
282 {
283     const int isz = (int)sizeof(int);
284     int i, j, k;
285     if( (cn | srcstep | dststep | (size_t)src | (size_t)dst | (size_t)value) % isz == 0 )
286     {
287         const int* isrc = (const int*)src;
288         int* idst = (int*)dst;
289         const int* ivalue = (const int*)value;
290         int v0 = ivalue[0];
291         
292         cn /= isz;
293         srcstep /= isz;
294         dststep /= isz;
295
296         srcroi.width *= cn;
297         dstroi.width *= cn;
298         left *= cn;
299
300         for( j = 1; j < cn; j++ )
301             if( ivalue[j] != ivalue[0] )
302                 break;
303
304         if( j == cn )
305             cn = 1;
306
307         if( dstroi.width <= 0 )
308             return CV_OK;
309
310         for( i = 0; i < dstroi.height; i++, idst += dststep )
311         {
312             if( i < top || i >= top + srcroi.height )
313             {
314                 if( cn == 1 )
315                 {
316                     for( j = 0; j < dstroi.width; j++ )
317                         idst[j] = v0;
318                 }
319                 else
320                 {
321                     for( j = 0; j < cn; j++ )
322                         idst[j] = ivalue[j];
323                     for( ; j < dstroi.width; j++ )
324                         idst[j] = idst[j - cn];
325                 }
326                 continue;
327             }
328
329             if( cn == 1 )
330             {
331                 for( j = 0; j < left; j++ )
332                     idst[j] = v0;
333                 for( j = srcroi.width + left; j < dstroi.width; j++ )
334                     idst[j] = v0;
335             }
336             else
337             {
338                 for( k = 0; k < cn; k++ )
339                 {
340                     for( j = 0; j < left; j += cn )
341                         idst[j+k] = ivalue[k];
342                     for( j = srcroi.width + left; j < dstroi.width; j += cn )
343                         idst[j+k] = ivalue[k];
344                 }
345             }
346
347             if( idst + left != isrc )
348                 for( j = 0; j < srcroi.width; j++ )
349                     idst[j + left] = isrc[j];
350             isrc += srcstep;
351         }
352     }
353     else
354     {
355         uchar v0 = value[0];
356         
357         srcroi.width *= cn;
358         dstroi.width *= cn;
359         left *= cn;
360
361         for( j = 1; j < cn; j++ )
362             if( value[j] != value[0] )
363                 break;
364
365         if( j == cn )
366             cn = 1;
367
368         if( dstroi.width <= 0 )
369             return CV_OK;
370
371         for( i = 0; i < dstroi.height; i++, dst += dststep )
372         {
373             if( i < top || i >= top + srcroi.height )
374             {
375                 if( cn == 1 )
376                 {
377                     for( j = 0; j < dstroi.width; j++ )
378                         dst[j] = v0;
379                 }
380                 else
381                 {
382                     for( j = 0; j < cn; j++ )
383                         dst[j] = value[j];
384                     for( ; j < dstroi.width; j++ )
385                         dst[j] = dst[j - cn];
386                 }
387                 continue;
388             }
389
390             if( cn == 1 )
391             {
392                 for( j = 0; j < left; j++ )
393                     dst[j] = v0;
394                 for( j = srcroi.width + left; j < dstroi.width; j++ )
395                     dst[j] = v0;
396             }
397             else
398             {
399                 for( k = 0; k < cn; k++ )
400                 {
401                     for( j = 0; j < left; j += cn )
402                         dst[j+k] = value[k];
403                     for( j = srcroi.width + left; j < dstroi.width; j += cn )
404                         dst[j+k] = value[k];
405                 }
406             }
407
408             if( dst + left != src )
409                 for( j = 0; j < srcroi.width; j++ )
410                     dst[j + left] = src[j];
411             src += srcstep;
412         }
413     }
414
415     return CV_OK;
416 }
417
418
419 CV_IMPL void
420 cvCopyMakeBorder( const CvArr* srcarr, CvArr* dstarr, CvPoint offset,
421                   int bordertype, CvScalar value )
422 {
423     CV_FUNCNAME( "cvCopyMakeBorder" );
424
425     __BEGIN__;
426
427     CvMat srcstub, *src = (CvMat*)srcarr;
428     CvMat dststub, *dst = (CvMat*)dstarr;
429     CvSize srcsize, dstsize;
430     int srcstep, dststep;
431     int pix_size, type;
432
433     if( !CV_IS_MAT(src) )
434         CV_CALL( src = cvGetMat( src, &srcstub ));
435     
436     if( !CV_IS_MAT(dst) )    
437         CV_CALL( dst = cvGetMat( dst, &dststub ));
438
439     if( offset.x < 0 || offset.y < 0 )
440         CV_ERROR( CV_StsOutOfRange, "Offset (left/top border width) is negative" );
441
442     if( src->rows + offset.y > dst->rows || src->cols + offset.x > dst->cols )
443         CV_ERROR( CV_StsBadSize, "Source array is too big or destination array is too small" );
444
445     if( !CV_ARE_TYPES_EQ( src, dst ))
446         CV_ERROR( CV_StsUnmatchedFormats, "" );
447
448     type = CV_MAT_TYPE(src->type);
449     pix_size = CV_ELEM_SIZE(type);
450     srcsize = cvGetMatSize(src);
451     dstsize = cvGetMatSize(dst);
452     srcstep = src->step;
453     dststep = dst->step;
454     if( srcstep == 0 )
455         srcstep = CV_STUB_STEP;
456     if( dststep == 0 )
457         dststep = CV_STUB_STEP;
458
459     if( bordertype == IPL_BORDER_REPLICATE )
460     {
461         icvCopyReplicateBorder_8u( src->data.ptr, srcstep, srcsize,
462                                    dst->data.ptr, dststep, dstsize,
463                                    offset.y, offset.x, pix_size );
464     }
465     else if( bordertype == IPL_BORDER_REFLECT_101 )
466     {
467         icvCopyReflect101Border_8u( src->data.ptr, srcstep, srcsize,
468                                    dst->data.ptr, dststep, dstsize,
469                                    offset.y, offset.x, pix_size );
470     }
471     else if( bordertype == IPL_BORDER_CONSTANT )
472     {
473         double buf[4];
474         cvScalarToRawData( &value, buf, src->type, 0 );
475         icvCopyConstBorder_8u( src->data.ptr, srcstep, srcsize,
476                                dst->data.ptr, dststep, dstsize,
477                                offset.y, offset.x, pix_size, (uchar*)buf );
478     }
479     else
480         CV_ERROR( CV_StsBadFlag, "Unknown/unsupported border type" );
481     
482     __END__;
483 }
484
485 namespace cv
486 {
487
488 void copyMakeBorder( const Mat& src, Mat& dst, int top, int bottom,
489                      int left, int right, int borderType, const Scalar& value )
490 {
491     dst.create( src.rows + top + bottom, src.cols + left + right, src.type() );
492     CvMat _src = src, _dst = dst;
493     cvCopyMakeBorder( &_src, &_dst, Point(left, top), borderType, value );
494 }
495
496 }
497
498 /* End of file. */