3434
3535package net .imglib2 .algorithm .fill ;
3636
37+ import java .util .function .BiPredicate ;
38+ import java .util .function .Consumer ;
39+
3740import gnu .trove .list .TLongList ;
3841import gnu .trove .list .array .TLongArrayList ;
3942import net .imglib2 .Cursor ;
@@ -58,6 +61,190 @@ public class FloodFill
5861 // int or long? current TLongList cannot store more than Integer.MAX_VALUE
5962 private static final int CLEANUP_THRESHOLD = ( int ) 1e5 ;
6063
64+ /**
65+ * Iterative n-dimensional flood fill for arbitrary neighborhoods: Starting
66+ * at seed location, write fillLabel into target at current location and
67+ * continue for each pixel in neighborhood defined by shape if neighborhood
68+ * pixel is in the same connected component and fillLabel has not been
69+ * written into that location yet (comparator evaluates to 0).
70+ *
71+ * Convenience call to
72+ * {@link FloodFill#fill(RandomAccessible, RandomAccessible, Localizable, Object, Type, Shape, BiPredicate)}.
73+ * seedLabel is extracted from source at seed location.
74+ *
75+ * @param source
76+ * input
77+ * @param target
78+ * {@link RandomAccessible} to be written into. May be the same
79+ * as input.
80+ * @param seed
81+ * Start flood fill at this location.
82+ * @param fillLabel
83+ * Immutable. Value to be written into valid flood fill
84+ * locations.
85+ * @param shape
86+ * Defines neighborhood that is considered for connected
87+ * components, e.g.
88+ * {@link net.imglib2.algorithm.neighborhood.DiamondShape}
89+ * @param <T>
90+ * T implements {@code Type<U>}.
91+ * @param <U>
92+ * U implements {@code Type<U>}.
93+ */
94+ public static < T extends Type < T >, U extends Type < U > > void fill (
95+ final RandomAccessible < T > source ,
96+ final RandomAccessible < U > target ,
97+ final Localizable seed ,
98+ final U fillLabel ,
99+ final Shape shape )
100+ {
101+ final RandomAccess < T > access = source .randomAccess ();
102+ access .setPosition ( seed );
103+ final T seedValue = access .get ().copy ();
104+ final BiPredicate < T , U > filter = ( t , u ) -> t .valueEquals ( seedValue ) && !u .valueEquals ( fillLabel );
105+ fill ( source , target , seed , fillLabel , shape , filter );
106+ }
107+
108+ /**
109+ * Iterative n-dimensional flood fill for arbitrary neighborhoods: Starting
110+ * at seed location, write fillLabel into target at current location and
111+ * continue for each pixel in neighborhood defined by shape if neighborhood
112+ * pixel is in the same connected component and fillLabel has not been
113+ * written into that location yet (comparator evaluates to 0).
114+ *
115+ * Convenience call to
116+ * {@link FloodFill#fill(RandomAccessible, RandomAccessible, Localizable, Object, Object, Shape, BiPredicate, Consumer)}
117+ * with {@link TypeWriter} as writer.
118+ *
119+ * @param source
120+ * input
121+ * @param target
122+ * {@link RandomAccessible} to be written into. May be the same
123+ * as input.
124+ * @param seed
125+ * Start flood fill at this location.
126+ * @param fillLabel
127+ * Immutable. Value to be written into valid flood fill
128+ * locations.
129+ * @param shape
130+ * Defines neighborhood that is considered for connected
131+ * components, e.g.
132+ * {@link net.imglib2.algorithm.neighborhood.DiamondShape}
133+ * @param filter
134+ * Returns true if pixel has not been visited yet and should be
135+ * written into. Returns false if target pixel has been visited
136+ * or source pixel is not part of the same connected component.
137+ * @param <T>
138+ * No restrictions on {@link T}.
139+ * @param <U>
140+ * {@link U} implements {@code Type<U>}.
141+ */
142+ public static < T , U extends Type < U > > void fill (
143+ final RandomAccessible < T > source ,
144+ final RandomAccessible < U > target ,
145+ final Localizable seed ,
146+ final U fillLabel ,
147+ final Shape shape ,
148+ final BiPredicate < T , U > filter )
149+ {
150+ fill ( source , target , seed , shape , filter , targetPixel -> targetPixel .set ( fillLabel ) );
151+ }
152+
153+ /**
154+ *
155+ * Iterative n-dimensional flood fill for arbitrary neighborhoods: Starting
156+ * at seed location, write fillLabel into target at current location and
157+ * continue for each pixel in neighborhood defined by shape if neighborhood
158+ * pixel is in the same connected component and fillLabel has not been
159+ * written into that location yet (comparator evaluates to 0).
160+ *
161+ * @param source
162+ * input
163+ * @param target
164+ * {@link RandomAccessible} to be written into. May be the same
165+ * as input.
166+ * @param seed
167+ * Start flood fill at this location.
168+ * @param shape
169+ * Defines neighborhood that is considered for connected
170+ * components, e.g.
171+ * {@link net.imglib2.algorithm.neighborhood.DiamondShape}
172+ * @param filter
173+ * Returns true if pixel has not been visited yet and should be
174+ * written into. Returns false if target pixel has been visited
175+ * or source pixel is not part of the same connected component.
176+ * @param writer
177+ * Defines how fill label is written into target at current
178+ * location.
179+ * @param <T>
180+ * No restrictions on T. Appropriate filter is the only
181+ * requirement.
182+ * @param <U>
183+ * No restrictions on U. Appropriate filter and writer is the
184+ * only requirement.
185+ */
186+ public static < T , U > void fill (
187+ final RandomAccessible < T > source ,
188+ final RandomAccessible < U > target ,
189+ final Localizable seed ,
190+ final Shape shape ,
191+ final BiPredicate < T , U > filter ,
192+ final Consumer < U > writer )
193+ {
194+ final int n = source .numDimensions ();
195+
196+ final RandomAccessible < Pair < T , U > > paired = Views .pair ( source , target );
197+
198+ TLongList coordinates = new TLongArrayList ();
199+ for ( int d = 0 ; d < n ; ++d )
200+ {
201+ coordinates .add ( seed .getLongPosition ( d ) );
202+ }
203+
204+ // final TLongList[] coordinates = new TLongList[ n ];
205+ // for ( int d = 0; d < n; ++d )
206+ // {
207+ // coordinates[ d ] = new TLongArrayList();
208+ // coordinates[ d ].add( seed.getLongPosition( d ) );
209+ // }
210+ final int cleanupThreshold = n * CLEANUP_THRESHOLD ;
211+
212+ final RandomAccessible < Neighborhood < Pair < T , U > > > neighborhood = shape .neighborhoodsRandomAccessible ( paired );
213+ final RandomAccess < Neighborhood < Pair < T , U > > > neighborhoodAccess = neighborhood .randomAccess ();
214+
215+ final RandomAccess < U > targetAccess = target .randomAccess ();
216+ targetAccess .setPosition ( seed );
217+ writer .accept ( targetAccess .get () );
218+
219+ for ( int i = 0 ; i < coordinates .size (); i += n )
220+ {
221+ for ( int d = 0 ; d < n ; ++d )
222+ neighborhoodAccess .setPosition ( coordinates .get ( i + d ), d );
223+
224+ final Cursor < Pair < T , U > > neighborhoodCursor = neighborhoodAccess .get ().cursor ();
225+
226+ while ( neighborhoodCursor .hasNext () )
227+ {
228+ final Pair < T , U > p = neighborhoodCursor .next ();
229+ if ( filter .test ( p .getA (), p .getB () ) )
230+ {
231+ writer .accept ( p .getB () );
232+ for ( int d = 0 ; d < n ; ++d )
233+ coordinates .add ( neighborhoodCursor .getLongPosition ( d ) );
234+ }
235+ }
236+
237+ if ( i > cleanupThreshold )
238+ {
239+ // TODO should it start from i + n?
240+ coordinates = coordinates .subList ( i , coordinates .size () );
241+ i = 0 ;
242+ }
243+
244+ }
245+
246+ }
247+
61248 /**
62249 * Iterative n-dimensional flood fill for arbitrary neighborhoods: Starting
63250 * at seed location, write fillLabel into target at current location and
@@ -88,6 +275,7 @@ public class FloodFill
88275 * @param <U>
89276 * U implements {@code Type<U>}.
90277 */
278+ @ Deprecated
91279 public static < T extends Type < T >, U extends Type < U > > void fill ( final RandomAccessible < T > source , final RandomAccessible < U > target , final Localizable seed , final U fillLabel , final Shape shape , final Filter < Pair < T , U >, Pair < T , U > > filter )
92280 {
93281 final RandomAccess < T > access = source .randomAccess ();
@@ -127,6 +315,7 @@ public static < T extends Type< T >, U extends Type< U > > void fill( final Rand
127315 * @param <U>
128316 * {@link U} implements {@code Type<U>}.
129317 */
318+ @ Deprecated
130319 public static < T , U extends Type < U > > void fill ( final RandomAccessible < T > source , final RandomAccessible < U > target , final Localizable seed , final T seedLabel , final U fillLabel , final Shape shape , final Filter < Pair < T , U >, Pair < T , U > > filter )
131320 {
132321 fill ( source , target , seed , seedLabel , fillLabel , shape , filter , new TypeWriter < U >() );
@@ -170,11 +359,12 @@ public static < T, U extends Type< U > > void fill( final RandomAccessible< T >
170359 * No restrictions on U. Appropriate comparator and writer is the
171360 * only requirement.
172361 */
362+ @ Deprecated
173363 public static < T , U > void fill ( final RandomAccessible < T > source , final RandomAccessible < U > target , final Localizable seed , final T seedLabel , final U fillLabel , final Shape shape , final Filter < Pair < T , U >, Pair < T , U > > filter , final Writer < U > writer )
174364 {
175365 final int n = source .numDimensions ();
176366
177- final ValuePair < T , U > reference = new ValuePair < T , U >( seedLabel , fillLabel );
367+ final ValuePair < T , U > reference = new ValuePair <>( seedLabel , fillLabel );
178368
179369 final RandomAccessible < Pair < T , U > > paired = Views .pair ( source , target );
180370
0 commit comments