1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
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.
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.
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.
44 typedef struct CvFFillSegment
58 #define ICV_PUSH( Y, L, R, PREV_L, PREV_R, DIR )\
60 tail->y = (ushort)(Y); \
61 tail->l = (ushort)(L); \
62 tail->r = (ushort)(R); \
63 tail->prevl = (ushort)(PREV_L); \
64 tail->prevr = (ushort)(PREV_R); \
65 tail->dir = (short)(DIR); \
66 if( ++tail >= buffer_end ) \
71 #define ICV_POP( Y, L, R, PREV_L, PREV_R, DIR ) \
76 PREV_L = head->prevl; \
77 PREV_R = head->prevr; \
79 if( ++head >= buffer_end ) \
84 #define ICV_EQ_C3( p1, p2 ) \
85 ((p1)[0] == (p2)[0] && (p1)[1] == (p2)[1] && (p1)[2] == (p2)[2])
87 #define ICV_SET_C3( p, q ) \
88 ((p)[0] = (q)[0], (p)[1] = (q)[1], (p)[2] = (q)[2])
90 /****************************************************************************************\
91 * Simple Floodfill (repainting single-color connected component) *
92 \****************************************************************************************/
95 icvFloodFill_8u_CnIR( uchar* pImage, int step, CvSize roi, CvPoint seed,
96 uchar* _newVal, CvConnectedComp* region, int flags,
97 CvFFillSegment* buffer, int buffer_size, int cn )
99 uchar* img = pImage + step * seed.y;
102 int val0[] = {0,0,0};
103 uchar newVal[] = {0,0,0};
104 int XMin, XMax, YMin = seed.y, YMax = seed.y;
105 int _8_connectivity = (flags & 255) == 8;
106 CvFFillSegment* buffer_end = buffer + buffer_size, *head = buffer, *tail = buffer;
108 L = R = XMin = XMax = seed.x;
113 newVal[0] = _newVal[0];
117 while( ++R < roi.width && img[R] == val0[0] )
120 while( --L >= 0 && img[L] == val0[0] )
126 ICV_SET_C3( val0, img + L*3 );
127 ICV_SET_C3( newVal, _newVal );
129 ICV_SET_C3( img + L*3, newVal );
131 while( --L >= 0 && ICV_EQ_C3( img + L*3, val0 ))
132 ICV_SET_C3( img + L*3, newVal );
134 while( ++R < roi.width && ICV_EQ_C3( img + R*3, val0 ))
135 ICV_SET_C3( img + R*3, newVal );
140 ICV_PUSH( seed.y, L, R, R + 1, R, UP );
142 while( head != tail )
144 int k, YC, PL, PR, dir;
145 ICV_POP( YC, L, R, PL, PR, dir );
149 {-dir, L - _8_connectivity, R + _8_connectivity},
150 {dir, L - _8_connectivity, PL - 1},
151 {dir, PR + 1, R + _8_connectivity}
158 if( XMax < R ) XMax = R;
159 if( XMin > L ) XMin = L;
160 if( YMax < YC ) YMax = YC;
161 if( YMin > YC ) YMin = YC;
164 for( k = 0/*(unsigned)(YC - dir) >= (unsigned)roi.height*/; k < 3; k++ )
167 img = pImage + (YC + dir) * step;
168 int left = data[k][1];
169 int right = data[k][2];
171 if( (unsigned)(YC + dir) >= (unsigned)roi.height )
175 for( i = left; i <= right; i++ )
177 if( (unsigned)i < (unsigned)roi.width && img[i] == val0[0] )
181 while( --j >= 0 && img[j] == val0[0] )
184 while( ++i < roi.width && img[i] == val0[0] )
187 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
191 for( i = left; i <= right; i++ )
193 if( (unsigned)i < (unsigned)roi.width && ICV_EQ_C3( img + i*3, val0 ))
196 ICV_SET_C3( img + i*3, newVal );
197 while( --j >= 0 && ICV_EQ_C3( img + j*3, val0 ))
198 ICV_SET_C3( img + j*3, newVal );
200 while( ++i < roi.width && ICV_EQ_C3( img + i*3, val0 ))
201 ICV_SET_C3( img + i*3, newVal );
203 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
212 region->rect.x = XMin;
213 region->rect.y = YMin;
214 region->rect.width = XMax - XMin + 1;
215 region->rect.height = YMax - YMin + 1;
216 region->value = cvScalar(newVal[0], newVal[1], newVal[2], 0);
223 /* because all the operations on floats that are done during non-gradient floodfill
224 are just copying and comparison on equality,
225 we can do the whole op on 32-bit integers instead */
227 icvFloodFill_32f_CnIR( int* pImage, int step, CvSize roi, CvPoint seed,
228 int* _newVal, CvConnectedComp* region, int flags,
229 CvFFillSegment* buffer, int buffer_size, int cn )
231 int* img = pImage + (step /= sizeof(pImage[0])) * seed.y;
234 int val0[] = {0,0,0};
235 int newVal[] = {0,0,0};
236 int XMin, XMax, YMin = seed.y, YMax = seed.y;
237 int _8_connectivity = (flags & 255) == 8;
238 CvFFillSegment* buffer_end = buffer + buffer_size, *head = buffer, *tail = buffer;
240 L = R = XMin = XMax = seed.x;
245 newVal[0] = _newVal[0];
249 while( ++R < roi.width && img[R] == val0[0] )
252 while( --L >= 0 && img[L] == val0[0] )
258 ICV_SET_C3( val0, img + L*3 );
259 ICV_SET_C3( newVal, _newVal );
261 ICV_SET_C3( img + L*3, newVal );
263 while( --L >= 0 && ICV_EQ_C3( img + L*3, val0 ))
264 ICV_SET_C3( img + L*3, newVal );
266 while( ++R < roi.width && ICV_EQ_C3( img + R*3, val0 ))
267 ICV_SET_C3( img + R*3, newVal );
272 ICV_PUSH( seed.y, L, R, R + 1, R, UP );
274 while( head != tail )
276 int k, YC, PL, PR, dir;
277 ICV_POP( YC, L, R, PL, PR, dir );
281 {-dir, L - _8_connectivity, R + _8_connectivity},
282 {dir, L - _8_connectivity, PL - 1},
283 {dir, PR + 1, R + _8_connectivity}
290 if( XMax < R ) XMax = R;
291 if( XMin > L ) XMin = L;
292 if( YMax < YC ) YMax = YC;
293 if( YMin > YC ) YMin = YC;
296 for( k = 0/*(unsigned)(YC - dir) >= (unsigned)roi.height*/; k < 3; k++ )
299 img = pImage + (YC + dir) * step;
300 int left = data[k][1];
301 int right = data[k][2];
303 if( (unsigned)(YC + dir) >= (unsigned)roi.height )
307 for( i = left; i <= right; i++ )
309 if( (unsigned)i < (unsigned)roi.width && img[i] == val0[0] )
313 while( --j >= 0 && img[j] == val0[0] )
316 while( ++i < roi.width && img[i] == val0[0] )
319 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
323 for( i = left; i <= right; i++ )
325 if( (unsigned)i < (unsigned)roi.width && ICV_EQ_C3( img + i*3, val0 ))
328 ICV_SET_C3( img + i*3, newVal );
329 while( --j >= 0 && ICV_EQ_C3( img + j*3, val0 ))
330 ICV_SET_C3( img + j*3, newVal );
332 while( ++i < roi.width && ICV_EQ_C3( img + i*3, val0 ))
333 ICV_SET_C3( img + i*3, newVal );
335 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
345 region->rect.x = XMin;
346 region->rect.y = YMin;
347 region->rect.width = XMax - XMin + 1;
348 region->rect.height = YMax - YMin + 1;
349 v0.i = newVal[0]; v1.i = newVal[1]; v2.i = newVal[2];
350 region->value = cvScalar( v0.f, v1.f, v2.f );
356 /****************************************************************************************\
357 * Gradient Floodfill *
358 \****************************************************************************************/
360 #define DIFF_INT_C1(p1,p2) ((unsigned)((p1)[0] - (p2)[0] + d_lw[0]) <= interval[0])
362 #define DIFF_INT_C3(p1,p2) ((unsigned)((p1)[0] - (p2)[0] + d_lw[0])<= interval[0] && \
363 (unsigned)((p1)[1] - (p2)[1] + d_lw[1])<= interval[1] && \
364 (unsigned)((p1)[2] - (p2)[2] + d_lw[2])<= interval[2])
366 #define DIFF_FLT_C1(p1,p2) (fabs((p1)[0] - (p2)[0] + d_lw[0]) <= interval[0])
368 #define DIFF_FLT_C3(p1,p2) (fabs((p1)[0] - (p2)[0] + d_lw[0]) <= interval[0] && \
369 fabs((p1)[1] - (p2)[1] + d_lw[1]) <= interval[1] && \
370 fabs((p1)[2] - (p2)[2] + d_lw[2]) <= interval[2])
373 icvFloodFill_Grad_8u_CnIR( uchar* pImage, int step, uchar* pMask, int maskStep,
374 CvSize /*roi*/, CvPoint seed, uchar* _newVal, uchar* _d_lw,
375 uchar* _d_up, CvConnectedComp* region, int flags,
376 CvFFillSegment* buffer, int buffer_size, int cn )
378 uchar* img = pImage + step*seed.y;
379 uchar* mask = (pMask += maskStep + 1) + maskStep*seed.y;
382 int sum[] = {0,0,0}, val0[] = {0,0,0};
383 uchar newVal[] = {0,0,0};
384 int d_lw[] = {0,0,0};
385 unsigned interval[] = {0,0,0};
386 int XMin, XMax, YMin = seed.y, YMax = seed.y;
387 int _8_connectivity = (flags & 255) == 8;
388 int fixedRange = flags & CV_FLOODFILL_FIXED_RANGE;
389 int fillImage = (flags & CV_FLOODFILL_MASK_ONLY) == 0;
390 uchar newMaskVal = (uchar)(flags & 0xff00 ? flags >> 8 : 1);
391 CvFFillSegment* buffer_end = buffer + buffer_size, *head = buffer, *tail = buffer;
397 mask[L] = newMaskVal;
399 for( i = 0; i < cn; i++ )
401 newVal[i] = _newVal[i];
403 interval[i] = (unsigned)(_d_up[i] + _d_lw[i]);
405 val0[i] = img[L*cn+i];
412 while( !mask[R + 1] && DIFF_INT_C1( img + (R+1), val0 ))
413 mask[++R] = newMaskVal;
415 while( !mask[L - 1] && DIFF_INT_C1( img + (L-1), val0 ))
416 mask[--L] = newMaskVal;
420 while( !mask[R + 1] && DIFF_INT_C1( img + (R+1), img + R ))
421 mask[++R] = newMaskVal;
423 while( !mask[L - 1] && DIFF_INT_C1( img + (L-1), img + L ))
424 mask[--L] = newMaskVal;
431 while( !mask[R + 1] && DIFF_INT_C3( img + (R+1)*3, val0 ))
432 mask[++R] = newMaskVal;
434 while( !mask[L - 1] && DIFF_INT_C3( img + (L-1)*3, val0 ))
435 mask[--L] = newMaskVal;
439 while( !mask[R + 1] && DIFF_INT_C3( img + (R+1)*3, img + R*3 ))
440 mask[++R] = newMaskVal;
442 while( !mask[L - 1] && DIFF_INT_C3( img + (L-1)*3, img + L*3 ))
443 mask[--L] = newMaskVal;
449 ICV_PUSH( seed.y, L, R, R + 1, R, UP );
451 while( head != tail )
453 int k, YC, PL, PR, dir, curstep;
454 ICV_POP( YC, L, R, PL, PR, dir );
458 {-dir, L - _8_connectivity, R + _8_connectivity},
459 {dir, L - _8_connectivity, PL - 1},
460 {dir, PR + 1, R + _8_connectivity}
463 unsigned length = (unsigned)(R-L);
467 area += (int)length + 1;
469 if( XMax < R ) XMax = R;
470 if( XMin > L ) XMin = L;
471 if( YMax < YC ) YMax = YC;
472 if( YMin > YC ) YMin = YC;
477 for( k = 0; k < 3; k++ )
480 curstep = dir * step;
481 img = pImage + (YC + dir) * step;
482 mask = pMask + (YC + dir) * maskStep;
483 int left = data[k][1];
484 int right = data[k][2];
487 for( i = left; i <= right; i++ )
489 if( !mask[i] && DIFF_INT_C1( img + i, val0 ))
492 mask[i] = newMaskVal;
493 while( !mask[--j] && DIFF_INT_C1( img + j, val0 ))
494 mask[j] = newMaskVal;
496 while( !mask[++i] && DIFF_INT_C1( img + i, val0 ))
497 mask[i] = newMaskVal;
499 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
502 else if( !_8_connectivity )
503 for( i = left; i <= right; i++ )
505 if( !mask[i] && DIFF_INT_C1( img + i, img - curstep + i ))
508 mask[i] = newMaskVal;
509 while( !mask[--j] && DIFF_INT_C1( img + j, img + (j+1) ))
510 mask[j] = newMaskVal;
513 (DIFF_INT_C1( img + i, img + (i-1) ) ||
514 (DIFF_INT_C1( img + i, img + i - curstep) && i <= R)))
515 mask[i] = newMaskVal;
517 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
521 for( i = left; i <= right; i++ )
527 (unsigned)(idx = i-L-1) <= length) &&
528 DIFF_INT_C1( val, img - curstep + (i-1) ) ||
529 (unsigned)(++idx) <= length &&
530 DIFF_INT_C1( val, img - curstep + i ) ||
531 (unsigned)(++idx) <= length &&
532 DIFF_INT_C1( val, img - curstep + (i+1) )))
535 mask[i] = newMaskVal;
536 while( !mask[--j] && DIFF_INT_C1( img + j, img + (j+1) ))
537 mask[j] = newMaskVal;
541 DIFF_INT_C1( val, img + (i-1) )) ||
542 ((unsigned)(idx = i-L-1) <= length &&
543 DIFF_INT_C1( val, img - curstep + (i-1) )) ||
544 (unsigned)(++idx) <= length &&
545 DIFF_INT_C1( val, img - curstep + i ) ||
546 (unsigned)(++idx) <= length &&
547 DIFF_INT_C1( val, img - curstep + (i+1) )))
548 mask[i] = newMaskVal;
550 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
555 img = pImage + YC * step;
557 for( i = L; i <= R; i++ )
560 for( i = L; i <= R; i++ )
565 for( k = 0; k < 3; k++ )
568 curstep = dir * step;
569 img = pImage + (YC + dir) * step;
570 mask = pMask + (YC + dir) * maskStep;
571 int left = data[k][1];
572 int right = data[k][2];
575 for( i = left; i <= right; i++ )
577 if( !mask[i] && DIFF_INT_C3( img + i*3, val0 ))
580 mask[i] = newMaskVal;
581 while( !mask[--j] && DIFF_INT_C3( img + j*3, val0 ))
582 mask[j] = newMaskVal;
584 while( !mask[++i] && DIFF_INT_C3( img + i*3, val0 ))
585 mask[i] = newMaskVal;
587 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
590 else if( !_8_connectivity )
591 for( i = left; i <= right; i++ )
593 if( !mask[i] && DIFF_INT_C3( img + i*3, img - curstep + i*3 ))
596 mask[i] = newMaskVal;
597 while( !mask[--j] && DIFF_INT_C3( img + j*3, img + (j+1)*3 ))
598 mask[j] = newMaskVal;
601 (DIFF_INT_C3( img + i*3, img + (i-1)*3 ) ||
602 (DIFF_INT_C3( img + i*3, img + i*3 - curstep) && i <= R)))
603 mask[i] = newMaskVal;
605 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
609 for( i = left; i <= right; i++ )
614 ((ICV_SET_C3( val, img+i*3 ),
615 (unsigned)(idx = i-L-1) <= length) &&
616 DIFF_INT_C3( val, img - curstep + (i-1)*3 ) ||
617 (unsigned)(++idx) <= length &&
618 DIFF_INT_C3( val, img - curstep + i*3 ) ||
619 (unsigned)(++idx) <= length &&
620 DIFF_INT_C3( val, img - curstep + (i+1)*3 )))
623 mask[i] = newMaskVal;
624 while( !mask[--j] && DIFF_INT_C3( img + j*3, img + (j+1)*3 ))
625 mask[j] = newMaskVal;
628 ((ICV_SET_C3( val, img + i*3 ),
629 DIFF_INT_C3( val, img + (i-1)*3 )) ||
630 ((unsigned)(idx = i-L-1) <= length &&
631 DIFF_INT_C3( val, img - curstep + (i-1)*3 )) ||
632 (unsigned)(++idx) <= length &&
633 DIFF_INT_C3( val, img - curstep + i*3 ) ||
634 (unsigned)(++idx) <= length &&
635 DIFF_INT_C3( val, img - curstep + (i+1)*3 )))
636 mask[i] = newMaskVal;
638 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
643 img = pImage + YC * step;
645 for( i = L; i <= R; i++ )
646 ICV_SET_C3( img + i*3, newVal );
648 for( i = L; i <= R; i++ )
651 sum[1] += img[i*3+1];
652 sum[2] += img[i*3+2];
660 region->rect.x = XMin;
661 region->rect.y = YMin;
662 region->rect.width = XMax - XMin + 1;
663 region->rect.height = YMax - YMin + 1;
666 region->value = cvScalar(newVal[0], newVal[1], newVal[2]);
669 double iarea = area ? 1./area : 0;
670 region->value = cvScalar(sum[0]*iarea, sum[1]*iarea, sum[2]*iarea);
679 icvFloodFill_Grad_32f_CnIR( float* pImage, int step, uchar* pMask, int maskStep,
680 CvSize /*roi*/, CvPoint seed, float* _newVal, float* _d_lw,
681 float* _d_up, CvConnectedComp* region, int flags,
682 CvFFillSegment* buffer, int buffer_size, int cn )
684 float* img = pImage + (step /= sizeof(float))*seed.y;
685 uchar* mask = (pMask += maskStep + 1) + maskStep*seed.y;
688 double sum[] = {0,0,0}, val0[] = {0,0,0};
689 float newVal[] = {0,0,0};
690 float d_lw[] = {0,0,0};
691 float interval[] = {0,0,0};
692 int XMin, XMax, YMin = seed.y, YMax = seed.y;
693 int _8_connectivity = (flags & 255) == 8;
694 int fixedRange = flags & CV_FLOODFILL_FIXED_RANGE;
695 int fillImage = (flags & CV_FLOODFILL_MASK_ONLY) == 0;
696 uchar newMaskVal = (uchar)(flags & 0xff00 ? flags >> 8 : 1);
697 CvFFillSegment* buffer_end = buffer + buffer_size, *head = buffer, *tail = buffer;
703 mask[L] = newMaskVal;
705 for( i = 0; i < cn; i++ )
707 newVal[i] = _newVal[i];
708 d_lw[i] = 0.5f*(_d_lw[i] - _d_up[i]);
709 interval[i] = 0.5f*(_d_lw[i] + _d_up[i]);
711 val0[i] = img[L*cn+i];
718 while( !mask[R + 1] && DIFF_FLT_C1( img + (R+1), val0 ))
719 mask[++R] = newMaskVal;
721 while( !mask[L - 1] && DIFF_FLT_C1( img + (L-1), val0 ))
722 mask[--L] = newMaskVal;
726 while( !mask[R + 1] && DIFF_FLT_C1( img + (R+1), img + R ))
727 mask[++R] = newMaskVal;
729 while( !mask[L - 1] && DIFF_FLT_C1( img + (L-1), img + L ))
730 mask[--L] = newMaskVal;
737 while( !mask[R + 1] && DIFF_FLT_C3( img + (R+1)*3, val0 ))
738 mask[++R] = newMaskVal;
740 while( !mask[L - 1] && DIFF_FLT_C3( img + (L-1)*3, val0 ))
741 mask[--L] = newMaskVal;
745 while( !mask[R + 1] && DIFF_FLT_C3( img + (R+1)*3, img + R*3 ))
746 mask[++R] = newMaskVal;
748 while( !mask[L - 1] && DIFF_FLT_C3( img + (L-1)*3, img + L*3 ))
749 mask[--L] = newMaskVal;
755 ICV_PUSH( seed.y, L, R, R + 1, R, UP );
757 while( head != tail )
759 int k, YC, PL, PR, dir, curstep;
760 ICV_POP( YC, L, R, PL, PR, dir );
764 {-dir, L - _8_connectivity, R + _8_connectivity},
765 {dir, L - _8_connectivity, PL - 1},
766 {dir, PR + 1, R + _8_connectivity}
769 unsigned length = (unsigned)(R-L);
773 area += (int)length + 1;
775 if( XMax < R ) XMax = R;
776 if( XMin > L ) XMin = L;
777 if( YMax < YC ) YMax = YC;
778 if( YMin > YC ) YMin = YC;
783 for( k = 0; k < 3; k++ )
786 curstep = dir * step;
787 img = pImage + (YC + dir) * step;
788 mask = pMask + (YC + dir) * maskStep;
789 int left = data[k][1];
790 int right = data[k][2];
793 for( i = left; i <= right; i++ )
795 if( !mask[i] && DIFF_FLT_C1( img + i, val0 ))
798 mask[i] = newMaskVal;
799 while( !mask[--j] && DIFF_FLT_C1( img + j, val0 ))
800 mask[j] = newMaskVal;
802 while( !mask[++i] && DIFF_FLT_C1( img + i, val0 ))
803 mask[i] = newMaskVal;
805 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
808 else if( !_8_connectivity )
809 for( i = left; i <= right; i++ )
811 if( !mask[i] && DIFF_FLT_C1( img + i, img - curstep + i ))
814 mask[i] = newMaskVal;
815 while( !mask[--j] && DIFF_FLT_C1( img + j, img + (j+1) ))
816 mask[j] = newMaskVal;
819 (DIFF_FLT_C1( img + i, img + (i-1) ) ||
820 (DIFF_FLT_C1( img + i, img + i - curstep) && i <= R)))
821 mask[i] = newMaskVal;
823 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
827 for( i = left; i <= right; i++ )
834 (unsigned)(idx = i-L-1) <= length) &&
835 DIFF_FLT_C1( val, img - curstep + (i-1) ) ||
836 (unsigned)(++idx) <= length &&
837 DIFF_FLT_C1( val, img - curstep + i ) ||
838 (unsigned)(++idx) <= length &&
839 DIFF_FLT_C1( val, img - curstep + (i+1) )))
842 mask[i] = newMaskVal;
843 while( !mask[--j] && DIFF_FLT_C1( img + j, img + (j+1) ))
844 mask[j] = newMaskVal;
848 DIFF_FLT_C1( val, img + (i-1) )) ||
849 ((unsigned)(idx = i-L-1) <= length &&
850 DIFF_FLT_C1( val, img - curstep + (i-1) )) ||
851 (unsigned)(++idx) <= length &&
852 DIFF_FLT_C1( val, img - curstep + i ) ||
853 (unsigned)(++idx) <= length &&
854 DIFF_FLT_C1( val, img - curstep + (i+1) )))
855 mask[i] = newMaskVal;
857 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
862 img = pImage + YC * step;
864 for( i = L; i <= R; i++ )
867 for( i = L; i <= R; i++ )
872 for( k = 0; k < 3; k++ )
875 curstep = dir * step;
876 img = pImage + (YC + dir) * step;
877 mask = pMask + (YC + dir) * maskStep;
878 int left = data[k][1];
879 int right = data[k][2];
882 for( i = left; i <= right; i++ )
884 if( !mask[i] && DIFF_FLT_C3( img + i*3, val0 ))
887 mask[i] = newMaskVal;
888 while( !mask[--j] && DIFF_FLT_C3( img + j*3, val0 ))
889 mask[j] = newMaskVal;
891 while( !mask[++i] && DIFF_FLT_C3( img + i*3, val0 ))
892 mask[i] = newMaskVal;
894 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
897 else if( !_8_connectivity )
898 for( i = left; i <= right; i++ )
900 if( !mask[i] && DIFF_FLT_C3( img + i*3, img - curstep + i*3 ))
903 mask[i] = newMaskVal;
904 while( !mask[--j] && DIFF_FLT_C3( img + j*3, img + (j+1)*3 ))
905 mask[j] = newMaskVal;
908 (DIFF_FLT_C3( img + i*3, img + (i-1)*3 ) ||
909 (DIFF_FLT_C3( img + i*3, img + i*3 - curstep) && i <= R)))
910 mask[i] = newMaskVal;
912 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
916 for( i = left; i <= right; i++ )
922 ((ICV_SET_C3( val, img+i*3 ),
923 (unsigned)(idx = i-L-1) <= length) &&
924 DIFF_FLT_C3( val, img - curstep + (i-1)*3 ) ||
925 (unsigned)(++idx) <= length &&
926 DIFF_FLT_C3( val, img - curstep + i*3 ) ||
927 (unsigned)(++idx) <= length &&
928 DIFF_FLT_C3( val, img - curstep + (i+1)*3 )))
931 mask[i] = newMaskVal;
932 while( !mask[--j] && DIFF_FLT_C3( img + j*3, img + (j+1)*3 ))
933 mask[j] = newMaskVal;
936 ((ICV_SET_C3( val, img + i*3 ),
937 DIFF_FLT_C3( val, img + (i-1)*3 )) ||
938 ((unsigned)(idx = i-L-1) <= length &&
939 DIFF_FLT_C3( val, img - curstep + (i-1)*3 )) ||
940 (unsigned)(++idx) <= length &&
941 DIFF_FLT_C3( val, img - curstep + i*3 ) ||
942 (unsigned)(++idx) <= length &&
943 DIFF_FLT_C3( val, img - curstep + (i+1)*3 )))
944 mask[i] = newMaskVal;
946 ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );
951 img = pImage + YC * step;
953 for( i = L; i <= R; i++ )
954 ICV_SET_C3( img + i*3, newVal );
956 for( i = L; i <= R; i++ )
959 sum[1] += img[i*3+1];
960 sum[2] += img[i*3+2];
968 region->rect.x = XMin;
969 region->rect.y = YMin;
970 region->rect.width = XMax - XMin + 1;
971 region->rect.height = YMax - YMin + 1;
974 region->value = cvScalar(newVal[0], newVal[1], newVal[2]);
977 double iarea = area ? 1./area : 0;
978 region->value = cvScalar(sum[0]*iarea, sum[1]*iarea, sum[2]*iarea);
986 /****************************************************************************************\
987 * External Functions *
988 \****************************************************************************************/
990 typedef CvStatus (CV_CDECL* CvFloodFillFunc)(
991 void* img, int step, CvSize size, CvPoint seed, void* newval,
992 CvConnectedComp* comp, int flags, void* buffer, int buffer_size, int cn );
994 typedef CvStatus (CV_CDECL* CvFloodFillGradFunc)(
995 void* img, int step, uchar* mask, int maskStep, CvSize size,
996 CvPoint seed, void* newval, void* d_lw, void* d_up, void* ccomp,
997 int flags, void* buffer, int buffer_size, int cn );
999 static void icvInitFloodFill( void** ffill_tab,
1000 void** ffillgrad_tab )
1002 ffill_tab[0] = (void*)icvFloodFill_8u_CnIR;
1003 ffill_tab[1] = (void*)icvFloodFill_32f_CnIR;
1005 ffillgrad_tab[0] = (void*)icvFloodFill_Grad_8u_CnIR;
1006 ffillgrad_tab[1] = (void*)icvFloodFill_Grad_32f_CnIR;
1011 cvFloodFill( CvArr* arr, CvPoint seed_point,
1012 CvScalar newVal, CvScalar lo_diff, CvScalar up_diff,
1013 CvConnectedComp* comp, int flags, CvArr* maskarr )
1015 static void* ffill_tab[4];
1016 static void* ffillgrad_tab[4];
1017 static int inittab = 0;
1019 CvMat* tempMask = 0;
1020 CvFFillSegment* buffer = 0;
1021 CV_FUNCNAME( "cvFloodFill" );
1024 memset( comp, 0, sizeof(*comp) );
1028 int i, type, depth, cn, is_simple, idx;
1029 int buffer_size, connectivity = flags & 255;
1030 double nv_buf[4] = {0,0,0,0};
1031 union { uchar b[4]; float f[4]; } ld_buf, ud_buf;
1032 CvMat stub, *img = (CvMat*)arr;
1033 CvMat maskstub, *mask = (CvMat*)maskarr;
1038 icvInitFloodFill( ffill_tab, ffillgrad_tab );
1042 CV_CALL( img = cvGetMat( img, &stub ));
1043 type = CV_MAT_TYPE( img->type );
1044 depth = CV_MAT_DEPTH(type);
1045 cn = CV_MAT_CN(type);
1047 idx = type == CV_8UC1 || type == CV_8UC3 ? 0 :
1048 type == CV_32FC1 || type == CV_32FC3 ? 1 : -1;
1051 CV_ERROR( CV_StsUnsupportedFormat, "" );
1053 if( connectivity == 0 )
1055 else if( connectivity != 4 && connectivity != 8 )
1056 CV_ERROR( CV_StsBadFlag, "Connectivity must be 4, 0(=4) or 8" );
1058 is_simple = mask == 0 && (flags & CV_FLOODFILL_MASK_ONLY) == 0;
1060 for( i = 0; i < cn; i++ )
1062 if( lo_diff.val[i] < 0 || up_diff.val[i] < 0 )
1063 CV_ERROR( CV_StsBadArg, "lo_diff and up_diff must be non-negative" );
1064 is_simple &= fabs(lo_diff.val[i]) < DBL_EPSILON && fabs(up_diff.val[i]) < DBL_EPSILON;
1067 size = cvGetMatSize( img );
1069 if( (unsigned)seed_point.x >= (unsigned)size.width ||
1070 (unsigned)seed_point.y >= (unsigned)size.height )
1071 CV_ERROR( CV_StsOutOfRange, "Seed point is outside of image" );
1073 cvScalarToRawData( &newVal, &nv_buf, type, 0 );
1074 buffer_size = MAX( size.width, size.height )*2;
1075 CV_CALL( buffer = (CvFFillSegment*)cvAlloc( buffer_size*sizeof(buffer[0])));
1079 CvFloodFillFunc func = (CvFloodFillFunc)ffill_tab[idx];
1081 CV_ERROR( CV_StsUnsupportedFormat, "" );
1083 IPPI_CALL( func( img->data.ptr, img->step, size,
1084 seed_point, &nv_buf, comp, flags,
1085 buffer, buffer_size, cn ));
1089 CvFloodFillGradFunc func = (CvFloodFillGradFunc)ffillgrad_tab[idx];
1091 CV_ERROR( CV_StsUnsupportedFormat, "" );
1095 /* created mask will be 8-byte aligned */
1096 tempMask = cvCreateMat( size.height + 2, (size.width + 9) & -8, CV_8UC1 );
1101 CV_CALL( mask = cvGetMat( mask, &maskstub ));
1102 if( !CV_IS_MASK_ARR( mask ))
1103 CV_ERROR( CV_StsBadMask, "" );
1105 if( mask->width != size.width + 2 || mask->height != size.height + 2 )
1106 CV_ERROR( CV_StsUnmatchedSizes, "mask must be 2 pixel wider "
1107 "and 2 pixel taller than filled image" );
1111 int width = tempMask ? mask->step : size.width + 2;
1112 uchar* mask_row = mask->data.ptr + mask->step;
1113 memset( mask_row - mask->step, 1, width );
1115 for( i = 1; i <= size.height; i++, mask_row += mask->step )
1118 memset( mask_row, 0, width );
1119 mask_row[0] = mask_row[size.width+1] = (uchar)1;
1121 memset( mask_row, 1, width );
1124 if( depth == CV_8U )
1125 for( i = 0; i < cn; i++ )
1127 int t = cvFloor(lo_diff.val[i]);
1128 ld_buf.b[i] = CV_CAST_8U(t);
1129 t = cvFloor(up_diff.val[i]);
1130 ud_buf.b[i] = CV_CAST_8U(t);
1133 for( i = 0; i < cn; i++ )
1135 ld_buf.f[i] = (float)lo_diff.val[i];
1136 ud_buf.f[i] = (float)up_diff.val[i];
1139 IPPI_CALL( func( img->data.ptr, img->step, mask->data.ptr, mask->step,
1140 size, seed_point, &nv_buf, ld_buf.f, ud_buf.f,
1141 comp, flags, buffer, buffer_size, cn ));
1147 cvReleaseMat( &tempMask );