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 /****************************************************************************************\
45 Down-sampling pyramids core functions
46 \****************************************************************************************/
47
48 //////////// Filtering macros /////////////
49
50 /* COMMON CASE */
51 /* 1/16[1 4 6 4 1] */
52 /* ...| x0 | x1 | x2 | x3 | x4 |... */
53 #define PD_FILTER( x0, x1, x2, x3, x4 ) ((x2)*6+((x1)+(x3))*4+(x0)+(x4))
54
55 /* MACROS FOR BORDERS */
56
57 /* | b I a | b | reflection used ("I" denotes the image boundary) */
58
59 /* LEFT/TOP */
60 /* 1/16[1 4 6 4 1] */
61 /* | x2 | x1 I x0 | x1 | x2 |... */
62 #define PD_LT(x0,x1,x2) ((x0)*6 + (x1)*8 + (x2)*2)
63
64 /* RIGHT/BOTTOM */
65 /* 1/16[1 4 6 4 1] */
66 /* ...| x0 | x1 | x2 | x3 I x2 | */
67 #define PD_RB(x0,x1,x2,x3) ((x0) + ((x1) + (x3))*4 + (x2)*7)
68
69 /* SINGULAR CASE ( width == 2 || height == 2 ) */
70 /* 1/16[1 4 6 4 1] */
71 /* | x0 | x1 I x0 | x1 I x0 | */
72 #define PD_SINGULAR(x0,x1) (((x0) + (x1))*8)
73
74 #define PD_SCALE_INT(x) (((x) + (1<<7)) >> 8)
75 #define PD_SCALE_FLT(x) ((x)*0.00390625f)
76
77 #define PD_SZ 5
78
79 ////////// generic macro ////////////
80
81 #define ICV_DEF_PYR_DOWN_FUNC( flavor, type, worktype, _pd_scale_ ) \
82 static CvStatus CV_STDCALL \
83 icvPyrDownG5x5_##flavor##_CnR( const type* src, int srcstep, type* dst, \
84 int dststep, CvSize size, void *buf, int Cs ) \
85 { \
86 worktype* buffer = (worktype*)buf; /* pointer to temporary buffer */ \
87 worktype* rows[PD_SZ]; /* array of rows pointers. dim(rows) is PD_SZ */ \
88 int y, top_row = 0; \
89 int Wd = size.width/2, Wdn = Wd*Cs; \
90 int buffer_step = Wdn; \
91 int pd_sz = (PD_SZ + 1)*buffer_step; \
92 int fst = 0, lst = size.height <= PD_SZ/2 ? size.height : PD_SZ/2 + 1; \
93 \
94 assert( Cs == 1 || Cs == 3 ); \
95 srcstep /= sizeof(src[0]); dststep /= sizeof(dst[0]); \
96 \
97 /* main loop */ \
98 for( y = 0; y < size.height; y += 2, dst += dststep ) \
99 { \
100 /* set first and last indices of buffer rows which are need to be filled */ \
101 int x, y1, k = top_row; \
102 int x1 = buffer_step; \
103 worktype *row01, *row23, *row4; \
104 \
105 /* assign rows pointers */ \
106 for( y1 = 0; y1 < PD_SZ; y1++ ) \
107 { \
108 rows[y1] = buffer + k; \
109 k += buffer_step; \
110 k &= k < pd_sz ? -1 : 0; \
111 } \
112 \
113 row01 = rows[0]; \
114 row23 = rows[2]; \
115 row4 = rows[4]; \
116 \
117 /* fill new buffer rows with filtered source (horizontal conv) */ \
118 if( Cs == 1 ) \
119 { \
120 if( size.width > PD_SZ/2 ) \
121 for( y1 = fst; y1 < lst; y1++, src += srcstep ) \
122 { \
123 worktype *row = rows[y1]; \
124 \
125 /* process left & right bounds */ \
126 row[0] = PD_LT( src[0], src[1], src[2] ); \
127 row[Wd-1] = PD_RB( src[Wd*2-4], src[Wd*2-3], \
128 src[Wd*2-2], src[Wd*2-1]); \
129 /* other points (even) */ \
130 for( x = 1; x < Wd - 1; x++ ) \
131 { \
132 row[x] = PD_FILTER( src[2*x-2], src[2*x-1], src[2*x], \
133 src[2*x+1], src[2*x+2] ); \
134 } \
135 } \
136 else \
137 for( y1 = fst; y1 < lst; y1++, src += srcstep ) \
138 { \
139 rows[y1][0] = PD_SINGULAR( src[0], src[1] ); \
140 } \
141 } \
142 else /* Cs == 3 */ \
143 { \
144 for( y1 = fst; y1 < lst; y1++, src += srcstep ) \
145 { \
146 worktype *row = rows[y1]; \
147 \
148 if( size.width > PD_SZ/2 ) \
149 { \
150 int c; \
151 for( c = 0; c < 3; c++ ) \
152 { \
153 /* process left & right bounds */ \
154 row[c] = PD_LT( src[c], src[3+c], src[6+c] ); \
155 row[Wdn-3+c] = PD_RB( src[Wdn*2-12+c], src[Wdn*2-9+c], \
156 src[Wdn*2-6+c], src[Wdn*2-3+c] ); \
157 } \
158 /* other points (even) */ \
159 for( x = 3; x < Wdn - 3; x += 3 ) \
160 { \
161 row[x] = PD_FILTER( src[2*x-6], src[2*x-3], src[2*x], \
162 src[2*x+3], src[2*x+6] ); \
163 row[x+1] = PD_FILTER( src[2*x-5], src[2*x-2], src[2*x+1], \
164 src[2*x+4], src[2*x+7] ); \
165 row[x+2] = PD_FILTER( src[2*x-4], src[2*x-1], src[2*x+2], \
166 src[2*x+5], src[2*x+8] ); \
167 } \
168 } \
169 else /* size.width <= PD_SZ/2 */ \
170 { \
171 row[0] = PD_SINGULAR( src[0], src[3] ); \
172 row[1] = PD_SINGULAR( src[1], src[4] ); \
173 row[2] = PD_SINGULAR( src[2], src[5] ); \
174 } \
175 } \
176 } \
177 \
178 /* second pass. Do vertical conv and write results do destination image */ \
179 if( y > 0 ) \
180 { \
181 if( y < size.height - PD_SZ/2 ) \
182 { \
183 for( x = 0; x < Wdn; x++, x1++ ) \
184 { \
185 dst[x] = (type)_pd_scale_( PD_FILTER( row01[x], row01[x1], \
186 row23[x], row23[x1], row4[x] )); \
187 } \
188 top_row += 2*buffer_step; \
189 top_row &= top_row < pd_sz ? -1 : 0; \
190 } \
191 else /* bottom */ \
192 for( x = 0; x < Wdn; x++, x1++ ) \
193 dst[x] = (type)_pd_scale_( PD_RB( row01[x], row01[x1], \
194 row23[x], row23[x1])); \
195 } \
196 else \
197 { \
198 if( size.height > PD_SZ/2 ) /* top */ \
199 { \
200 for( x = 0; x < Wdn; x++, x1++ ) \
201 dst[x] = (type)_pd_scale_( PD_LT( row01[x], row01[x1], row23[x] )); \
202 } \
203 else /* size.height <= PD_SZ/2 */ \
204 { \
205 for( x = 0; x < Wdn; x++, x1++ ) \
206 dst[x] = (type)_pd_scale_( PD_SINGULAR( row01[x], row01[x1] )); \
207 } \
208 fst = PD_SZ - 2; \
209 } \
210 \
211 lst = y + 2 + PD_SZ/2 < size.height ? PD_SZ : size.height - y; \
212 } \
213 \
214 return CV_OK; \
215 }
216
217
218 ICV_DEF_PYR_DOWN_FUNC( 8u, uchar, int, PD_SCALE_INT )
219 ICV_DEF_PYR_DOWN_FUNC( 16s, short, int, PD_SCALE_INT )
220 ICV_DEF_PYR_DOWN_FUNC( 16u, ushort, int, PD_SCALE_INT )
221 ICV_DEF_PYR_DOWN_FUNC( 32f, float, float, PD_SCALE_FLT )
222 ICV_DEF_PYR_DOWN_FUNC( 64f, double, double, PD_SCALE_FLT )
223
224
225 /****************************************************************************************\
226 Up-sampling pyramids core functions
227 \****************************************************************************************/
228
229 /////////// filtering macros //////////////
230
231 /* COMMON CASE: NON ZERO */
232 /* 1/16[1 4 6 4 1] */
233 /* ...| x0 | 0 | x1 | 0 | x2 |... */
234 #define PU_FILTER( x0, x1, x2 ) ((x1)*6 + (x0) + (x2))
235
236 /* ZERO POINT AT CENTER */
237 /* 1/16[1 4 6 4 1] */
238 /* ...| 0 | x0 | 0 | x1 | 0 |... */
239 #define PU_FILTER_ZI( x0, x1 ) (((x0) + (x1))*4)
240
241 /* MACROS FOR BORDERS */
242
243 /* | b I a | b | reflection */
244
245 /* LEFT/TOP */
246 /* 1/16[1 4 6 4 1] */
247 /* | x1 | 0 I x0 | 0 | x1 |... */
248 #define PU_LT( x0, x1 ) ((x0)*6 + (x1)*2)
249
250 /* 1/16[1 4 6 4 1] */
251 /* | 0 I x0 | 0 | x1 | 0 |... */
252 #define PU_LT_ZI( x0, x1 ) PU_FILTER_ZI((x0),(x1))
253
254 /* RIGHT/BOTTOM: NON ZERO */
255 /* 1/16[1 4 6 4 1] */
256 /* ...| x0 | 0 | x1 | 0 I x1 | */
257 #define PU_RB( x0, x1 ) ((x0) + (x1)*7)
258
259 /* RIGHT/BOTTOM: ZERO POINT AT CENTER */
260 /* 1/16[1 4 6 4 1] */
261 /* ...| 0 | x0 | 0 I x0 | 0 | */
262 #define PU_RB_ZI( x0 ) ((x0)*8)
263
264 /* SINGULAR CASE */
265 /* 1/16[1 4 6 4 1] */
266 /* | x0 | 0 I x0 | 0 I x0 | */
267 #define PU_SINGULAR( x0 ) PU_RB_ZI((x0)) /* <--| the same formulas */
268 #define PU_SINGULAR_ZI( x0 ) PU_RB_ZI((x0)) /* <--| */
269
270 /* x/64 - scaling in up-sampling functions */
271 #define PU_SCALE_INT(x) (((x) + (1<<5)) >> 6)
272 #define PU_SCALE_FLT(x) ((x)*0.015625f)
273
274 #define PU_SZ 3
275
276 //////////// generic macro /////////////
277
278
279 #define ICV_DEF_PYR_UP_FUNC( flavor, type, worktype, _pu_scale_ ) \
280 static CvStatus CV_STDCALL \
281 icvPyrUpG5x5_##flavor##_CnR( const type* src, int srcstep, type* dst, \
282 int dststep, CvSize size, void *buf, int Cs ) \
283 { \
284 worktype *buffer = (worktype*)buf; \
285 worktype *rows[PU_SZ]; \
286 int y, top_row = 0; \
287 int Wd = size.width * 2, Wdn = Wd * Cs, Wn = size.width * Cs; \
288 int buffer_step = Wdn; \
289 int pu_sz = PU_SZ*buffer_step; \
290 int fst = 0, lst = size.height <= PU_SZ/2 ? size.height : PU_SZ/2 + 1; \
291 \
292 assert( Cs == 1 || Cs == 3 ); \
293 srcstep /= sizeof(src[0]); dststep /= sizeof(dst[0]); \
294 \
295 /* main loop */ \
296 for( y = 0; y < size.height; y++, dst += 2 * dststep ) \
297 { \
298 int x, y1, k = top_row; \
299 worktype *row0, *row1, *row2; \
300 type *dst1; \
301 \
302 /* assign rows pointers */ \
303 for( y1 = 0; y1 < PU_SZ; y1++ ) \
304 { \
305 rows[y1] = buffer + k; \
306 k += buffer_step; \
307 k &= k < pu_sz ? -1 : 0; \
308 } \
309 \
310 row0 = rows[0]; \
311 row1 = rows[1]; \
312 row2 = rows[2]; \
313 dst1 = dst + dststep; \
314 \
315 /* fill new buffer rows with filtered source (horizontal conv) */ \
316 if( Cs == 1 ) \
317 if( size.width > PU_SZ / 2 ) \
318 for( y1 = fst; y1 < lst; y1++, src += srcstep ) \
319 { \
320 worktype *row = rows[y1]; \
321 \
322 /* process left & right bounds */ \
323 row[0] = PU_LT( src[0], src[1] ); \
324 row[1] = PU_LT_ZI( src[0], src[1] ); \
325 row[size.width * 2 - 2] = PU_RB( src[size.width - 2], \
326 src[size.width - 1] ); \
327 row[size.width * 2 - 1] = PU_RB_ZI( src[size.width - 1] ); \
328 /* other points */ \
329 for( x = 1; x < size.width - 1; x++ ) \
330 { \
331 row[2 * x] = PU_FILTER( src[x - 1], src[x], src[x + 1] ); \
332 row[2 * x + 1] = PU_FILTER_ZI( src[x], src[x + 1] ); \
333 } \
334 } \
335 else /* size.width <= PU_SZ/2 */ \
336 for( y1 = fst; y1 < lst; y1++, src += srcstep ) \
337 { \
338 worktype *row = rows[y1]; \
339 worktype val = src[0]; \
340 \
341 row[0] = PU_SINGULAR( val ); \
342 row[1] = PU_SINGULAR_ZI( val ); \
343 } \
344 else /* Cs == 3 */ \
345 for( y1 = fst; y1 < lst; y1++, src += srcstep ) \
346 { \
347 worktype *row = rows[y1]; \
348 \
349 if( size.width > PU_SZ / 2 ) \
350 { \
351 int c; \
352 \
353 for( c = 0; c < 3; c++ ) \
354 { \
355 /* process left & right bounds */ \
356 row[c] = PU_LT( src[c], src[3 + c] ); \
357 row[3 + c] = PU_LT_ZI( src[c], src[3 + c] ); \
358 row[Wn * 2 - 6 + c] = PU_RB( src[Wn - 6 + c], src[Wn - 3 + c]); \
359 row[Wn * 2 - 3 + c] = PU_RB_ZI( src[Wn - 3 + c] ); \
360 } \
361 /* other points */ \
362 for( x = 3; x < Wn - 3; x += 3 ) \
363 { \
364 row[2 * x] = PU_FILTER( src[x - 3], src[x], src[x + 3] ); \
365 row[2 * x + 3] = PU_FILTER_ZI( src[x], src[x + 3] ); \
366 \
367 row[2 * x + 1] = PU_FILTER( src[x - 2], src[x + 1], src[x + 4]);\
368 row[2 * x + 4] = PU_FILTER_ZI( src[x + 1], src[x + 4] ); \
369 \
370 row[2 * x + 2] = PU_FILTER( src[x - 1], src[x + 2], src[x + 5]);\
371 row[2 * x + 5] = PU_FILTER_ZI( src[x + 2], src[x + 5] ); \
372 } \
373 } \
374 else /* size.width <= PU_SZ/2 */ \
375 { \
376 int c; \
377 \
378 for( c = 0; c < 3; c++ ) \
379 { \
380 row[c] = PU_SINGULAR( src[c] ); \
381 row[3 + c] = PU_SINGULAR_ZI( src[c] ); \
382 } \
383 } \
384 } \
385 \
386 /* second pass. Do vertical conv and write results do destination image */ \
387 if( y > 0 ) \
388 { \
389 if( y < size.height - PU_SZ / 2 ) \
390 { \
391 for( x = 0; x < Wdn; x++ ) \
392 { \
393 dst[x] = (type)_pu_scale_( PU_FILTER( row0[x], row1[x], row2[x] )); \
394 dst1[x] = (type)_pu_scale_( PU_FILTER_ZI( row1[x], row2[x] )); \
395 } \
396 top_row += buffer_step; \
397 top_row &= top_row < pu_sz ? -1 : 0; \
398 } \
399 else /* bottom */ \
400 for( x = 0; x < Wdn; x++ ) \
401 { \
402 dst[x] = (type)_pu_scale_( PU_RB( row0[x], row1[x] )); \
403 dst1[x] = (type)_pu_scale_( PU_RB_ZI( row1[x] )); \
404 } \
405 } \
406 else \
407 { \
408 if( size.height > PU_SZ / 2 ) /* top */ \
409 for( x = 0; x < Wdn; x++ ) \
410 { \
411 dst[x] = (type)_pu_scale_( PU_LT( row0[x], row1[x] )); \
412 dst1[x] = (type)_pu_scale_( PU_LT_ZI( row0[x], row1[x] )); \
413 } \
414 else /* size.height <= PU_SZ/2 */ \
415 for( x = 0; x < Wdn; x++ ) \
416 { \
417 dst[x] = (type)_pu_scale_( PU_SINGULAR( row0[x] )); \
418 dst1[x] = (type)_pu_scale_( PU_SINGULAR_ZI( row0[x] )); \
419 } \
420 fst = PU_SZ - 1; \
421 } \
422 \
423 lst = y < size.height - PU_SZ/2 - 1 ? PU_SZ : size.height + PU_SZ/2 - y - 1; \
424 } \
425 \
426 return CV_OK; \
427 }
428
429
430 ICV_DEF_PYR_UP_FUNC( 8u, uchar, int, PU_SCALE_INT )
431 ICV_DEF_PYR_UP_FUNC( 16s, short, int, PU_SCALE_INT )
432 ICV_DEF_PYR_UP_FUNC( 16u, ushort, int, PU_SCALE_INT )
433 ICV_DEF_PYR_UP_FUNC( 32f, float, float, PU_SCALE_FLT )
434 ICV_DEF_PYR_UP_FUNC( 64f, double, double, PU_SCALE_FLT )
435
436
437 static CvStatus CV_STDCALL
icvPyrUpG5x5_GetBufSize(int roiWidth,CvDataType dataType,int channels,int * bufSize)438 icvPyrUpG5x5_GetBufSize( int roiWidth, CvDataType dataType,
439 int channels, int *bufSize )
440 {
441 int bufStep;
442
443 if( !bufSize )
444 return CV_NULLPTR_ERR;
445 *bufSize = 0;
446
447 if( roiWidth < 0 )
448 return CV_BADSIZE_ERR;
449 if( channels != 1 && channels != 3 )
450 return CV_UNSUPPORTED_CHANNELS_ERR;
451
452 bufStep = 2*roiWidth*channels;
453
454 if( dataType == cv64f )
455 bufStep *= sizeof(double);
456 else
457 bufStep *= sizeof(int);
458
459 *bufSize = bufStep * PU_SZ;
460 return CV_OK;
461 }
462
463
464 static CvStatus CV_STDCALL
icvPyrDownG5x5_GetBufSize(int roiWidth,CvDataType dataType,int channels,int * bufSize)465 icvPyrDownG5x5_GetBufSize( int roiWidth, CvDataType dataType,
466 int channels, int *bufSize )
467 {
468 int bufStep;
469
470 if( !bufSize )
471 return CV_NULLPTR_ERR;
472 *bufSize = 0;
473
474 if( roiWidth < 0 || (roiWidth & 1) != 0 )
475 return CV_BADSIZE_ERR;
476 if( channels != 1 && channels != 3 )
477 return CV_UNSUPPORTED_CHANNELS_ERR;
478
479 bufStep = 2*roiWidth*channels;
480
481 if( dataType == cv64f )
482 bufStep *= sizeof(double);
483 else
484 bufStep *= sizeof(int);
485
486 *bufSize = bufStep * (PD_SZ + 1);
487 return CV_OK;
488 }
489
490 /****************************************************************************************\
491 Downsampled image border completion
492 \****************************************************************************************/
493
494 #define ICV_DEF_PYR_BORDER_FUNC( flavor, arrtype, worktype, _pd_scale_ ) \
495 static CvStatus CV_STDCALL \
496 icvPyrDownBorder_##flavor##_CnR( const arrtype *src, int src_step, CvSize src_size, \
497 arrtype *dst, int dst_step, CvSize dst_size, int channels ) \
498 { \
499 int local_alloc = 0; \
500 worktype *buf = 0, *buf0 = 0; \
501 const arrtype* src2; \
502 arrtype* dst2; \
503 int buf_size; \
504 int i, j; \
505 int W = src_size.width, H = src_size.height; \
506 int Wd = dst_size.width, Hd = dst_size.height; \
507 int Wd_, Hd_; \
508 int Wn = W*channels; \
509 int bufW; \
510 int cols, rows; /* columns and rows to modify */ \
511 \
512 assert( channels == 1 || channels == 3 ); \
513 \
514 buf_size = MAX(src_size.width,src_size.height) * sizeof(buf[0]) * 2 * channels; \
515 if( buf_size > (1 << 14) ) \
516 { \
517 buf = (worktype*)cvAlloc( buf_size ); \
518 if( !buf ) \
519 return CV_OUTOFMEM_ERR; \
520 } \
521 else \
522 { \
523 buf = (worktype*)cvAlignPtr(alloca( buf_size+8 ), 8); \
524 local_alloc = 1; \
525 } \
526 \
527 buf0 = buf; \
528 \
529 src_step /= sizeof(src[0]); \
530 dst_step /= sizeof(dst[0]); \
531 \
532 cols = (W & 1) + (Wd*2 > W); \
533 rows = (H & 1) + (Hd*2 > H); \
534 \
535 src2 = src + (H-1)*src_step; \
536 dst2 = dst + (Hd - rows)*dst_step; \
537 src += (W - 1)*channels; \
538 dst += (Wd - cols)*channels; \
539 \
540 /* part of row(column) from 1 to Wd_(Hd_) is processed using PD_FILTER macro */ \
541 Wd_ = Wd - 1 + (cols == 1 && (W & 1) != 0); \
542 Hd_ = Hd - 1 + (rows == 1 && (H & 1) != 0); \
543 \
544 bufW = channels * cols; \
545 \
546 /******************* STAGE 1. ******************/ \
547 \
548 /* do horizontal convolution of the 1-2 right columns and write results to buffer */\
549 if( cols > 0 ) \
550 { \
551 if( W <= 2 ) \
552 { \
553 assert( Wd == 1 ); \
554 for( i = 0; i < H; i++, src += src_step, buf += channels ) \
555 { \
556 if( channels == 1 ) \
557 buf[0] = PD_SINGULAR( src[1-Wn], src[0] ); \
558 else \
559 { \
560 buf[0] = PD_SINGULAR( src[3-Wn], src[0] ); \
561 buf[1] = PD_SINGULAR( src[4-Wn], src[1] ); \
562 buf[2] = PD_SINGULAR( src[5-Wn], src[2] ); \
563 } \
564 } \
565 } \
566 else if( (W == 3 && Wd == 1) || (W > 3 && !(Wd & 1)) ) \
567 { \
568 for( i = 0; i < H; i++, src += src_step, buf += channels ) \
569 { \
570 if( channels == 1 ) \
571 buf[0] = PD_LT( src[-2], src[-1], src[0] ); \
572 else \
573 { \
574 buf[0] = PD_LT( src[-6], src[-3], src[0] ); \
575 buf[1] = PD_LT( src[-5], src[-2], src[1] ); \
576 buf[2] = PD_LT( src[-4], src[-1], src[2] ); \
577 } \
578 } \
579 } \
580 else if( W == 3 ) \
581 { \
582 for( i = 0; i < H; i++, src += src_step, buf += channels*2 ) \
583 { \
584 if( channels == 1 ) \
585 { \
586 buf[0] = PD_LT( src[-2], src[-1], src[0] ); \
587 buf[1] = PD_LT( src[0], src[-1], src[-2] ); \
588 } \
589 else \
590 { \
591 buf[0] = PD_LT( src[-6], src[-3], src[0] ); \
592 buf[1] = PD_LT( src[-5], src[-2], src[1] ); \
593 buf[2] = PD_LT( src[-4], src[-1], src[2] ); \
594 buf[3] = PD_LT( src[0], src[-3], src[-6] ); \
595 buf[4] = PD_LT( src[1], src[-2], src[-5] ); \
596 buf[5] = PD_LT( src[2], src[-1], src[-4] ); \
597 } \
598 } \
599 } \
600 else if( cols == 1 ) \
601 { \
602 for( i = 0; i < H; i++, src += src_step, buf += channels ) \
603 { \
604 if( channels == 1 ) \
605 buf[0] = PD_FILTER( src[-4], src[-3], src[-2], src[-1], src[0]); \
606 else \
607 { \
608 buf[0] = PD_FILTER( src[-12], src[-9], src[-6], src[-3], src[0]); \
609 buf[1] = PD_FILTER( src[-11], src[-8], src[-5], src[-2], src[1]); \
610 buf[2] = PD_FILTER( src[-10], src[-7], src[-4], src[-1], src[2]); \
611 } \
612 } \
613 } \
614 else \
615 { \
616 for( i = 0; i < H; i++, src += src_step, buf += channels*2 ) \
617 { \
618 if( channels == 1 ) \
619 { \
620 buf[0] = PD_FILTER( src[-4], src[-3], src[-2], src[-1], src[0] ); \
621 buf[1] = PD_LT( src[0], src[-1], src[-2] ); \
622 } \
623 else \
624 { \
625 buf[0] = PD_FILTER( src[-12], src[-9], src[-6], src[-3], src[0] ); \
626 buf[1] = PD_FILTER( src[-11], src[-8], src[-5], src[-2], src[1] ); \
627 buf[2] = PD_FILTER( src[-10], src[-7], src[-4], src[-1], src[2] ); \
628 buf[3] = PD_LT( src[0], src[-3], src[-6] ); \
629 buf[4] = PD_LT( src[1], src[-2], src[-5] ); \
630 buf[5] = PD_LT( src[2], src[-1], src[-4] ); \
631 } \
632 } \
633 } \
634 buf = buf0; \
635 } \
636 \
637 src = src2; \
638 \
639 /******************* STAGE 2. ******************/ \
640 \
641 /* do vertical convolution of the pre-processed right columns, */ \
642 /* stored in buffer, and write results to the destination */ \
643 /* do vertical convolution of the 1-2 bottom rows */ \
644 /* and write results to the buffer */ \
645 if( H <= 2 ) \
646 { \
647 if( cols > 0 ) \
648 { \
649 assert( Hd == 1 ); \
650 for( j = 0; j < bufW; j++ ) \
651 dst[j] = (arrtype)_pd_scale_( PD_SINGULAR( buf[j], buf[j+(H-1)*bufW] ));\
652 } \
653 \
654 if( rows > 0 ) \
655 { \
656 for( j = 0; j < Wn; j++ ) \
657 buf[j] = PD_SINGULAR( src[j-src_step], src[j] ); \
658 } \
659 } \
660 else if( H == 3 ) \
661 { \
662 if( cols > 0 ) \
663 { \
664 for( j = 0; j < bufW; j++ ) \
665 { \
666 dst[j]= (arrtype)_pd_scale_(PD_LT( buf[j], buf[j+bufW], buf[j+bufW*2]));\
667 } \
668 if( Hd == 2 ) \
669 { \
670 dst += dst_step; \
671 for( j = 0; j < bufW; j++ ) \
672 dst[j] = (arrtype)_pd_scale_( PD_LT( buf[j+bufW*2], \
673 buf[j+bufW], buf[j] )); \
674 } \
675 } \
676 \
677 if( Hd == 1 ) \
678 { \
679 for( j = 0; j < Wn; j++ ) \
680 buf[j] = PD_LT( src[j-src_step*2], src[j - src_step], src[j] ); \
681 } \
682 else \
683 { \
684 for( j = 0; j < Wn; j++ ) \
685 { \
686 buf[j] = PD_LT( src[j-src_step*2], src[j - src_step], src[j] ); \
687 buf[j+Wn] = PD_LT( src[j],src[j-src_step],src[j-src_step*2] ); \
688 } \
689 } \
690 } \
691 else \
692 { \
693 if( cols > 0 ) \
694 { \
695 /* top of the right border */ \
696 for( j = 0; j < bufW; j++ ) \
697 dst[j]=(arrtype)_pd_scale_( PD_LT( buf[j], buf[j+bufW], buf[j+bufW*2]));\
698 \
699 /* middle part of the right border */ \
700 buf += bufW*2; \
701 dst += dst_step; \
702 for( i = 1; i < Hd_; i++, dst += dst_step, buf += bufW*2 ) \
703 { \
704 for( j = 0; j < bufW; j++ ) \
705 dst[j] = (arrtype)_pd_scale_( PD_FILTER( buf[j-bufW*2], buf[j-bufW],\
706 buf[j], buf[j+bufW], buf[j+bufW*2] ));\
707 } \
708 \
709 /* bottom of the right border */ \
710 if( !(H & 1) ) \
711 { \
712 for( j = 0; j < bufW; j++ ) \
713 dst[j] = (arrtype)_pd_scale_( PD_RB( buf[j-bufW*2], buf[j-bufW], \
714 buf[j], buf[j+bufW] )); \
715 } \
716 else if( rows > 1 ) \
717 { \
718 for( j = 0; j < bufW; j++ ) \
719 dst[j]=(arrtype)_pd_scale_( PD_LT( buf[j-bufW*2], \
720 buf[j-bufW], buf[j])); \
721 } \
722 \
723 buf = buf0; \
724 } \
725 \
726 if( rows > 0 ) \
727 { \
728 if( !(H & 1) ) \
729 { \
730 for( j = 0; j < Wn; j++ ) \
731 buf[j] = PD_LT( src[j], src[j-src_step], src[j-src_step*2] ); \
732 } \
733 else if( cols == 1 ) \
734 { \
735 for( j = 0; j < Wn; j++ ) \
736 buf[j] = PD_FILTER( src[j-src_step*4], src[j-src_step*3], \
737 src[j-src_step*2], src[j-src_step], src[j] ); \
738 } \
739 else \
740 { \
741 for( j = 0; j < Wn; j++ ) \
742 { \
743 buf[j] = PD_FILTER( src[j-src_step*4], src[j-src_step*3], \
744 src[j-src_step*2], src[j-src_step], src[j] ); \
745 buf[j+Wn] = PD_LT( src[j], src[j-src_step], src[j-src_step*2] ); \
746 } \
747 } \
748 } \
749 } \
750 \
751 \
752 /******************* STAGE 3. ******************/ \
753 \
754 /* do horizontal convolution of the pre-processed bottom rows,*/ \
755 /* stored in buffer, and write results to the destination */ \
756 if( rows > 0 ) \
757 { \
758 dst = dst2; \
759 \
760 if( W <= 2 ) \
761 { \
762 assert( Wd == 1 ); \
763 for( ; rows--; dst += dst_step, buf += Wn ) \
764 { \
765 if( channels == 1 ) \
766 dst[0] = (arrtype)_pd_scale_( PD_SINGULAR( buf[0], buf[Wn-1] )); \
767 else \
768 { \
769 dst[0] = (arrtype)_pd_scale_( PD_SINGULAR( buf[0], buf[Wn-3] )); \
770 dst[1] = (arrtype)_pd_scale_( PD_SINGULAR( buf[1], buf[Wn-2] )); \
771 dst[2] = (arrtype)_pd_scale_( PD_SINGULAR( buf[2], buf[Wn-1] )); \
772 } \
773 } \
774 } \
775 else if( W == 3 ) \
776 { \
777 if( Wd == 1 ) \
778 { \
779 for( ; rows--; dst += dst_step, buf += Wn ) \
780 { \
781 if( channels == 1 ) \
782 dst[0] = (arrtype)_pd_scale_( PD_LT(buf[0], buf[1], buf[2] )); \
783 else \
784 { \
785 dst[0] = (arrtype)_pd_scale_( PD_LT(buf[0], buf[3], buf[6] )); \
786 dst[1] = (arrtype)_pd_scale_( PD_LT(buf[1], buf[4], buf[7] )); \
787 dst[2] = (arrtype)_pd_scale_( PD_LT(buf[2], buf[5], buf[8] )); \
788 } \
789 } \
790 } \
791 else \
792 { \
793 for( ; rows--; dst += dst_step, buf += Wn ) \
794 { \
795 if( channels == 1 ) \
796 { \
797 dst[0] = (arrtype)_pd_scale_( PD_LT(buf[0], buf[1], buf[2] )); \
798 dst[1] = (arrtype)_pd_scale_( PD_LT(buf[2], buf[1], buf[0] )); \
799 } \
800 else \
801 { \
802 dst[0] = (arrtype)_pd_scale_( PD_LT(buf[0], buf[3], buf[6] )); \
803 dst[1] = (arrtype)_pd_scale_( PD_LT(buf[1], buf[4], buf[7] )); \
804 dst[2] = (arrtype)_pd_scale_( PD_LT(buf[2], buf[5], buf[8] )); \
805 dst[3] = (arrtype)_pd_scale_( PD_LT(buf[6], buf[3], buf[0] )); \
806 dst[4] = (arrtype)_pd_scale_( PD_LT(buf[7], buf[4], buf[1] )); \
807 dst[5] = (arrtype)_pd_scale_( PD_LT(buf[8], buf[5], buf[2] )); \
808 } \
809 } \
810 } \
811 } \
812 else \
813 { \
814 for( ; rows--; dst += dst_step, buf += Wn ) \
815 { \
816 if( channels == 1 ) \
817 { \
818 /* left part of the bottom row */ \
819 dst[0] = (arrtype)_pd_scale_( PD_LT( buf[0], buf[1], buf[2] )); \
820 \
821 /* middle part of the bottom row */ \
822 for( i = 1; i < Wd_; i++ ) \
823 { \
824 dst[i] = (arrtype)_pd_scale_( PD_FILTER(buf[i*2-2], buf[i*2-1], \
825 buf[i*2],buf[i*2+1], buf[i*2+2] )); \
826 } \
827 \
828 /* right part of the bottom row */ \
829 if( !(W & 1) ) \
830 dst[i] = (arrtype)_pd_scale_( PD_RB( buf[i*2-2],buf[i*2-1], \
831 buf[i*2], buf[i*2+1] )); \
832 else if( cols > 1 ) \
833 dst[i] = (arrtype)_pd_scale_( PD_LT( buf[i*2-2], \
834 buf[i*2-1], buf[i*2] )); \
835 } \
836 else \
837 { \
838 /* left part of the bottom row */ \
839 dst[0] = (arrtype)_pd_scale_( PD_LT( buf[0], buf[3], buf[6] )); \
840 dst[1] = (arrtype)_pd_scale_( PD_LT( buf[1], buf[4], buf[7] )); \
841 dst[2] = (arrtype)_pd_scale_( PD_LT( buf[2], buf[5], buf[8] )); \
842 \
843 /* middle part of the bottom row */ \
844 for( i = 3; i < Wd_*3; i++ ) \
845 { \
846 dst[i] = (arrtype)_pd_scale_( PD_FILTER(buf[i*2-6], buf[i*2-3], \
847 buf[i*2],buf[i*2+3], buf[i*2+6]));\
848 } \
849 \
850 /* right part of the bottom row */ \
851 if( !(W & 1) ) \
852 { \
853 dst[i] = (arrtype)_pd_scale_( PD_RB( buf[i*2-6],buf[i*2-3], \
854 buf[i*2], buf[i*2+3] )); \
855 dst[i+1] = (arrtype)_pd_scale_( PD_RB( buf[i*2-5],buf[i*2-2], \
856 buf[i*2+1], buf[i*2+4] )); \
857 dst[i+2] = (arrtype)_pd_scale_( PD_RB( buf[i*2-4],buf[i*2-1], \
858 buf[i*2+2], buf[i*2+5] )); \
859 } \
860 else if( cols > 1 ) \
861 { \
862 dst[i] = (arrtype)_pd_scale_( PD_LT( buf[i*2-6], buf[i*2-3], buf[i*2] )); \
863 dst[i+1] = (arrtype)_pd_scale_( PD_LT( buf[i*2-5], buf[i*2-2], buf[i*2+1]));\
864 dst[i+2] = (arrtype)_pd_scale_( PD_LT( buf[i*2-4], buf[i*2-1], buf[i*2+2]));\
865 } \
866 } \
867 } \
868 } \
869 } \
870 \
871 if( !local_alloc ) \
872 cvFree( &buf0 ); \
873 \
874 return CV_OK; \
875 }
876
877
878 #define ICV_DEF_INIT_PYR_TABLE( FUNCNAME ) \
879 static void icvInit##FUNCNAME##Table( CvFuncTable* tab ) \
880 { \
881 tab->fn_2d[CV_8U] = (void*)icv##FUNCNAME##_8u_CnR; \
882 tab->fn_2d[CV_8S] = 0; \
883 tab->fn_2d[CV_16S] = (void*)icv##FUNCNAME##_16s_CnR; \
884 tab->fn_2d[CV_16U] = (void*)icv##FUNCNAME##_16u_CnR; \
885 tab->fn_2d[CV_32F] = (void*)icv##FUNCNAME##_32f_CnR; \
886 tab->fn_2d[CV_64F] = (void*)icv##FUNCNAME##_64f_CnR; \
887 }
888
889 static void icvInitPyrDownBorderTable( CvFuncTable* tab );
890
891 ICV_DEF_INIT_PYR_TABLE( PyrUpG5x5 )
892 ICV_DEF_INIT_PYR_TABLE( PyrDownG5x5 )
893
894 typedef CvStatus (CV_STDCALL * CvPyrDownBorderFunc)( const void* src, int srcstep,
895 CvSize srcsize, void* dst,
896 int dststep, CvSize dstsize, int cn );
897
898 ////////////////////////////// IPP pyramid functions /////////////////////////////////////
899
900 icvPyrDown_Gauss5x5_8u_C1R_t icvPyrDown_Gauss5x5_8u_C1R_p = 0;
901 icvPyrDown_Gauss5x5_8u_C3R_t icvPyrDown_Gauss5x5_8u_C3R_p = 0;
902 icvPyrDown_Gauss5x5_32f_C1R_t icvPyrDown_Gauss5x5_32f_C1R_p = 0;
903 icvPyrDown_Gauss5x5_32f_C3R_t icvPyrDown_Gauss5x5_32f_C3R_p = 0;
904
905 icvPyrUp_Gauss5x5_8u_C1R_t icvPyrUp_Gauss5x5_8u_C1R_p = 0;
906 icvPyrUp_Gauss5x5_8u_C3R_t icvPyrUp_Gauss5x5_8u_C3R_p = 0;
907 icvPyrUp_Gauss5x5_32f_C1R_t icvPyrUp_Gauss5x5_32f_C1R_p = 0;
908 icvPyrUp_Gauss5x5_32f_C3R_t icvPyrUp_Gauss5x5_32f_C3R_p = 0;
909
910 icvPyrUpGetBufSize_Gauss5x5_t icvPyrUpGetBufSize_Gauss5x5_p = 0;
911 icvPyrDownGetBufSize_Gauss5x5_t icvPyrDownGetBufSize_Gauss5x5_p = 0;
912
913 typedef CvStatus (CV_STDCALL * CvPyramidFunc)
914 ( const void* src, int srcstep, void* dst,
915 int dststep, CvSize size, void* buffer, int cn );
916
917 typedef CvStatus (CV_STDCALL * CvPyramidIPPFunc)
918 ( const void* src, int srcstep, void* dst, int dststep, CvSize size, void* buffer );
919
920 //////////////////////////////////////////////////////////////////////////////////////////
921
922 /****************************************************************************************\
923 * External functions *
924 \****************************************************************************************/
925
926 CV_IMPL void
cvPyrUp(const void * srcarr,void * dstarr,int _filter)927 cvPyrUp( const void* srcarr, void* dstarr, int _filter )
928 {
929 static CvFuncTable pyrup_tab;
930 static int inittab = 0;
931
932 void *buffer = 0;
933 int local_alloc = 0;
934
935 CV_FUNCNAME( "cvPyrUp" );
936
937 __BEGIN__;
938
939 int coi1 = 0, coi2 = 0;
940 int buffer_size = 0;
941 int type, depth, cn;
942 CvMat srcstub, *src = (CvMat*)srcarr;
943 CvMat dststub, *dst = (CvMat*)dstarr;
944 CvFilter filter = (CvFilter) _filter;
945 CvPyramidFunc func;
946 CvPyramidIPPFunc ipp_func = 0;
947 int use_ipp = 0;
948 CvSize size;
949
950 if( !inittab )
951 {
952 icvInitPyrUpG5x5Table( &pyrup_tab );
953 inittab = 1;
954 }
955
956 CV_CALL( src = cvGetMat( src, &srcstub, &coi1 ));
957 CV_CALL( dst = cvGetMat( dst, &dststub, &coi2 ));
958
959 if( coi1 != 0 || coi2 != 0 )
960 CV_ERROR( CV_BadCOI, "" );
961
962 if( filter != CV_GAUSSIAN_5x5 )
963 CV_ERROR( CV_StsBadArg, "this filter type not supported" );
964
965 if( !CV_ARE_TYPES_EQ( src, dst ))
966 CV_ERROR( CV_StsUnmatchedFormats, "" );
967
968 if( src->cols*2 != dst->cols || src->rows*2 != dst->rows )
969 CV_ERROR( CV_StsUnmatchedSizes, "" );
970
971 size = cvGetMatSize(src);
972 type = CV_MAT_TYPE(src->type);
973 depth = CV_MAT_DEPTH(type);
974 cn = CV_MAT_CN(type);
975
976 if( cn != 1 && cn != 3 )
977 CV_ERROR( CV_StsUnsupportedFormat, "The images must have 1 or 3 channel" );
978
979 func = (CvPyramidFunc)pyrup_tab.fn_2d[depth];
980
981 if( !func )
982 CV_ERROR( CV_StsUnsupportedFormat, "" );
983
984 if( icvPyrUpGetBufSize_Gauss5x5_p )
985 {
986 ipp_func = type == CV_8UC1 ? icvPyrUp_Gauss5x5_8u_C1R_p :
987 type == CV_8UC3 ? icvPyrUp_Gauss5x5_8u_C3R_p :
988 type == CV_32FC1 ? icvPyrUp_Gauss5x5_32f_C1R_p :
989 type == CV_32FC3 ? icvPyrUp_Gauss5x5_32f_C3R_p : 0;
990
991 use_ipp = ipp_func && icvPyrUpGetBufSize_Gauss5x5_p( size.width,
992 icvDepthToDataType(type), cn, &buffer_size ) >= 0;
993 }
994
995 if( !use_ipp )
996 icvPyrUpG5x5_GetBufSize( size.width, icvDepthToDataType(type), cn, &buffer_size );
997
998 if( buffer_size <= CV_MAX_LOCAL_SIZE )
999 {
1000 buffer = cvStackAlloc( buffer_size );
1001 local_alloc = 1;
1002 }
1003 else
1004 CV_CALL( buffer = cvAlloc( buffer_size ));
1005
1006 if( !use_ipp )
1007 func( src->data.ptr, src->step, dst->data.ptr, dst->step, size, buffer, cn );
1008 else
1009 IPPI_CALL( ipp_func( src->data.ptr, src->step ? src->step : CV_STUB_STEP,
1010 dst->data.ptr, dst->step ? dst->step : CV_STUB_STEP, size, buffer ));
1011 __END__;
1012
1013 if( buffer && !local_alloc )
1014 cvFree( &buffer );
1015 }
1016
1017
1018 CV_IMPL void
cvPyrDown(const void * srcarr,void * dstarr,int _filter)1019 cvPyrDown( const void* srcarr, void* dstarr, int _filter )
1020 {
1021 static CvFuncTable pyrdown_tab;
1022 static CvFuncTable pyrdownborder_tab;
1023 static int inittab = 0;
1024
1025 void *buffer = 0;
1026 int local_alloc = 0;
1027
1028 CV_FUNCNAME( "cvPyrDown" );
1029
1030 __BEGIN__;
1031
1032 int coi1 = 0, coi2 = 0;
1033 int buffer_size = 0;
1034 int type, depth, cn;
1035 CvMat srcstub, *src = (CvMat*)srcarr;
1036 CvMat dststub, *dst = (CvMat*)dstarr;
1037 CvFilter filter = (CvFilter) _filter;
1038 CvPyramidFunc func;
1039 CvPyramidIPPFunc ipp_func = 0;
1040 int use_ipp = 0;
1041 CvSize src_size, src_size2, dst_size;
1042
1043 if( !inittab )
1044 {
1045 icvInitPyrDownG5x5Table( &pyrdown_tab );
1046 icvInitPyrDownBorderTable( &pyrdownborder_tab );
1047 inittab = 1;
1048 }
1049
1050 CV_CALL( src = cvGetMat( src, &srcstub, &coi1 ));
1051 CV_CALL( dst = cvGetMat( dst, &dststub, &coi2 ));
1052
1053 if( coi1 != 0 || coi2 != 0 )
1054 CV_ERROR( CV_BadCOI, "" );
1055
1056 if( filter != CV_GAUSSIAN_5x5 )
1057 CV_ERROR( CV_StsBadArg, "this filter type not supported" );
1058
1059 if( !CV_ARE_TYPES_EQ( src, dst ))
1060 CV_ERROR( CV_StsUnmatchedFormats, "" );
1061
1062 src_size = cvGetMatSize(src);
1063 dst_size = cvGetMatSize(dst);
1064 src_size2.width = src_size.width & -2;
1065 src_size2.height = src_size.height & -2;
1066
1067 if( (unsigned)(dst_size.width - src_size.width/2) > 1 ||
1068 (unsigned)(dst_size.height - src_size.height/2) > 1 )
1069 CV_ERROR( CV_StsUnmatchedSizes, "" );
1070
1071 // current restriction of PyrDownBorder*
1072 if( (src_size.width <= 2 && dst_size.width != 1) ||
1073 (src_size.height <= 2 && dst_size.height != 1) )
1074 CV_ERROR( CV_StsUnmatchedSizes, "" );
1075
1076 /*if( src->data.ptr == dst->data.ptr )
1077 CV_ERROR( CV_StsInplaceNotSupported, "" );*/
1078
1079 type = CV_MAT_TYPE(src->type);
1080 depth = CV_MAT_DEPTH(type);
1081 cn = CV_MAT_CN(type);
1082
1083 if( cn != 1 && cn != 3 )
1084 CV_ERROR( CV_StsUnsupportedFormat, "The images must have 1 or 3 channel" );
1085
1086 func = (CvPyramidFunc)pyrdown_tab.fn_2d[depth];
1087
1088 if( !func )
1089 CV_ERROR( CV_StsUnsupportedFormat, "" );
1090
1091 if( icvPyrDownGetBufSize_Gauss5x5_p )
1092 {
1093 ipp_func = type == CV_8UC1 ? icvPyrDown_Gauss5x5_8u_C1R_p :
1094 type == CV_8UC3 ? icvPyrDown_Gauss5x5_8u_C3R_p :
1095 type == CV_32FC1 ? icvPyrDown_Gauss5x5_32f_C1R_p :
1096 type == CV_32FC3 ? icvPyrDown_Gauss5x5_32f_C3R_p : 0;
1097
1098 use_ipp = ipp_func && icvPyrDownGetBufSize_Gauss5x5_p( src_size2.width,
1099 icvDepthToDataType(type), cn, &buffer_size ) >= 0;
1100 }
1101
1102 if( !use_ipp )
1103 icvPyrDownG5x5_GetBufSize( src_size2.width,
1104 icvDepthToDataType(type), cn, &buffer_size );
1105
1106 if( buffer_size <= CV_MAX_LOCAL_SIZE )
1107 {
1108 buffer = cvStackAlloc( buffer_size );
1109 local_alloc = 1;
1110 }
1111 else
1112 CV_CALL( buffer = cvAlloc( buffer_size ));
1113
1114 if( !use_ipp )
1115 func( src->data.ptr, src->step, dst->data.ptr,
1116 dst->step, src_size2, buffer, cn );
1117 else
1118 IPPI_CALL( ipp_func( src->data.ptr, src->step ? src->step : CV_STUB_STEP,
1119 dst->data.ptr, dst->step ? dst->step : CV_STUB_STEP, src_size2, buffer ));
1120
1121 if( src_size.width != dst_size.width*2 || src_size.height != dst_size.height*2 )
1122 {
1123 CvPyrDownBorderFunc border_func = (CvPyrDownBorderFunc)
1124 pyrdownborder_tab.fn_2d[CV_MAT_DEPTH(type)];
1125
1126 if( !border_func )
1127 CV_ERROR( CV_StsUnsupportedFormat, "" );
1128
1129 IPPI_CALL( border_func( src->data.ptr, src->step, src_size,
1130 dst->data.ptr, dst->step, dst_size, CV_MAT_CN(type) ));
1131 }
1132
1133 __END__;
1134
1135 if( buffer && !local_alloc )
1136 cvFree( &buffer );
1137 }
1138
1139
1140 CV_IMPL void
cvReleasePyramid(CvMat *** _pyramid,int extra_layers)1141 cvReleasePyramid( CvMat*** _pyramid, int extra_layers )
1142 {
1143 CV_FUNCNAME( "cvReleasePyramid" );
1144
1145 __BEGIN__;
1146
1147 CvMat** pyramid;
1148 int i;
1149
1150 if( !_pyramid )
1151 CV_ERROR( CV_StsNullPtr, "" );
1152
1153 pyramid = *_pyramid;
1154
1155 if( pyramid )
1156 {
1157 for( i = 0; i <= extra_layers; i++ )
1158 cvReleaseMat( &pyramid[i] );
1159 }
1160
1161 cvFree( _pyramid );
1162
1163 __END__;
1164 }
1165
1166
1167 CV_IMPL CvMat**
cvCreatePyramid(const CvArr * srcarr,int extra_layers,double rate,const CvSize * layer_sizes,CvArr * bufarr,int calc,int filter)1168 cvCreatePyramid( const CvArr* srcarr, int extra_layers, double rate,
1169 const CvSize* layer_sizes, CvArr* bufarr,
1170 int calc, int filter )
1171 {
1172 CvMat** pyramid = 0;
1173 const float eps = 0.1f;
1174
1175 CV_FUNCNAME( "cvCreatePyramid" );
1176
1177 __BEGIN__;
1178
1179 int i, elem_size, layer_step;
1180 CvMat stub, *src;
1181 CvSize size, layer_size;
1182 uchar* ptr = 0;
1183
1184 CV_CALL( src = cvGetMat( srcarr, &stub ));
1185
1186 if( extra_layers < 0 )
1187 CV_ERROR( CV_StsOutOfRange, "The number of extra layers must be non negative" );
1188
1189 elem_size = CV_ELEM_SIZE(src->type);
1190 size = cvGetMatSize(src);
1191
1192 if( bufarr )
1193 {
1194 CvMat bstub, *buf;
1195 int bufsize = 0;
1196
1197 CV_CALL( buf = cvGetMat( bufarr, &bstub ));
1198 bufsize = buf->rows*buf->cols*CV_ELEM_SIZE(buf->type);
1199 layer_size = size;
1200 for( i = 1; i <= extra_layers; i++ )
1201 {
1202 if( !layer_sizes )
1203 {
1204 layer_size.width = cvRound(layer_size.width*rate+eps);
1205 layer_size.height = cvRound(layer_size.height*rate+eps);
1206 }
1207 else
1208 layer_size = layer_sizes[i-1];
1209 layer_step = layer_size.width*elem_size;
1210 bufsize -= layer_step*layer_size.height;
1211 }
1212
1213 if( bufsize < 0 )
1214 CV_ERROR( CV_StsOutOfRange, "The buffer is too small to fit the pyramid" );
1215 ptr = buf->data.ptr;
1216 }
1217
1218 CV_CALL( pyramid = (CvMat**)cvAlloc( (extra_layers+1)*sizeof(pyramid[0]) ));
1219 memset( pyramid, 0, (extra_layers+1)*sizeof(pyramid[0]) );
1220
1221 pyramid[0] = cvCreateMatHeader( size.height, size.width, src->type );
1222 cvSetData( pyramid[0], src->data.ptr, src->step );
1223 layer_size = size;
1224
1225 for( i = 1; i <= extra_layers; i++ )
1226 {
1227 if( !layer_sizes )
1228 {
1229 layer_size.width = cvRound(layer_size.width*rate + eps);
1230 layer_size.height = cvRound(layer_size.height*rate + eps);
1231 }
1232 else
1233 layer_size = layer_sizes[i];
1234
1235 if( bufarr )
1236 {
1237 pyramid[i] = cvCreateMatHeader( layer_size.height, layer_size.width, src->type );
1238 layer_step = layer_size.width*elem_size;
1239 cvSetData( pyramid[i], ptr, layer_step );
1240 ptr += layer_step*layer_size.height;
1241 }
1242 else
1243 pyramid[i] = cvCreateMat( layer_size.height, layer_size.width, src->type );
1244
1245 if( calc )
1246 cvPyrDown( pyramid[i-1], pyramid[i], filter );
1247 //cvResize( pyramid[i-1], pyramid[i], CV_INTER_LINEAR );
1248 }
1249
1250 __END__;
1251
1252 if( cvGetErrStatus() < 0 )
1253 cvReleasePyramid( &pyramid, extra_layers );
1254
1255 return pyramid;
1256 }
1257
1258
1259 /* MSVC .NET 2003 spends a long time building this, thus, as the code
1260 is not performance-critical, we turn off the optimization here */
1261 #if defined _MSC_VER && _MSC_VER > 1300 && !defined CV_ICC
1262 #pragma optimize("", off)
1263 #endif
1264
1265 ICV_DEF_PYR_BORDER_FUNC( 8u, uchar, int, PD_SCALE_INT )
1266 ICV_DEF_PYR_BORDER_FUNC( 16u, ushort, int, PD_SCALE_INT )
1267 ICV_DEF_PYR_BORDER_FUNC( 16s, short, int, PD_SCALE_INT )
1268 ICV_DEF_PYR_BORDER_FUNC( 32f, float, float, PD_SCALE_FLT )
1269 ICV_DEF_PYR_BORDER_FUNC( 64f, double, double, PD_SCALE_FLT )
1270
1271 #define ICV_DEF_INIT_PYR_BORDER_TABLE( FUNCNAME ) \
1272 static void icvInit##FUNCNAME##Table( CvFuncTable* tab ) \
1273 { \
1274 tab->fn_2d[CV_8U] = (void*)icv##FUNCNAME##_8u_CnR; \
1275 tab->fn_2d[CV_8S] = 0; \
1276 tab->fn_2d[CV_16U] = (void*)icv##FUNCNAME##_16u_CnR; \
1277 tab->fn_2d[CV_16S] = (void*)icv##FUNCNAME##_16s_CnR; \
1278 tab->fn_2d[CV_32F] = (void*)icv##FUNCNAME##_32f_CnR; \
1279 tab->fn_2d[CV_64F] = (void*)icv##FUNCNAME##_64f_CnR; \
1280 }
1281
1282 ICV_DEF_INIT_PYR_BORDER_TABLE( PyrDownBorder )
1283
1284 /* End of file. */
1285