Update to 2.0.0 tree from current Fremantle build
[opencv] / src / cv / cvfloodfill.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////\r
2 //\r
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.\r
4 //\r
5 //  By downloading, copying, installing or using the software you agree to this license.\r
6 //  If you do not agree to this license, do not download, install,\r
7 //  copy or use the software.\r
8 //\r
9 //\r
10 //                        Intel License Agreement\r
11 //                For Open Source Computer Vision Library\r
12 //\r
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.\r
14 // Third party copyrights are property of their respective owners.\r
15 //\r
16 // Redistribution and use in source and binary forms, with or without modification,\r
17 // are permitted provided that the following conditions are met:\r
18 //\r
19 //   * Redistribution's of source code must retain the above copyright notice,\r
20 //     this list of conditions and the following disclaimer.\r
21 //\r
22 //   * Redistribution's in binary form must reproduce the above copyright notice,\r
23 //     this list of conditions and the following disclaimer in the documentation\r
24 //     and/or other materials provided with the distribution.\r
25 //\r
26 //   * The name of Intel Corporation may not be used to endorse or promote products\r
27 //     derived from this software without specific prior written permission.\r
28 //\r
29 // This software is provided by the copyright holders and contributors "as is" and\r
30 // any express or implied warranties, including, but not limited to, the implied\r
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.\r
32 // In no event shall the Intel Corporation or contributors be liable for any direct,\r
33 // indirect, incidental, special, exemplary, or consequential damages\r
34 // (including, but not limited to, procurement of substitute goods or services;\r
35 // loss of use, data, or profits; or business interruption) however caused\r
36 // and on any theory of liability, whether in contract, strict liability,\r
37 // or tort (including negligence or otherwise) arising in any way out of\r
38 // the use of this software, even if advised of the possibility of such damage.\r
39 //\r
40 //M*/\r
41 \r
42 #include "_cv.h"\r
43 \r
44 typedef struct CvFFillSegment\r
45 {\r
46     ushort y;\r
47     ushort l;\r
48     ushort r;\r
49     ushort prevl;\r
50     ushort prevr;\r
51     short dir;\r
52 }\r
53 CvFFillSegment;\r
54 \r
55 #define UP 1\r
56 #define DOWN -1\r
57 \r
58 #define ICV_PUSH( Y, L, R, PREV_L, PREV_R, DIR )\\r
59 {                                               \\r
60     tail->y = (ushort)(Y);                      \\r
61     tail->l = (ushort)(L);                      \\r
62     tail->r = (ushort)(R);                      \\r
63     tail->prevl = (ushort)(PREV_L);             \\r
64     tail->prevr = (ushort)(PREV_R);             \\r
65     tail->dir = (short)(DIR);                   \\r
66     if( ++tail >= buffer_end )                  \\r
67         tail = buffer;                          \\r
68 }\r
69 \r
70 \r
71 #define ICV_POP( Y, L, R, PREV_L, PREV_R, DIR ) \\r
72 {                                               \\r
73     Y = head->y;                                \\r
74     L = head->l;                                \\r
75     R = head->r;                                \\r
76     PREV_L = head->prevl;                       \\r
77     PREV_R = head->prevr;                       \\r
78     DIR = head->dir;                            \\r
79     if( ++head >= buffer_end )                  \\r
80         head = buffer;                          \\r
81 }\r
82 \r
83 \r
84 #define ICV_EQ_C3( p1, p2 ) \\r
85     ((p1)[0] == (p2)[0] && (p1)[1] == (p2)[1] && (p1)[2] == (p2)[2])\r
86 \r
87 #define ICV_SET_C3( p, q ) \\r
88     ((p)[0] = (q)[0], (p)[1] = (q)[1], (p)[2] = (q)[2])\r
89 \r
90 /****************************************************************************************\\r
91 *              Simple Floodfill (repainting single-color connected component)            *\r
92 \****************************************************************************************/\r
93 \r
94 static CvStatus\r
95 icvFloodFill_8u_CnIR( uchar* pImage, int step, CvSize roi, CvPoint seed,\r
96                       uchar* _newVal, CvConnectedComp* region, int flags,\r
97                       CvFFillSegment* buffer, int buffer_size, int cn )\r
98 {\r
99     uchar* img = pImage + step * seed.y;\r
100     int i, L, R;\r
101     int area = 0;\r
102     int val0[] = {0,0,0};\r
103     uchar newVal[] = {0,0,0};\r
104     int XMin, XMax, YMin = seed.y, YMax = seed.y;\r
105     int _8_connectivity = (flags & 255) == 8;\r
106     CvFFillSegment* buffer_end = buffer + buffer_size, *head = buffer, *tail = buffer;\r
107 \r
108     L = R = XMin = XMax = seed.x;\r
109 \r
110     if( cn == 1 )\r
111     {\r
112         val0[0] = img[L];\r
113         newVal[0] = _newVal[0];\r
114 \r
115         img[L] = newVal[0];\r
116 \r
117         while( ++R < roi.width && img[R] == val0[0] )\r
118             img[R] = newVal[0];\r
119 \r
120         while( --L >= 0 && img[L] == val0[0] )\r
121             img[L] = newVal[0];\r
122     }\r
123     else\r
124     {\r
125         assert( cn == 3 );\r
126         ICV_SET_C3( val0, img + L*3 );\r
127         ICV_SET_C3( newVal, _newVal );\r
128 \r
129         ICV_SET_C3( img + L*3, newVal );\r
130 \r
131         while( --L >= 0 && ICV_EQ_C3( img + L*3, val0 ))\r
132             ICV_SET_C3( img + L*3, newVal );\r
133 \r
134         while( ++R < roi.width && ICV_EQ_C3( img + R*3, val0 ))\r
135             ICV_SET_C3( img + R*3, newVal );\r
136     }\r
137 \r
138     XMax = --R;\r
139     XMin = ++L;\r
140     ICV_PUSH( seed.y, L, R, R + 1, R, UP );\r
141 \r
142     while( head != tail )\r
143     {\r
144         int k, YC, PL, PR, dir;\r
145         ICV_POP( YC, L, R, PL, PR, dir );\r
146 \r
147         int data[][3] =\r
148         {\r
149             {-dir, L - _8_connectivity, R + _8_connectivity},\r
150             {dir, L - _8_connectivity, PL - 1},\r
151             {dir, PR + 1, R + _8_connectivity}\r
152         };\r
153 \r
154         if( region )\r
155         {\r
156             area += R - L + 1;\r
157 \r
158             if( XMax < R ) XMax = R;\r
159             if( XMin > L ) XMin = L;\r
160             if( YMax < YC ) YMax = YC;\r
161             if( YMin > YC ) YMin = YC;\r
162         }\r
163 \r
164         for( k = 0/*(unsigned)(YC - dir) >= (unsigned)roi.height*/; k < 3; k++ )\r
165         {\r
166             dir = data[k][0];\r
167             img = pImage + (YC + dir) * step;\r
168             int left = data[k][1];\r
169             int right = data[k][2];\r
170 \r
171             if( (unsigned)(YC + dir) >= (unsigned)roi.height )\r
172                 continue;\r
173 \r
174             if( cn == 1 )\r
175                 for( i = left; i <= right; i++ )\r
176                 {\r
177                     if( (unsigned)i < (unsigned)roi.width && img[i] == val0[0] )\r
178                     {\r
179                         int j = i;\r
180                         img[i] = newVal[0];\r
181                         while( --j >= 0 && img[j] == val0[0] )\r
182                             img[j] = newVal[0];\r
183 \r
184                         while( ++i < roi.width && img[i] == val0[0] )\r
185                             img[i] = newVal[0];\r
186 \r
187                         ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );\r
188                     }\r
189                 }\r
190             else\r
191                 for( i = left; i <= right; i++ )\r
192                 {\r
193                     if( (unsigned)i < (unsigned)roi.width && ICV_EQ_C3( img + i*3, val0 ))\r
194                     {\r
195                         int j = i;\r
196                         ICV_SET_C3( img + i*3, newVal );\r
197                         while( --j >= 0 && ICV_EQ_C3( img + j*3, val0 ))\r
198                             ICV_SET_C3( img + j*3, newVal );\r
199 \r
200                         while( ++i < roi.width && ICV_EQ_C3( img + i*3, val0 ))\r
201                             ICV_SET_C3( img + i*3, newVal );\r
202 \r
203                         ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );\r
204                     }\r
205                 }\r
206         }\r
207     }\r
208 \r
209     if( region )\r
210     {\r
211         region->area = area;\r
212         region->rect.x = XMin;\r
213         region->rect.y = YMin;\r
214         region->rect.width = XMax - XMin + 1;\r
215         region->rect.height = YMax - YMin + 1;\r
216         region->value = cvScalar(newVal[0], newVal[1], newVal[2], 0);\r
217     }\r
218 \r
219     return CV_NO_ERR;\r
220 }\r
221 \r
222 \r
223 /* because all the operations on floats that are done during non-gradient floodfill\r
224    are just copying and comparison on equality,\r
225    we can do the whole op on 32-bit integers instead */\r
226 static CvStatus\r
227 icvFloodFill_32f_CnIR( int* pImage, int step, CvSize roi, CvPoint seed,\r
228                        int* _newVal, CvConnectedComp* region, int flags,\r
229                        CvFFillSegment* buffer, int buffer_size, int cn )\r
230 {\r
231     int* img = pImage + (step /= sizeof(pImage[0])) * seed.y;\r
232     int i, L, R;\r
233     int area = 0;\r
234     int val0[] = {0,0,0};\r
235     int newVal[] = {0,0,0};\r
236     int XMin, XMax, YMin = seed.y, YMax = seed.y;\r
237     int _8_connectivity = (flags & 255) == 8;\r
238     CvFFillSegment* buffer_end = buffer + buffer_size, *head = buffer, *tail = buffer;\r
239 \r
240     L = R = XMin = XMax = seed.x;\r
241 \r
242     if( cn == 1 )\r
243     {\r
244         val0[0] = img[L];\r
245         newVal[0] = _newVal[0];\r
246 \r
247         img[L] = newVal[0];\r
248 \r
249         while( ++R < roi.width && img[R] == val0[0] )\r
250             img[R] = newVal[0];\r
251 \r
252         while( --L >= 0 && img[L] == val0[0] )\r
253             img[L] = newVal[0];\r
254     }\r
255     else\r
256     {\r
257         assert( cn == 3 );\r
258         ICV_SET_C3( val0, img + L*3 );\r
259         ICV_SET_C3( newVal, _newVal );\r
260 \r
261         ICV_SET_C3( img + L*3, newVal );\r
262 \r
263         while( --L >= 0 && ICV_EQ_C3( img + L*3, val0 ))\r
264             ICV_SET_C3( img + L*3, newVal );\r
265 \r
266         while( ++R < roi.width && ICV_EQ_C3( img + R*3, val0 ))\r
267             ICV_SET_C3( img + R*3, newVal );\r
268     }\r
269 \r
270     XMax = --R;\r
271     XMin = ++L;\r
272     ICV_PUSH( seed.y, L, R, R + 1, R, UP );\r
273 \r
274     while( head != tail )\r
275     {\r
276         int k, YC, PL, PR, dir;\r
277         ICV_POP( YC, L, R, PL, PR, dir );\r
278 \r
279         int data[][3] =\r
280         {\r
281             {-dir, L - _8_connectivity, R + _8_connectivity},\r
282             {dir, L - _8_connectivity, PL - 1},\r
283             {dir, PR + 1, R + _8_connectivity}\r
284         };\r
285 \r
286         if( region )\r
287         {\r
288             area += R - L + 1;\r
289 \r
290             if( XMax < R ) XMax = R;\r
291             if( XMin > L ) XMin = L;\r
292             if( YMax < YC ) YMax = YC;\r
293             if( YMin > YC ) YMin = YC;\r
294         }\r
295 \r
296         for( k = 0/*(unsigned)(YC - dir) >= (unsigned)roi.height*/; k < 3; k++ )\r
297         {\r
298             dir = data[k][0];\r
299             img = pImage + (YC + dir) * step;\r
300             int left = data[k][1];\r
301             int right = data[k][2];\r
302 \r
303             if( (unsigned)(YC + dir) >= (unsigned)roi.height )\r
304                 continue;\r
305 \r
306             if( cn == 1 )\r
307                 for( i = left; i <= right; i++ )\r
308                 {\r
309                     if( (unsigned)i < (unsigned)roi.width && img[i] == val0[0] )\r
310                     {\r
311                         int j = i;\r
312                         img[i] = newVal[0];\r
313                         while( --j >= 0 && img[j] == val0[0] )\r
314                             img[j] = newVal[0];\r
315 \r
316                         while( ++i < roi.width && img[i] == val0[0] )\r
317                             img[i] = newVal[0];\r
318 \r
319                         ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );\r
320                     }\r
321                 }\r
322             else\r
323                 for( i = left; i <= right; i++ )\r
324                 {\r
325                     if( (unsigned)i < (unsigned)roi.width && ICV_EQ_C3( img + i*3, val0 ))\r
326                     {\r
327                         int j = i;\r
328                         ICV_SET_C3( img + i*3, newVal );\r
329                         while( --j >= 0 && ICV_EQ_C3( img + j*3, val0 ))\r
330                             ICV_SET_C3( img + j*3, newVal );\r
331 \r
332                         while( ++i < roi.width && ICV_EQ_C3( img + i*3, val0 ))\r
333                             ICV_SET_C3( img + i*3, newVal );\r
334 \r
335                         ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );\r
336                     }\r
337                 }\r
338         }\r
339     }\r
340 \r
341     if( region )\r
342     {\r
343         Cv32suf v0, v1, v2;\r
344         region->area = area;\r
345         region->rect.x = XMin;\r
346         region->rect.y = YMin;\r
347         region->rect.width = XMax - XMin + 1;\r
348         region->rect.height = YMax - YMin + 1;\r
349         v0.i = newVal[0]; v1.i = newVal[1]; v2.i = newVal[2];\r
350         region->value = cvScalar( v0.f, v1.f, v2.f );\r
351     }\r
352 \r
353     return CV_NO_ERR;\r
354 }\r
355 \r
356 /****************************************************************************************\\r
357 *                                   Gradient Floodfill                                   *\r
358 \****************************************************************************************/\r
359 \r
360 #define DIFF_INT_C1(p1,p2) ((unsigned)((p1)[0] - (p2)[0] + d_lw[0]) <= interval[0])\r
361 \r
362 #define DIFF_INT_C3(p1,p2) ((unsigned)((p1)[0] - (p2)[0] + d_lw[0])<= interval[0] && \\r
363                             (unsigned)((p1)[1] - (p2)[1] + d_lw[1])<= interval[1] && \\r
364                             (unsigned)((p1)[2] - (p2)[2] + d_lw[2])<= interval[2])\r
365 \r
366 #define DIFF_FLT_C1(p1,p2) (fabs((p1)[0] - (p2)[0] + d_lw[0]) <= interval[0])\r
367 \r
368 #define DIFF_FLT_C3(p1,p2) (fabs((p1)[0] - (p2)[0] + d_lw[0]) <= interval[0] && \\r
369                             fabs((p1)[1] - (p2)[1] + d_lw[1]) <= interval[1] && \\r
370                             fabs((p1)[2] - (p2)[2] + d_lw[2]) <= interval[2])\r
371 \r
372 static CvStatus\r
373 icvFloodFill_Grad_8u_CnIR( uchar* pImage, int step, uchar* pMask, int maskStep,\r
374                            CvSize /*roi*/, CvPoint seed, uchar* _newVal, uchar* _d_lw,\r
375                            uchar* _d_up, CvConnectedComp* region, int flags,\r
376                            CvFFillSegment* buffer, int buffer_size, int cn )\r
377 {\r
378     uchar* img = pImage + step*seed.y;\r
379     uchar* mask = (pMask += maskStep + 1) + maskStep*seed.y;\r
380     int i, L, R;\r
381     int area = 0;\r
382     int sum[] = {0,0,0}, val0[] = {0,0,0};\r
383     uchar newVal[] = {0,0,0};\r
384     int d_lw[] = {0,0,0};\r
385     unsigned interval[] = {0,0,0};\r
386     int XMin, XMax, YMin = seed.y, YMax = seed.y;\r
387     int _8_connectivity = (flags & 255) == 8;\r
388     int fixedRange = flags & CV_FLOODFILL_FIXED_RANGE;\r
389     int fillImage = (flags & CV_FLOODFILL_MASK_ONLY) == 0;\r
390     uchar newMaskVal = (uchar)(flags & 0xff00 ? flags >> 8 : 1);\r
391     CvFFillSegment* buffer_end = buffer + buffer_size, *head = buffer, *tail = buffer;\r
392 \r
393     L = R = seed.x;\r
394     if( mask[L] )\r
395         return CV_OK;\r
396 \r
397     mask[L] = newMaskVal;\r
398 \r
399     for( i = 0; i < cn; i++ )\r
400     {\r
401         newVal[i] = _newVal[i];\r
402         d_lw[i] = _d_lw[i];\r
403         interval[i] = (unsigned)(_d_up[i] + _d_lw[i]);\r
404         if( fixedRange )\r
405             val0[i] = img[L*cn+i];\r
406     }\r
407 \r
408     if( cn == 1 )\r
409     {\r
410         if( fixedRange )\r
411         {\r
412             while( !mask[R + 1] && DIFF_INT_C1( img + (R+1), val0 ))\r
413                 mask[++R] = newMaskVal;\r
414 \r
415             while( !mask[L - 1] && DIFF_INT_C1( img + (L-1), val0 ))\r
416                 mask[--L] = newMaskVal;\r
417         }\r
418         else\r
419         {\r
420             while( !mask[R + 1] && DIFF_INT_C1( img + (R+1), img + R ))\r
421                 mask[++R] = newMaskVal;\r
422 \r
423             while( !mask[L - 1] && DIFF_INT_C1( img + (L-1), img + L ))\r
424                 mask[--L] = newMaskVal;\r
425         }\r
426     }\r
427     else\r
428     {\r
429         if( fixedRange )\r
430         {\r
431             while( !mask[R + 1] && DIFF_INT_C3( img + (R+1)*3, val0 ))\r
432                 mask[++R] = newMaskVal;\r
433 \r
434             while( !mask[L - 1] && DIFF_INT_C3( img + (L-1)*3, val0 ))\r
435                 mask[--L] = newMaskVal;\r
436         }\r
437         else\r
438         {\r
439             while( !mask[R + 1] && DIFF_INT_C3( img + (R+1)*3, img + R*3 ))\r
440                 mask[++R] = newMaskVal;\r
441 \r
442             while( !mask[L - 1] && DIFF_INT_C3( img + (L-1)*3, img + L*3 ))\r
443                 mask[--L] = newMaskVal;\r
444         }\r
445     }\r
446 \r
447     XMax = R;\r
448     XMin = L;\r
449     ICV_PUSH( seed.y, L, R, R + 1, R, UP );\r
450 \r
451     while( head != tail )\r
452     {\r
453         int k, YC, PL, PR, dir, curstep;\r
454         ICV_POP( YC, L, R, PL, PR, dir );\r
455 \r
456         int data[][3] =\r
457         {\r
458             {-dir, L - _8_connectivity, R + _8_connectivity},\r
459             {dir, L - _8_connectivity, PL - 1},\r
460             {dir, PR + 1, R + _8_connectivity}\r
461         };\r
462 \r
463         unsigned length = (unsigned)(R-L);\r
464 \r
465         if( region )\r
466         {\r
467             area += (int)length + 1;\r
468 \r
469             if( XMax < R ) XMax = R;\r
470             if( XMin > L ) XMin = L;\r
471             if( YMax < YC ) YMax = YC;\r
472             if( YMin > YC ) YMin = YC;\r
473         }\r
474 \r
475         if( cn == 1 )\r
476         {\r
477             for( k = 0; k < 3; k++ )\r
478             {\r
479                 dir = data[k][0];\r
480                 curstep = dir * step;\r
481                 img = pImage + (YC + dir) * step;\r
482                 mask = pMask + (YC + dir) * maskStep;\r
483                 int left = data[k][1];\r
484                 int right = data[k][2];\r
485 \r
486                 if( fixedRange )\r
487                     for( i = left; i <= right; i++ )\r
488                     {\r
489                         if( !mask[i] && DIFF_INT_C1( img + i, val0 ))\r
490                         {\r
491                             int j = i;\r
492                             mask[i] = newMaskVal;\r
493                             while( !mask[--j] && DIFF_INT_C1( img + j, val0 ))\r
494                                 mask[j] = newMaskVal;\r
495 \r
496                             while( !mask[++i] && DIFF_INT_C1( img + i, val0 ))\r
497                                 mask[i] = newMaskVal;\r
498 \r
499                             ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );\r
500                         }\r
501                     }\r
502                 else if( !_8_connectivity )\r
503                     for( i = left; i <= right; i++ )\r
504                     {\r
505                         if( !mask[i] && DIFF_INT_C1( img + i, img - curstep + i ))\r
506                         {\r
507                             int j = i;\r
508                             mask[i] = newMaskVal;\r
509                             while( !mask[--j] && DIFF_INT_C1( img + j, img + (j+1) ))\r
510                                 mask[j] = newMaskVal;\r
511 \r
512                             while( !mask[++i] &&\r
513                                    (DIFF_INT_C1( img + i, img + (i-1) ) ||\r
514                                    (DIFF_INT_C1( img + i, img + i - curstep) && i <= R)))\r
515                                 mask[i] = newMaskVal;\r
516 \r
517                             ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );\r
518                         }\r
519                     }\r
520                 else\r
521                     for( i = left; i <= right; i++ )\r
522                     {\r
523                         int idx, val[1];\r
524 \r
525                         if( !mask[i] &&\r
526                             (((val[0] = img[i],\r
527                             (unsigned)(idx = i-L-1) <= length) &&\r
528                             DIFF_INT_C1( val, img - curstep + (i-1))) ||\r
529                             ((unsigned)(++idx) <= length &&\r
530                             DIFF_INT_C1( val, img - curstep + i )) ||\r
531                             ((unsigned)(++idx) <= length &&\r
532                             DIFF_INT_C1( val, img - curstep + (i+1) ))))\r
533                         {\r
534                             int j = i;\r
535                             mask[i] = newMaskVal;\r
536                             while( !mask[--j] && DIFF_INT_C1( img + j, img + (j+1) ))\r
537                                 mask[j] = newMaskVal;\r
538 \r
539                             while( !mask[++i] &&\r
540                                    ((val[0] = img[i],\r
541                                    DIFF_INT_C1( val, img + (i-1) )) ||\r
542                                    (((unsigned)(idx = i-L-1) <= length &&\r
543                                    DIFF_INT_C1( val, img - curstep + (i-1) ))) ||\r
544                                    ((unsigned)(++idx) <= length &&\r
545                                    DIFF_INT_C1( val, img - curstep + i )) ||\r
546                                    ((unsigned)(++idx) <= length &&\r
547                                    DIFF_INT_C1( val, img - curstep + (i+1) ))))\r
548                                 mask[i] = newMaskVal;\r
549 \r
550                             ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );\r
551                         }\r
552                     }\r
553             }\r
554 \r
555             img = pImage + YC * step;\r
556             if( fillImage )\r
557                 for( i = L; i <= R; i++ )\r
558                     img[i] = newVal[0];\r
559             else if( region )\r
560                 for( i = L; i <= R; i++ )\r
561                     sum[0] += img[i];\r
562         }\r
563         else\r
564         {\r
565             for( k = 0; k < 3; k++ )\r
566             {\r
567                 dir = data[k][0];\r
568                 curstep = dir * step;\r
569                 img = pImage + (YC + dir) * step;\r
570                 mask = pMask + (YC + dir) * maskStep;\r
571                 int left = data[k][1];\r
572                 int right = data[k][2];\r
573 \r
574                 if( fixedRange )\r
575                     for( i = left; i <= right; i++ )\r
576                     {\r
577                         if( !mask[i] && DIFF_INT_C3( img + i*3, val0 ))\r
578                         {\r
579                             int j = i;\r
580                             mask[i] = newMaskVal;\r
581                             while( !mask[--j] && DIFF_INT_C3( img + j*3, val0 ))\r
582                                 mask[j] = newMaskVal;\r
583 \r
584                             while( !mask[++i] && DIFF_INT_C3( img + i*3, val0 ))\r
585                                 mask[i] = newMaskVal;\r
586 \r
587                             ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );\r
588                         }\r
589                     }\r
590                 else if( !_8_connectivity )\r
591                     for( i = left; i <= right; i++ )\r
592                     {\r
593                         if( !mask[i] && DIFF_INT_C3( img + i*3, img - curstep + i*3 ))\r
594                         {\r
595                             int j = i;\r
596                             mask[i] = newMaskVal;\r
597                             while( !mask[--j] && DIFF_INT_C3( img + j*3, img + (j+1)*3 ))\r
598                                 mask[j] = newMaskVal;\r
599 \r
600                             while( !mask[++i] &&\r
601                                    (DIFF_INT_C3( img + i*3, img + (i-1)*3 ) ||\r
602                                    (DIFF_INT_C3( img + i*3, img + i*3 - curstep) && i <= R)))\r
603                                 mask[i] = newMaskVal;\r
604 \r
605                             ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );\r
606                         }\r
607                     }\r
608                 else\r
609                     for( i = left; i <= right; i++ )\r
610                     {\r
611                         int idx, val[3];\r
612 \r
613                         if( !mask[i] &&\r
614                             (((ICV_SET_C3( val, img+i*3 ),\r
615                             (unsigned)(idx = i-L-1) <= length) &&\r
616                             DIFF_INT_C3( val, img - curstep + (i-1)*3 )) ||\r
617                             ((unsigned)(++idx) <= length &&\r
618                             DIFF_INT_C3( val, img - curstep + i*3 )) ||\r
619                             ((unsigned)(++idx) <= length &&\r
620                             DIFF_INT_C3( val, img - curstep + (i+1)*3 ))))\r
621                         {\r
622                             int j = i;\r
623                             mask[i] = newMaskVal;\r
624                             while( !mask[--j] && DIFF_INT_C3( img + j*3, img + (j+1)*3 ))\r
625                                 mask[j] = newMaskVal;\r
626 \r
627                             while( !mask[++i] &&\r
628                                    ((ICV_SET_C3( val, img + i*3 ),\r
629                                    DIFF_INT_C3( val, img + (i-1)*3 )) ||\r
630                                    (((unsigned)(idx = i-L-1) <= length &&\r
631                                    DIFF_INT_C3( val, img - curstep + (i-1)*3 ))) ||\r
632                                    ((unsigned)(++idx) <= length &&\r
633                                    DIFF_INT_C3( val, img - curstep + i*3 )) ||\r
634                                    ((unsigned)(++idx) <= length &&\r
635                                    DIFF_INT_C3( val, img - curstep + (i+1)*3 ))))\r
636                                 mask[i] = newMaskVal;\r
637 \r
638                             ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );\r
639                         }\r
640                     }\r
641             }\r
642 \r
643             img = pImage + YC * step;\r
644             if( fillImage )\r
645                 for( i = L; i <= R; i++ )\r
646                     ICV_SET_C3( img + i*3, newVal );\r
647             else if( region )\r
648                 for( i = L; i <= R; i++ )\r
649                 {\r
650                     sum[0] += img[i*3];\r
651                     sum[1] += img[i*3+1];\r
652                     sum[2] += img[i*3+2];\r
653                 }\r
654         }\r
655     }\r
656 \r
657     if( region )\r
658     {\r
659         region->area = area;\r
660         region->rect.x = XMin;\r
661         region->rect.y = YMin;\r
662         region->rect.width = XMax - XMin + 1;\r
663         region->rect.height = YMax - YMin + 1;\r
664 \r
665         if( fillImage )\r
666             region->value = cvScalar(newVal[0], newVal[1], newVal[2]);\r
667         else\r
668         {\r
669             double iarea = area ? 1./area : 0;\r
670             region->value = cvScalar(sum[0]*iarea, sum[1]*iarea, sum[2]*iarea);\r
671         }\r
672     }\r
673 \r
674     return CV_NO_ERR;\r
675 }\r
676 \r
677 \r
678 static CvStatus\r
679 icvFloodFill_Grad_32f_CnIR( float* pImage, int step, uchar* pMask, int maskStep,\r
680                            CvSize /*roi*/, CvPoint seed, float* _newVal, float* _d_lw,\r
681                            float* _d_up, CvConnectedComp* region, int flags,\r
682                            CvFFillSegment* buffer, int buffer_size, int cn )\r
683 {\r
684     float* img = pImage + (step /= sizeof(float))*seed.y;\r
685     uchar* mask = (pMask += maskStep + 1) + maskStep*seed.y;\r
686     int i, L, R;\r
687     int area = 0;\r
688     double sum[] = {0,0,0}, val0[] = {0,0,0};\r
689     float newVal[] = {0,0,0};\r
690     float d_lw[] = {0,0,0};\r
691     float interval[] = {0,0,0};\r
692     int XMin, XMax, YMin = seed.y, YMax = seed.y;\r
693     int _8_connectivity = (flags & 255) == 8;\r
694     int fixedRange = flags & CV_FLOODFILL_FIXED_RANGE;\r
695     int fillImage = (flags & CV_FLOODFILL_MASK_ONLY) == 0;\r
696     uchar newMaskVal = (uchar)(flags & 0xff00 ? flags >> 8 : 1);\r
697     CvFFillSegment* buffer_end = buffer + buffer_size, *head = buffer, *tail = buffer;\r
698 \r
699     L = R = seed.x;\r
700     if( mask[L] )\r
701         return CV_OK;\r
702 \r
703     mask[L] = newMaskVal;\r
704 \r
705     for( i = 0; i < cn; i++ )\r
706     {\r
707         newVal[i] = _newVal[i];\r
708         d_lw[i] = 0.5f*(_d_lw[i] - _d_up[i]);\r
709         interval[i] = 0.5f*(_d_lw[i] + _d_up[i]);\r
710         if( fixedRange )\r
711             val0[i] = img[L*cn+i];\r
712     }\r
713 \r
714     if( cn == 1 )\r
715     {\r
716         if( fixedRange )\r
717         {\r
718             while( !mask[R + 1] && DIFF_FLT_C1( img + (R+1), val0 ))\r
719                 mask[++R] = newMaskVal;\r
720 \r
721             while( !mask[L - 1] && DIFF_FLT_C1( img + (L-1), val0 ))\r
722                 mask[--L] = newMaskVal;\r
723         }\r
724         else\r
725         {\r
726             while( !mask[R + 1] && DIFF_FLT_C1( img + (R+1), img + R ))\r
727                 mask[++R] = newMaskVal;\r
728 \r
729             while( !mask[L - 1] && DIFF_FLT_C1( img + (L-1), img + L ))\r
730                 mask[--L] = newMaskVal;\r
731         }\r
732     }\r
733     else\r
734     {\r
735         if( fixedRange )\r
736         {\r
737             while( !mask[R + 1] && DIFF_FLT_C3( img + (R+1)*3, val0 ))\r
738                 mask[++R] = newMaskVal;\r
739 \r
740             while( !mask[L - 1] && DIFF_FLT_C3( img + (L-1)*3, val0 ))\r
741                 mask[--L] = newMaskVal;\r
742         }\r
743         else\r
744         {\r
745             while( !mask[R + 1] && DIFF_FLT_C3( img + (R+1)*3, img + R*3 ))\r
746                 mask[++R] = newMaskVal;\r
747 \r
748             while( !mask[L - 1] && DIFF_FLT_C3( img + (L-1)*3, img + L*3 ))\r
749                 mask[--L] = newMaskVal;\r
750         }\r
751     }\r
752 \r
753     XMax = R;\r
754     XMin = L;\r
755     ICV_PUSH( seed.y, L, R, R + 1, R, UP );\r
756 \r
757     while( head != tail )\r
758     {\r
759         int k, YC, PL, PR, dir, curstep;\r
760         ICV_POP( YC, L, R, PL, PR, dir );\r
761 \r
762         int data[][3] =\r
763         {\r
764             {-dir, L - _8_connectivity, R + _8_connectivity},\r
765             {dir, L - _8_connectivity, PL - 1},\r
766             {dir, PR + 1, R + _8_connectivity}\r
767         };\r
768 \r
769         unsigned length = (unsigned)(R-L);\r
770 \r
771         if( region )\r
772         {\r
773             area += (int)length + 1;\r
774 \r
775             if( XMax < R ) XMax = R;\r
776             if( XMin > L ) XMin = L;\r
777             if( YMax < YC ) YMax = YC;\r
778             if( YMin > YC ) YMin = YC;\r
779         }\r
780 \r
781         if( cn == 1 )\r
782         {\r
783             for( k = 0; k < 3; k++ )\r
784             {\r
785                 dir = data[k][0];\r
786                 curstep = dir * step;\r
787                 img = pImage + (YC + dir) * step;\r
788                 mask = pMask + (YC + dir) * maskStep;\r
789                 int left = data[k][1];\r
790                 int right = data[k][2];\r
791 \r
792                 if( fixedRange )\r
793                     for( i = left; i <= right; i++ )\r
794                     {\r
795                         if( !mask[i] && DIFF_FLT_C1( img + i, val0 ))\r
796                         {\r
797                             int j = i;\r
798                             mask[i] = newMaskVal;\r
799                             while( !mask[--j] && DIFF_FLT_C1( img + j, val0 ))\r
800                                 mask[j] = newMaskVal;\r
801 \r
802                             while( !mask[++i] && DIFF_FLT_C1( img + i, val0 ))\r
803                                 mask[i] = newMaskVal;\r
804 \r
805                             ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );\r
806                         }\r
807                     }\r
808                 else if( !_8_connectivity )\r
809                     for( i = left; i <= right; i++ )\r
810                     {\r
811                         if( !mask[i] && DIFF_FLT_C1( img + i, img - curstep + i ))\r
812                         {\r
813                             int j = i;\r
814                             mask[i] = newMaskVal;\r
815                             while( !mask[--j] && DIFF_FLT_C1( img + j, img + (j+1) ))\r
816                                 mask[j] = newMaskVal;\r
817 \r
818                             while( !mask[++i] &&\r
819                                    (DIFF_FLT_C1( img + i, img + (i-1) ) ||\r
820                                    (DIFF_FLT_C1( img + i, img + i - curstep) && i <= R)))\r
821                                 mask[i] = newMaskVal;\r
822 \r
823                             ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );\r
824                         }\r
825                     }\r
826                 else\r
827                     for( i = left; i <= right; i++ )\r
828                     {\r
829                         int idx;\r
830                         float val[1];\r
831 \r
832                         if( !mask[i] &&\r
833                             (((val[0] = img[i],\r
834                             (unsigned)(idx = i-L-1) <= length) &&\r
835                             DIFF_FLT_C1( val, img - curstep + (i-1) )) ||\r
836                             ((unsigned)(++idx) <= length &&\r
837                             DIFF_FLT_C1( val, img - curstep + i )) ||\r
838                             ((unsigned)(++idx) <= length &&\r
839                             DIFF_FLT_C1( val, img - curstep + (i+1) ))))\r
840                         {\r
841                             int j = i;\r
842                             mask[i] = newMaskVal;\r
843                             while( !mask[--j] && DIFF_FLT_C1( img + j, img + (j+1) ))\r
844                                 mask[j] = newMaskVal;\r
845 \r
846                             while( !mask[++i] &&\r
847                                    ((val[0] = img[i],\r
848                                    DIFF_FLT_C1( val, img + (i-1) )) ||\r
849                                    (((unsigned)(idx = i-L-1) <= length &&\r
850                                    DIFF_FLT_C1( val, img - curstep + (i-1) ))) ||\r
851                                    ((unsigned)(++idx) <= length &&\r
852                                    DIFF_FLT_C1( val, img - curstep + i )) ||\r
853                                    ((unsigned)(++idx) <= length &&\r
854                                    DIFF_FLT_C1( val, img - curstep + (i+1) ))))\r
855                                 mask[i] = newMaskVal;\r
856 \r
857                             ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );\r
858                         }\r
859                     }\r
860             }\r
861 \r
862             img = pImage + YC * step;\r
863             if( fillImage )\r
864                 for( i = L; i <= R; i++ )\r
865                     img[i] = newVal[0];\r
866             else if( region )\r
867                 for( i = L; i <= R; i++ )\r
868                     sum[0] += img[i];\r
869         }\r
870         else\r
871         {\r
872             for( k = 0; k < 3; k++ )\r
873             {\r
874                 dir = data[k][0];\r
875                 curstep = dir * step;\r
876                 img = pImage + (YC + dir) * step;\r
877                 mask = pMask + (YC + dir) * maskStep;\r
878                 int left = data[k][1];\r
879                 int right = data[k][2];\r
880 \r
881                 if( fixedRange )\r
882                     for( i = left; i <= right; i++ )\r
883                     {\r
884                         if( !mask[i] && DIFF_FLT_C3( img + i*3, val0 ))\r
885                         {\r
886                             int j = i;\r
887                             mask[i] = newMaskVal;\r
888                             while( !mask[--j] && DIFF_FLT_C3( img + j*3, val0 ))\r
889                                 mask[j] = newMaskVal;\r
890 \r
891                             while( !mask[++i] && DIFF_FLT_C3( img + i*3, val0 ))\r
892                                 mask[i] = newMaskVal;\r
893 \r
894                             ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );\r
895                         }\r
896                     }\r
897                 else if( !_8_connectivity )\r
898                     for( i = left; i <= right; i++ )\r
899                     {\r
900                         if( !mask[i] && DIFF_FLT_C3( img + i*3, img - curstep + i*3 ))\r
901                         {\r
902                             int j = i;\r
903                             mask[i] = newMaskVal;\r
904                             while( !mask[--j] && DIFF_FLT_C3( img + j*3, img + (j+1)*3 ))\r
905                                 mask[j] = newMaskVal;\r
906 \r
907                             while( !mask[++i] &&\r
908                                    (DIFF_FLT_C3( img + i*3, img + (i-1)*3 ) ||\r
909                                    (DIFF_FLT_C3( img + i*3, img + i*3 - curstep) && i <= R)))\r
910                                 mask[i] = newMaskVal;\r
911 \r
912                             ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );\r
913                         }\r
914                     }\r
915                 else\r
916                     for( i = left; i <= right; i++ )\r
917                     {\r
918                         int idx;\r
919                         float val[3];\r
920 \r
921                         if( !mask[i] &&\r
922                             (((ICV_SET_C3( val, img+i*3 ),\r
923                             (unsigned)(idx = i-L-1) <= length) &&\r
924                             DIFF_FLT_C3( val, img - curstep + (i-1)*3 )) ||\r
925                             ((unsigned)(++idx) <= length &&\r
926                             DIFF_FLT_C3( val, img - curstep + i*3 )) ||\r
927                             ((unsigned)(++idx) <= length &&\r
928                             DIFF_FLT_C3( val, img - curstep + (i+1)*3 ))))\r
929                         {\r
930                             int j = i;\r
931                             mask[i] = newMaskVal;\r
932                             while( !mask[--j] && DIFF_FLT_C3( img + j*3, img + (j+1)*3 ))\r
933                                 mask[j] = newMaskVal;\r
934 \r
935                             while( !mask[++i] &&\r
936                                    ((ICV_SET_C3( val, img + i*3 ),\r
937                                    DIFF_FLT_C3( val, img + (i-1)*3 )) ||\r
938                                    (((unsigned)(idx = i-L-1) <= length &&\r
939                                    DIFF_FLT_C3( val, img - curstep + (i-1)*3 ))) ||\r
940                                    ((unsigned)(++idx) <= length &&\r
941                                    DIFF_FLT_C3( val, img - curstep + i*3 )) ||\r
942                                    ((unsigned)(++idx) <= length &&\r
943                                    DIFF_FLT_C3( val, img - curstep + (i+1)*3 ))))\r
944                                 mask[i] = newMaskVal;\r
945 \r
946                             ICV_PUSH( YC + dir, j+1, i-1, L, R, -dir );\r
947                         }\r
948                     }\r
949             }\r
950 \r
951             img = pImage + YC * step;\r
952             if( fillImage )\r
953                 for( i = L; i <= R; i++ )\r
954                     ICV_SET_C3( img + i*3, newVal );\r
955             else if( region )\r
956                 for( i = L; i <= R; i++ )\r
957                 {\r
958                     sum[0] += img[i*3];\r
959                     sum[1] += img[i*3+1];\r
960                     sum[2] += img[i*3+2];\r
961                 }\r
962         }\r
963     }\r
964 \r
965     if( region )\r
966     {\r
967         region->area = area;\r
968         region->rect.x = XMin;\r
969         region->rect.y = YMin;\r
970         region->rect.width = XMax - XMin + 1;\r
971         region->rect.height = YMax - YMin + 1;\r
972 \r
973         if( fillImage )\r
974             region->value = cvScalar(newVal[0], newVal[1], newVal[2]);\r
975         else\r
976         {\r
977             double iarea = area ? 1./area : 0;\r
978             region->value = cvScalar(sum[0]*iarea, sum[1]*iarea, sum[2]*iarea);\r
979         }\r
980     }\r
981 \r
982     return CV_NO_ERR;\r
983 }\r
984 \r
985 \r
986 /****************************************************************************************\\r
987 *                                    External Functions                                  *\r
988 \****************************************************************************************/\r
989 \r
990 typedef  CvStatus (CV_CDECL* CvFloodFillFunc)(\r
991                void* img, int step, CvSize size, CvPoint seed, void* newval,\r
992                CvConnectedComp* comp, int flags, void* buffer, int buffer_size, int cn );\r
993 \r
994 typedef  CvStatus (CV_CDECL* CvFloodFillGradFunc)(\r
995                void* img, int step, uchar* mask, int maskStep, CvSize size,\r
996                CvPoint seed, void* newval, void* d_lw, void* d_up, void* ccomp,\r
997                int flags, void* buffer, int buffer_size, int cn );\r
998 \r
999 static  void  icvInitFloodFill( void** ffill_tab,\r
1000                                 void** ffillgrad_tab )\r
1001 {\r
1002     ffill_tab[0] = (void*)icvFloodFill_8u_CnIR;\r
1003     ffill_tab[1] = (void*)icvFloodFill_32f_CnIR;\r
1004 \r
1005     ffillgrad_tab[0] = (void*)icvFloodFill_Grad_8u_CnIR;\r
1006     ffillgrad_tab[1] = (void*)icvFloodFill_Grad_32f_CnIR;\r
1007 }\r
1008 \r
1009 \r
1010 CV_IMPL void\r
1011 cvFloodFill( CvArr* arr, CvPoint seed_point,\r
1012              CvScalar newVal, CvScalar lo_diff, CvScalar up_diff,\r
1013              CvConnectedComp* comp, int flags, CvArr* maskarr )\r
1014 {\r
1015     static void* ffill_tab[4];\r
1016     static void* ffillgrad_tab[4];\r
1017     static int inittab = 0;\r
1018 \r
1019     CvMat* tempMask = 0;\r
1020     CvFFillSegment* buffer = 0;\r
1021     CV_FUNCNAME( "cvFloodFill" );\r
1022 \r
1023     if( comp )\r
1024         memset( comp, 0, sizeof(*comp) );\r
1025 \r
1026     __BEGIN__;\r
1027 \r
1028     int i, type, depth, cn, is_simple, idx;\r
1029     int buffer_size, connectivity = flags & 255;\r
1030     double nv_buf[4] = {0,0,0,0};\r
1031     union { uchar b[4]; float f[4]; } ld_buf, ud_buf;\r
1032     CvMat stub, *img = (CvMat*)arr;\r
1033     CvMat maskstub, *mask = (CvMat*)maskarr;\r
1034     CvSize size;\r
1035 \r
1036     if( !inittab )\r
1037     {\r
1038         icvInitFloodFill( ffill_tab, ffillgrad_tab );\r
1039         inittab = 1;\r
1040     }\r
1041 \r
1042     CV_CALL( img = cvGetMat( img, &stub ));\r
1043     type = CV_MAT_TYPE( img->type );\r
1044     depth = CV_MAT_DEPTH(type);\r
1045     cn = CV_MAT_CN(type);\r
1046 \r
1047     idx = type == CV_8UC1 || type == CV_8UC3 ? 0 :\r
1048           type == CV_32FC1 || type == CV_32FC3 ? 1 : -1;\r
1049 \r
1050     if( idx < 0 )\r
1051         CV_ERROR( CV_StsUnsupportedFormat, "" );\r
1052 \r
1053     if( connectivity == 0 )\r
1054         connectivity = 4;\r
1055     else if( connectivity != 4 && connectivity != 8 )\r
1056         CV_ERROR( CV_StsBadFlag, "Connectivity must be 4, 0(=4) or 8" );\r
1057 \r
1058     is_simple = mask == 0 && (flags & CV_FLOODFILL_MASK_ONLY) == 0;\r
1059 \r
1060     for( i = 0; i < cn; i++ )\r
1061     {\r
1062         if( lo_diff.val[i] < 0 || up_diff.val[i] < 0 )\r
1063             CV_ERROR( CV_StsBadArg, "lo_diff and up_diff must be non-negative" );\r
1064         is_simple &= fabs(lo_diff.val[i]) < DBL_EPSILON && fabs(up_diff.val[i]) < DBL_EPSILON;\r
1065     }\r
1066 \r
1067     size = cvGetMatSize( img );\r
1068 \r
1069     if( (unsigned)seed_point.x >= (unsigned)size.width ||\r
1070         (unsigned)seed_point.y >= (unsigned)size.height )\r
1071         CV_ERROR( CV_StsOutOfRange, "Seed point is outside of image" );\r
1072 \r
1073     cvScalarToRawData( &newVal, &nv_buf, type, 0 );\r
1074     buffer_size = MAX( size.width, size.height )*2;\r
1075     CV_CALL( buffer = (CvFFillSegment*)cvAlloc( buffer_size*sizeof(buffer[0])));\r
1076 \r
1077     if( is_simple )\r
1078     {\r
1079         int elem_size = CV_ELEM_SIZE(type);\r
1080         const uchar* seed_ptr = img->data.ptr + img->step*seed_point.y + elem_size*seed_point.x;\r
1081         CvFloodFillFunc func = (CvFloodFillFunc)ffill_tab[idx];\r
1082         if( !func )\r
1083             CV_ERROR( CV_StsUnsupportedFormat, "" );\r
1084         // check if the new value is different from the current value at the seed point.\r
1085         // if they are exactly the same, use the generic version with mask to avoid infinite loops.\r
1086         for( i = 0; i < elem_size; i++ )\r
1087             if( seed_ptr[i] != ((uchar*)nv_buf)[i] )\r
1088                 break;\r
1089         if( i < elem_size )\r
1090         {\r
1091             IPPI_CALL( func( img->data.ptr, img->step, size,\r
1092                              seed_point, &nv_buf, comp, flags,\r
1093                              buffer, buffer_size, cn ));\r
1094             EXIT;\r
1095         }\r
1096     }\r
1097 \r
1098     {\r
1099         CvFloodFillGradFunc func = (CvFloodFillGradFunc)ffillgrad_tab[idx];\r
1100         if( !func )\r
1101             CV_ERROR( CV_StsUnsupportedFormat, "" );\r
1102 \r
1103         if( !mask )\r
1104         {\r
1105             /* created mask will be 8-byte aligned */\r
1106             tempMask = cvCreateMat( size.height + 2, (size.width + 9) & -8, CV_8UC1 );\r
1107             mask = tempMask;\r
1108         }\r
1109         else\r
1110         {\r
1111             CV_CALL( mask = cvGetMat( mask, &maskstub ));\r
1112             if( !CV_IS_MASK_ARR( mask ))\r
1113                 CV_ERROR( CV_StsBadMask, "" );\r
1114 \r
1115             if( mask->width != size.width + 2 || mask->height != size.height + 2 )\r
1116                 CV_ERROR( CV_StsUnmatchedSizes, "mask must be 2 pixel wider "\r
1117                                        "and 2 pixel taller than filled image" );\r
1118         }\r
1119 \r
1120         {\r
1121             int width = tempMask ? mask->step : size.width + 2;\r
1122             uchar* mask_row = mask->data.ptr + mask->step;\r
1123             memset( mask_row - mask->step, 1, width );\r
1124 \r
1125             for( i = 1; i <= size.height; i++, mask_row += mask->step )\r
1126             {\r
1127                 if( tempMask )\r
1128                     memset( mask_row, 0, width );\r
1129                 mask_row[0] = mask_row[size.width+1] = (uchar)1;\r
1130             }\r
1131             memset( mask_row, 1, width );\r
1132         }\r
1133 \r
1134         if( depth == CV_8U )\r
1135             for( i = 0; i < cn; i++ )\r
1136             {\r
1137                 int t = cvFloor(lo_diff.val[i]);\r
1138                 ld_buf.b[i] = CV_CAST_8U(t);\r
1139                 t = cvFloor(up_diff.val[i]);\r
1140                 ud_buf.b[i] = CV_CAST_8U(t);\r
1141             }\r
1142         else\r
1143             for( i = 0; i < cn; i++ )\r
1144             {\r
1145                 ld_buf.f[i] = (float)lo_diff.val[i];\r
1146                 ud_buf.f[i] = (float)up_diff.val[i];\r
1147             }\r
1148 \r
1149         IPPI_CALL( func( img->data.ptr, img->step, mask->data.ptr, mask->step,\r
1150                          size, seed_point, &nv_buf, ld_buf.f, ud_buf.f,\r
1151                          comp, flags, buffer, buffer_size, cn ));\r
1152     }\r
1153 \r
1154     __END__;\r
1155 \r
1156     cvFree( &buffer );\r
1157     cvReleaseMat( &tempMask );\r
1158 }\r
1159 \r
1160 \r
1161 int cv::floodFill( Mat& image, Point seedPoint,\r
1162                    Scalar newVal, Rect* rect,\r
1163                    Scalar loDiff, Scalar upDiff, int flags )\r
1164 {\r
1165     CvConnectedComp ccomp;\r
1166     CvMat _image = image;\r
1167     cvFloodFill(&_image, seedPoint, newVal, loDiff, upDiff, &ccomp, flags, 0);\r
1168     if( rect )\r
1169         *rect = ccomp.rect;\r
1170     return cvRound(ccomp.area);\r
1171 }\r
1172 \r
1173 int cv::floodFill( Mat& image, Mat& mask,\r
1174                    Point seedPoint, Scalar newVal, Rect* rect, \r
1175                    Scalar loDiff, Scalar upDiff, int flags )\r
1176 {\r
1177     CvConnectedComp ccomp;\r
1178     CvMat _image = image, _mask = mask;\r
1179     cvFloodFill(&_image, seedPoint, newVal, loDiff, upDiff, &ccomp, flags, &_mask);\r
1180     if( rect )\r
1181         *rect = ccomp.rect;\r
1182     return cvRound(ccomp.area);\r
1183 }\r
1184 \r
1185 /* End of file. */\r