diff --git a/src/main/java/net/imglib2/algorithm/blocks/AbstractBlockProcessor.java b/src/main/java/net/imglib2/algorithm/blocks/AbstractBlockProcessor.java index abd095b9b..6c1923486 100644 --- a/src/main/java/net/imglib2/algorithm/blocks/AbstractBlockProcessor.java +++ b/src/main/java/net/imglib2/algorithm/blocks/AbstractBlockProcessor.java @@ -35,10 +35,8 @@ import static net.imglib2.util.Util.safeInt; -import java.util.Arrays; - import net.imglib2.Interval; -import net.imglib2.algorithm.blocks.util.BlockProcessorSourceInterval; +import net.imglib2.blocks.BlockInterval; import net.imglib2.blocks.TempArray; import net.imglib2.type.PrimitiveType; import net.imglib2.util.Intervals; @@ -51,12 +49,12 @@ * adaptable number of dimensions (such as converters), see {@link * AbstractDimensionlessBlockProcessor}. *
- * {@link BlockProcessor#getSourcePos() getSourcePos()}, {@link - * BlockProcessor#getSourceSize() getSourceSize()}, and {@link - * BlockProcessor#getSourceInterval() getSourceInterval()} are implemented to - * return the {@code protected} fields {@code long[] sourcePos} and {@code - * }int[] sourceSize}. The {@code }protected} method {@code }int sourceLength()} - * can be used to get the number of elements in the source interval. + * A {@link BlockInterval} of the desired number of dimensions is exposed + * through {@link #getSourceInterval()}. (For convenience, {@code min} and + * {@code dimensions} of the interval are also exposed through the {@code + * protected} fields {@link #sourcePos} and {@link #sourceSize}.) The {@code + * protected} method {@link #sourceLength()} returns the number of elements in + * the source interval. *
* {@link BlockProcessor#getSourceBuffer() getSourceBuffer()} is implemented * according to the {@code sourcePrimitiveType} specified at construction. @@ -70,53 +68,41 @@ public abstract class AbstractBlockProcessor< I, O > implements BlockProcessor< { private final TempArray< I > tempArray; + private final BlockInterval sourceInterval; + protected final long[] sourcePos; protected final int[] sourceSize; - private final BlockProcessorSourceInterval sourceInterval = new BlockProcessorSourceInterval( this ); - protected AbstractBlockProcessor( final PrimitiveType sourcePrimitiveType, final int numSourceDimensions ) { tempArray = TempArray.forPrimitiveType( sourcePrimitiveType ); - sourcePos = new long[ numSourceDimensions ]; - sourceSize = new int[ numSourceDimensions ]; + sourceInterval = new BlockInterval( numSourceDimensions ); + sourcePos = sourceInterval.min(); + sourceSize = sourceInterval.size(); } protected AbstractBlockProcessor( final AbstractBlockProcessor< I, O > proc ) { tempArray = proc.tempArray.newInstance(); - final int numSourceDimensions = proc.sourcePos.length; - sourcePos = new long[ numSourceDimensions ]; - sourceSize = new int[ numSourceDimensions ]; + sourceInterval = new BlockInterval( proc.sourceInterval.numDimensions() ); + sourcePos = sourceInterval.min(); + sourceSize = sourceInterval.size(); } protected int sourceLength() { - return safeInt( Intervals.numElements( sourceSize ) ); + return safeInt( Intervals.numElements( sourceInterval ) ); } @Override public void setTargetInterval( final Interval interval ) { - interval.min( sourcePos ); - Arrays.setAll( sourceSize, d -> safeInt( interval.dimension( d ) ) ); - } - - @Override - public long[] getSourcePos() - { - return sourcePos; - } - - @Override - public int[] getSourceSize() - { - return sourceSize; + sourceInterval.setFrom( interval ); } @Override - public Interval getSourceInterval() + public BlockInterval getSourceInterval() { return sourceInterval; } diff --git a/src/main/java/net/imglib2/algorithm/blocks/AbstractBlockSupplier.java b/src/main/java/net/imglib2/algorithm/blocks/AbstractBlockSupplier.java index 7e0d513c3..80e734201 100644 --- a/src/main/java/net/imglib2/algorithm/blocks/AbstractBlockSupplier.java +++ b/src/main/java/net/imglib2/algorithm/blocks/AbstractBlockSupplier.java @@ -35,6 +35,7 @@ import java.util.function.Supplier; +import net.imglib2.Interval; import net.imglib2.type.NativeType; import net.imglib2.util.CloseableThreadLocal; @@ -68,9 +69,9 @@ public int numDimensions() } @Override - public void copy( final long[] srcPos, final Object dest, final int[] size ) + public void copy( final Interval interval, final Object dest ) { - threadSafeSupplier.get().copy( srcPos, dest, size ); + threadSafeSupplier.get().copy( interval, dest ); } @Override diff --git a/src/main/java/net/imglib2/algorithm/blocks/AbstractDimensionlessBlockProcessor.java b/src/main/java/net/imglib2/algorithm/blocks/AbstractDimensionlessBlockProcessor.java index e73bc918b..97f5c0fd2 100644 --- a/src/main/java/net/imglib2/algorithm/blocks/AbstractDimensionlessBlockProcessor.java +++ b/src/main/java/net/imglib2/algorithm/blocks/AbstractDimensionlessBlockProcessor.java @@ -35,10 +35,8 @@ import static net.imglib2.util.Util.safeInt; -import java.util.Arrays; - import net.imglib2.Interval; -import net.imglib2.algorithm.blocks.util.BlockProcessorSourceInterval; +import net.imglib2.blocks.BlockInterval; import net.imglib2.blocks.TempArray; import net.imglib2.type.PrimitiveType; import net.imglib2.util.Intervals; @@ -50,12 +48,10 @@ * number of dimensions (such as converters). For {@code BlockProcessor} with a * fixed number of source dimensions, see {@link AbstractBlockProcessor}. *
- * {@link BlockProcessor#getSourcePos() getSourcePos()}, {@link - * BlockProcessor#getSourceSize() getSourceSize()}, and {@link - * BlockProcessor#getSourceInterval() getSourceInterval()} are implemented to - * return the {@code protected} fields {@code long[] sourcePos} and {@code - * }int[] sourceSize}. The {@code }protected} method {@code }int sourceLength()} - * can be used to get the number of elements in the source interval. + * A {@link BlockInterval} is exposed through {@link #getSourceInterval()} + * (after {@link #setTargetInterval} has been called). The {@code protected} + * method {@link #sourceLength()} returns the number of elements in the source + * interval. *
* {@link BlockProcessor#getSourceBuffer() getSourceBuffer()} is implemented
* according to the {@code sourcePrimitiveType} specified at construction.
@@ -69,11 +65,7 @@ public abstract class AbstractDimensionlessBlockProcessor< I, O > implements Blo
{
private final TempArray< I > tempArray;
- protected long[] sourcePos;
-
- protected int[] sourceSize;
-
- private final BlockProcessorSourceInterval sourceInterval = new BlockProcessorSourceInterval( this );
+ protected BlockInterval sourceInterval;
protected AbstractDimensionlessBlockProcessor( final PrimitiveType sourcePrimitiveType )
{
@@ -88,26 +80,24 @@ protected AbstractDimensionlessBlockProcessor( final AbstractDimensionlessBlockP
@Override
public void setTargetInterval( final Interval interval )
{
- updateNumSourceDimsensions( interval.numDimensions() );
- interval.min( sourcePos );
- Arrays.setAll( sourceSize, d -> safeInt( interval.dimension( d ) ) );
+ updateNumSourceDimensions( interval.numDimensions() );
+ sourceInterval.setFrom( interval );
}
/**
- * Re-allocates {@code sourcePos} and {@code sourceSize} arrays if they do
- * not already exist and have {@code length==n}.
+ * Re-allocates {@code sourceInterval} if it does not already exist and
+ * match {@code numDimensions()==n}.
*
* @param n
* new number of source dimensions
*
- * @return {@code true} if {@code sourcePos} and {@code sourceSize} arrays were re-allocated
+ * @return {@code true} if {@code sourceInterval} was re-allocated
*/
- protected boolean updateNumSourceDimsensions( final int n )
+ protected boolean updateNumSourceDimensions( final int n )
{
- if ( sourcePos == null || sourcePos.length != n )
+ if ( sourceInterval == null || sourceInterval.numDimensions() != n )
{
- sourcePos = new long[ n ];
- sourceSize = new int[ n ];
+ sourceInterval = new BlockInterval( n );
return true;
}
return false;
@@ -115,23 +105,11 @@ protected boolean updateNumSourceDimsensions( final int n )
protected int sourceLength()
{
- return safeInt( Intervals.numElements( sourceSize ) );
- }
-
- @Override
- public long[] getSourcePos()
- {
- return sourcePos;
- }
-
- @Override
- public int[] getSourceSize()
- {
- return sourceSize;
+ return safeInt( Intervals.numElements( sourceInterval ) );
}
@Override
- public Interval getSourceInterval()
+ public BlockInterval getSourceInterval()
{
return sourceInterval;
}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/NoOpUnaryBlockOperator.java b/src/main/java/net/imglib2/algorithm/blocks/AbstractUnaryBlockOperator.java
similarity index 66%
rename from src/main/java/net/imglib2/algorithm/blocks/NoOpUnaryBlockOperator.java
rename to src/main/java/net/imglib2/algorithm/blocks/AbstractUnaryBlockOperator.java
index be69c830b..26786b261 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/NoOpUnaryBlockOperator.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/AbstractUnaryBlockOperator.java
@@ -11,13 +11,13 @@
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -33,65 +33,61 @@
*/
package net.imglib2.algorithm.blocks;
-import java.util.function.Supplier;
-
import net.imglib2.type.NativeType;
-import net.imglib2.util.Cast;
-import net.imglib2.util.CloseableThreadLocal;
/**
- * Does nothing. This should be eliminated when concatenating through
- * {@link UnaryBlockOperator#andThen(UnaryBlockOperator)} or {@link BlockSupplier#andThen(UnaryBlockOperator)}.
+ * Abstract implementation of {@link UnaryBlockOperator}.
+ * Takes care of source/target type/dimensionality boilerplate.
*
+ * @param
- * Typically, {@code BlockProcessor} should not be used directly, but
- * wrapped in {@link UnaryBlockOperator} which has the ImgLib2 {@code Type}s
+ * Typically, {@code BlockProcessor} should not be used directly, but wrapped in
+ * {@link DefaultUnaryBlockOperator} which has the ImgLib2 {@code Type}s
* corresponding to {@code I}, {@code O}. This helps to avoid mistakes with
* unchecked (primitive array) type casts.
*
@@ -56,21 +55,26 @@ public interface BlockProcessor< I, O >
void setTargetInterval( Interval interval );
- default void setTargetInterval( long[] pos, int[] size )
- {
- setTargetInterval( new BlockProcessorTargetInterval( pos, size ) );
- }
-
- long[] getSourcePos();
-
- int[] getSourceSize();
-
Interval getSourceInterval();
/**
* Get a {@code src} array of sufficient size.
*
- * Consecutive calls may return the same array, but don't have to.
+ * Consecutive calls may return the same array (but don't have to).
+ *
+ * E.g., this is a BUG:
+ *
* {@code src} and {@code dest} are expected to be flattened arrays of the
- * dimensions specified in {@link #setTargetInterval} and computed in {@link
- * #getSourceSize}, respectively. The typical sequence is:
+ * dimensions specified in {@link #setTargetInterval} and provided in {@link
+ * #getSourceInterval}, respectively. The typical sequence is:
*
* Typically, {@code BlockProcessor} should not be used directly, but
- * wrapped in {@link UnaryBlockOperator} which has the ImgLib2 {@code Type}s
- * corresponding to {@code I}, {@code O}.
+ * wrapped in {@link DefaultUnaryBlockOperator} which has the ImgLib2 {@code
+ * Type}s corresponding to {@code I}, {@code O}.
*
* @param src
* flattened primitive array with input values
@@ -106,20 +109,4 @@ default void setTargetInterval( long[] pos, int[] size )
* flattened primitive array to fill with output values
*/
void compute( I src, O dest );
-
- /**
- * Returns a {@code BlockProcessor concatenated} such that
- *
+ * Use the static method {@link BlockSupplier#of(RandomAccessible)
+ * BlockSupplier.of} to create a {@code BlockSupplier} accessor from an {@code
+ * RandomAccessible} source. (This is just a thin wrapper around {@link
+ * PrimitiveBlocks}).
+ *
+ * Currently, only pixel types {@code T} are supported that map one-to-one to a
+ * primitive type. (For example, {@code ComplexDoubleType} or {@code
+ * Unsigned4BitType} are not supported.)
+ *
+ * If a source {@code RandomAccessible} view construction cannot be understood,
+ * {@link BlockSupplier#of(RandomAccessible) BlockSupplier.of} will return a
+ * fall-back implementation. Fallback can be configured with the optional {@link
+ * PrimitiveBlocks.OnFallback OnFallback} argument to {@link
+ * BlockSupplier#of(RandomAccessible, PrimitiveBlocks.OnFallback)
+ * BlockSupplier.of}.
+ *
+ * Use {@link BlockSupplier#andThen} to decorate a {@code BlockSupplier} with a
+ * sequence of {@code UnaryBlockOperator}s.
+ *
+ * Use {@link BlockSupplier#toCellImg} to create {@code CachedCellImg} which
+ * copies cells from a {@code BlockSupplier}.
+ *
+ * Implementations are not thread-safe in general. Use {@link #threadSafe()} to
+ * obtain a thread-safe instance (implemented using {@link ThreadLocal} copies).
+ * E.g.,
+ *
- * Example use cases:
- *
+ * Example use cases:
+ *
* The {@link UnaryBlockOperator} can then be used in {@link
* BlockSupplier#andThen(UnaryBlockOperator)} chains in a type- and
- * simensionality-safe manner.
+ * dimensionality-safe manner.
*
* @param
+ * Note that this involves an unchecked cast, that is, the returned {@code
+ * BlockProcessor} will be cast to the {@code I, O} types expected by
+ * the caller.
+ *
+ * This is mostly intended for debugging.
+ *
+ * @param
+ * input primitive array type, e.g., float[]. Must correspond to S.
+ * @param
* Each {@code copy} on the source {@code BlockSupplier} requests (at most) an
* interval of the {@code tileSize} specified in the constructor. The source
* {@code BlockSupplier.copy} writes to a temporary buffer, which is then copied
* into the appropriate portion of the {@code dest} buffer.
*
- * {@link BlockSupplier#copy} requests that are smaller or equal to {@code
- * tileSize} are passed directly to the source {@code BlockSupplier}.
+ * {@link #compute} requests that are smaller or equal to {@code tileSize} are
+ * passed directly to the source {@code BlockSupplier}.
*
* Example use cases:
*
* corresponding primitive array type
+ *
+ * @see BlockSupplier#tile
*/
-class TilingBlockSupplier< T extends NativeType< T >, P > extends AbstractBlockSupplier< T >
+class TilingUnaryBlockOperator< T extends NativeType< T >, P > extends AbstractUnaryBlockOperator< T, T >
{
- private final BlockSupplier< T > p0;
-
private final int[] innerTileSize;
private final int[] borderTileSize;
private final int[] numTiles;
@@ -80,80 +82,76 @@ class TilingBlockSupplier< T extends NativeType< T >, P > extends AbstractBlockS
private final SubArrayCopy.Typed< P, P > subArrayCopy;
- final int[] tile_pos_in_dest;
- final long[] tile_pos_in_src;
- final int[] tile_origin;
- final int[] tile_size;
+ private final int[] tile_pos_in_dest;
+ private final long[] tile_pos_in_src;
+ private final int[] tile_size;
+ private final BlockInterval tile_interval_in_src;
+ private final int[] zero;
/**
- * Create a {@code BlockSupplier} that handles {@link BlockSupplier#copy}
+ * Create a {@code UnaryBlockOperator} that handles {@link #compute}
* requests by splitting into {@code tileSize} portions that are each
- * handled by the given {@code srcSupplier} and assembled into the final
+ * handled by the source {@code BlockSupplier} and assembled into the final
* result.
*
- * @param srcSupplier
- * source {@code BlockSupplier} to wrap.
+ * @param type
+ * pixel type (source and target) of this operator
+ * @param numDimensions
+ * number of dimensions (source and target) of this operator
* @param tileSize
- * (maximum) dimensions of a request to the {@code srcSupplier}.
+ * (maximum) dimensions of a request to the source {@code BlockSupplier}.
* {@code tileSize} is expanded or truncated to the necessary size.
* For example, if {@code tileSize=={64}} when wrapping a 3D {@code
* srcSupplier}, {@code tileSize} is expanded to {@code {64, 64,
* 64}}.
*/
- public TilingBlockSupplier(
- final BlockSupplier< T > srcSupplier,
- final int... tileSize )
+ public TilingUnaryBlockOperator( final T type, final int numDimensions, final int... tileSize )
{
- this.p0 = srcSupplier;
- final int n = srcSupplier.numDimensions();
- innerTileSize = Util.expandArray( tileSize, n );
+ super( type, type, numDimensions, numDimensions );
+
+ innerTileSize = Util.expandArray( tileSize, numDimensions );
innerTileNumElements = Util.safeInt( Intervals.numElements( innerTileSize ) );
- borderTileSize = new int[ n ];
- numTiles = new int[ n ];
+ borderTileSize = new int[ numDimensions ];
+ numTiles = new int[ numDimensions ];
- final PrimitiveType primitiveType = srcSupplier.getType().getNativeTypeFactory().getPrimitiveType();
+ final PrimitiveType primitiveType = type.getNativeTypeFactory().getPrimitiveType();
tempArray = TempArray.forPrimitiveType( primitiveType );
subArrayCopy = SubArrayCopy.forPrimitiveType( primitiveType );
- tile_pos_in_dest = new int[ n ];
- tile_pos_in_src = new long[ n ];
- tile_origin = new int[ n ];
- tile_size = new int[ n ];
+ tile_pos_in_dest = new int[ numDimensions ];
+ tile_pos_in_src = new long[ numDimensions ];
+ tile_size = new int[ numDimensions ];
+ tile_interval_in_src = BlockInterval.wrap( tile_pos_in_src, tile_size );
+ zero = new int[ numDimensions ];
}
- private TilingBlockSupplier( final TilingBlockSupplier< T, P > s )
+ private TilingUnaryBlockOperator( TilingUnaryBlockOperator< T, P > op )
{
- p0 = s.p0.independentCopy();
- innerTileSize = s.innerTileSize;
- innerTileNumElements = s.innerTileNumElements;
- tempArray = s.tempArray.newInstance();
- subArrayCopy = s.subArrayCopy;
+ super( op );
+
+ innerTileSize = op.innerTileSize;
+ innerTileNumElements = op.innerTileNumElements;
+ tempArray = op.tempArray.newInstance();
+ subArrayCopy = op.subArrayCopy;
- final int n = numDimensions();
+ final int n = op.numTargetDimensions();
borderTileSize = new int[ n ];
numTiles = new int[ n ];
tile_pos_in_dest = new int[ n ];
tile_pos_in_src = new long[ n ];
- tile_origin = new int[ n ];
tile_size = new int[ n ];
+ tile_interval_in_src = BlockInterval.wrap( tile_pos_in_src, tile_size );
+ zero = op.zero;
}
@Override
- public T getType()
+ public void compute( final BlockSupplier< T > src, final Interval interval, final Object dest )
{
- return p0.getType();
- }
+ final BlockInterval blockInterval = BlockInterval.asBlockInterval( interval );
+ final long[] srcPos = blockInterval.min();
+ final int[] size = blockInterval.size();
- @Override
- public int numDimensions()
- {
- return p0.numDimensions();
- }
-
- @Override
- public void copy( final long[] srcPos, final Object dest, final int[] size )
- {
- final int n = numDimensions();
+ final int n = numTargetDimensions();
boolean singleTile = true;
for ( int d = 0; d < n; ++d )
{
@@ -164,16 +162,16 @@ public void copy( final long[] srcPos, final Object dest, final int[] size )
}
if ( singleTile )
{
- p0.copy( srcPos, dest, size );
+ src.copy( blockInterval, dest );
}
else
{
final P tile_buf = tempArray.get( innerTileNumElements );
- compute_tiles_recursively( n - 1, srcPos, Cast.unchecked( dest ), size, tile_buf );
+ compute_tiles_recursively( n - 1, src, srcPos, Cast.unchecked( dest ), size, tile_buf );
}
}
- private void compute_tiles_recursively( final int d, final long[] srcPos, final P dest, final int[] dest_size, final P tile_buf ) {
+ private void compute_tiles_recursively( final int d, final BlockSupplier< T > src, final long[] srcPos, final P dest, final int[] dest_size, final P tile_buf ) {
final int numTiles = this.numTiles[ d ];
for ( int i = 0; i < numTiles; ++i )
{
@@ -182,19 +180,19 @@ private void compute_tiles_recursively( final int d, final long[] srcPos, final
tile_size[ d ] = ( i == numTiles - 1 ) ? borderTileSize[ d ] : innerTileSize[ d ];
if ( d == 0 )
{
- p0.copy( tile_pos_in_src, tile_buf, tile_size );
- subArrayCopy.copy( tile_buf, tile_size, tile_origin, dest, dest_size, tile_pos_in_dest, tile_size );
+ src.copy( tile_interval_in_src, tile_buf );
+ subArrayCopy.copy( tile_buf, tile_size, zero, dest, dest_size, tile_pos_in_dest, tile_size );
}
else
{
- compute_tiles_recursively( d - 1, srcPos, dest, dest_size, tile_buf );
+ compute_tiles_recursively( d - 1, src, srcPos, dest, dest_size, tile_buf );
}
}
}
@Override
- public BlockSupplier< T > independentCopy()
+ public UnaryBlockOperator< T, T > independentCopy()
{
- return new TilingBlockSupplier<>( this );
+ return new TilingUnaryBlockOperator<>( this );
}
}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/UnaryBlockOperator.java b/src/main/java/net/imglib2/algorithm/blocks/UnaryBlockOperator.java
index 0c2f31b91..dfc368e23 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/UnaryBlockOperator.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/UnaryBlockOperator.java
@@ -33,43 +33,47 @@
*/
package net.imglib2.algorithm.blocks;
+import net.imglib2.Interval;
import net.imglib2.algorithm.blocks.convert.Convert;
import net.imglib2.type.NativeType;
-import net.imglib2.util.Cast;
/**
- * Wraps {@code BlockProcessor}, where {@code I} is the primitive array
- * type backing ImgLib2 {@code NativeType} {@code S} and {@code O} is the
- * primitive array type backing ImgLib2 {@code NativeType} {@code T}.
+ * A {@code UnaryBlockOperator} computes blocks of {@code NativeType
- * Typically, {@code UnaryBlockOperator} should be used rather than {@link
- * BlockProcessor} directly, to avoid mistakes with unchecked (primitive array)
- * type casts.
+ * Use the {@link UnaryBlockOperator#compute(BlockSupplier, Interval, Object)}
+ * method to compute a block of data and store it into a flat primitive array
+ * (of the appropriate primitive type corresponding to {@code T}). The input
+ * block (appropriately sized and positioned to produce the desired output
+ * {@code Interval}) is read from a {@code BlockSupplier
+ * Typically, {@code UnaryBlockOperator} are chained to a particular {@code
+ * BlockSupplier
+ * Implementations are not thread-safe in general. Use {@link
+ * #independentCopy()} to obtain independent instances.
*
* @param
- * Note that this involves an unchecked cast, that is, the returned {@code
- * BlockProcessor} will be cast to the {@code I, O} types expected by
- * the caller.
- *
- * This is mostly intented for internal use, e.g., in {@link BlockAlgoUtils}.
+ * Compute a block (using {@code src} to provide input data) and store into the given primitive array (of the appropriate type).
*
- * @param
- * input primitive array type, e.g., float[]. Must correspond to S.
- * @param
+ * source type
* @param {@code
+ * blockProcessor.setTargetInterval( interval );
+ * blockSupplier.copy( blockProcessor.getSourceInterval(), blockProcessor.getSourceBuffer() );
+ * blockProcessor.compute( blockProcessor.getSourceBuffer(), dest );
+ * }
+ * Use this instead:
+ * {@code
+ * blockProcessor.setTargetInterval( interval );
+ * Object buf = blockProcessor.getSourceBuffer();
+ * blockSupplier.copy( blockProcessor.getSourceInterval(), buf );
+ * blockProcessor.compute( buf, dest );
+ * }
*/
I getSourceBuffer();
@@ -78,18 +82,17 @@ default void setTargetInterval( long[] pos, int[] size )
* Compute the {@code dest} array from the {@code src} array.
*
*
* Note, that the {@code src} and {@code dest} arrays may be larger than
@@ -97,8 +100,8 @@ default void setTargetInterval( long[] pos, int[] size )
* case the trailing elements are ignored.
* {@code
- * concatenated.compute(src, dest);
- * }
- * is equivalent to
- * {@code
- * this.compute(src, tmp);
- * processor.compute(tmp, dest);
- * }
- */
- default < P > BlockProcessor< I, P > andThen( BlockProcessor< O, P > processor )
- {
- return new ConcatenatedBlockProcessor<>( this, processor );
- }
}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/BlockProcessorTargetInterval.java b/src/main/java/net/imglib2/algorithm/blocks/BlockProcessorTargetInterval.java
deleted file mode 100644
index 08c2862dd..000000000
--- a/src/main/java/net/imglib2/algorithm/blocks/BlockProcessorTargetInterval.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*-
- * #%L
- * ImgLib2: a general-purpose, multidimensional image processing library.
- * %%
- * Copyright (C) 2009 - 2024 Tobias Pietzsch, Stephan Preibisch, Stephan Saalfeld,
- * John Bogovic, Albert Cardona, Barry DeZonia, Christian Dietz, Jan Funke,
- * Aivar Grislis, Jonathan Hale, Grant Harris, Stefan Helfrich, Mark Hiner,
- * Martin Horn, Steffen Jaensch, Lee Kamentsky, Larry Lindsey, Melissa Linkert,
- * Mark Longair, Brian Northan, Nick Perry, Curtis Rueden, Johannes Schindelin,
- * Jean-Yves Tinevez and Michael Zinsmaier.
- * %%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * #L%
- */
-package net.imglib2.algorithm.blocks;
-
-import net.imglib2.Interval;
-
-/**
- * Wraps {@code long[] pos} and {@code int[] size} as a {@code Interval}, for
- * the default implementation of {@link BlockProcessor#setTargetInterval(long[],
- * int[])}.
- */
-class BlockProcessorTargetInterval implements Interval
-{
- private final long[] min;
-
- private final int[] size;
-
- BlockProcessorTargetInterval( long[] min, int[] size )
- {
- this.min = min;
- this.size = size;
- }
-
- @Override
- public long min( final int i )
- {
- return min[ i ];
- }
-
- @Override
- public long max( final int i )
- {
- return min[ i ] + size[ i ] - 1;
- }
-
- @Override
- public long dimension( final int d )
- {
- return size[ d ];
- }
-
- @Override
- public int numDimensions()
- {
- return min.length;
- }
-}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/BlockSupplier.java b/src/main/java/net/imglib2/algorithm/blocks/BlockSupplier.java
index b8983f452..34cf27acb 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/BlockSupplier.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/BlockSupplier.java
@@ -33,12 +33,6 @@
*/
package net.imglib2.algorithm.blocks;
-import static net.imglib2.blocks.PrimitiveBlocks.OnFallback.WARN;
-import static net.imglib2.util.Util.safeInt;
-
-import java.util.Arrays;
-import java.util.function.Function;
-
import net.imglib2.EuclideanSpace;
import net.imglib2.Interval;
import net.imglib2.RandomAccessible;
@@ -46,44 +40,50 @@
import net.imglib2.blocks.PrimitiveBlocks;
import net.imglib2.cache.img.CachedCellImg;
import net.imglib2.type.NativeType;
-import net.imglib2.util.Cast;
-import net.imglib2.util.Util;
-public interface BlockSupplier< T extends NativeType< T > > extends Typed< T >, EuclideanSpace
-{
- /**
- * Copy a block from the ({@code T}-typed) source into primitive arrays (of
- * the appropriate type).
- *
- * @param srcPos
- * min coordinate of the block to copy
- * @param dest
- * primitive array to copy into. Must correspond to {@code T}, for
- * example, if {@code T} is {@code UnsignedByteType} then {@code dest} must
- * be {@code byte[]}.
- * @param size
- * the size of the block to copy
- */
- void copy( long[] srcPos, Object dest, int[] size );
+import java.util.function.Function;
- /**
- * Copy a block from the ({@code T}-typed) source into primitive arrays (of
- * the appropriate type).
- *
- * @param srcPos
- * min coordinate of the block to copy
- * @param dest
- * primitive array to copy into. Must correspond to {@code T}, for
- * example, if {@code T} is {@code UnsignedByteType} then {@code dest} must
- * be {@code byte[]}.
- * @param size
- * the size of the block to copy
- */
- default void copy( int[] srcPos, Object dest, int[] size )
- {
- copy( Util.int2long( srcPos ), dest, size );
- }
+import static net.imglib2.blocks.PrimitiveBlocks.OnFallback.WARN;
+/**
+ * Provides blocks of data from a {@code NativeType{@code
+ * BlockSupplier
+ *
+ * @param
- *
- *
- * @param tileSize
- * (maximum) dimensions of a request to the {@code srcSupplier}.
- * {@code tileSize} is expanded or truncated to the necessary size. For
- * example, if {@code tileSize=={64}} and this {@code BlockSupplier} is 3D,
- * then {@code tileSize} is expanded to {@code {64, 64, 64}}.
- */
- default BlockSupplier< T > tile( int... tileSize )
- {
- return new TilingBlockSupplier<>( this, tileSize );
- }
-
- /**
- * Returns a {@code UnaryBlockOperator} that is equivalent to applying
- * {@code this}, and then applying {@code op} to the result.
+ * Returns a {@code BlockSupplier} that provide blocks using the given
+ * {@code operator} with this {@code BlockSupplier} as input.
*/
default < U extends NativeType< U > > BlockSupplier< U > andThen( UnaryBlockOperator< T, U > operator )
{
- if ( operator instanceof NoOpUnaryBlockOperator )
- return Cast.unchecked( this );
- else
- return new ConcatenatedBlockSupplier<>( this.independentCopy(), operator.independentCopy() );
+ return operator.applyTo( this );
}
default < U extends NativeType< U > > BlockSupplier< U > andThen( Function< BlockSupplier< T >, UnaryBlockOperator< T, U > > function )
@@ -157,25 +123,6 @@ default < U extends NativeType< U > > BlockSupplier< U > andThen( Function< Bloc
return andThen( function.apply( this ) );
}
- /**
- * Return a {@code CachedCellImg} which copies cells from this {@code BlockSupplier}.
- *
- * @param dimensions
- * dimensions of the {@code CachedCellImg} to create
- * @param cellDimensions
- * block size of the {@code CachedCellImg} to create.
- * This is extended or truncated as necessary.
- * For example if {@code cellDimensions={64,32}} then for creating a 3D
- * image it will be augmented to {@code {64,32,32}}. For creating a 1D image
- * it will be truncated to {@code {64}}.
- *
- * @return a {@code CachedCellImg} which copies cells from this {@code BlockSupplier}.
- */
- default CachedCellImg< T, ? > toCellImg( final long[] dimensions, final int... cellDimensions )
- {
- return BlockAlgoUtils.cellImg( this, dimensions, cellDimensions );
- }
-
/**
* Create a {@code BlockSupplier} accessor for an arbitrary {@code
* RandomAccessible} source. Many View constructions (that ultimately end in
@@ -229,11 +176,47 @@ static < T extends NativeType< T > > BlockSupplier< T > of(
return new PrimitiveBlocksSupplier<>( PrimitiveBlocks.of( ra, onFallback ) );
}
- /*
- * Wrap the given {@code PrimitiveBlocks} as a {@code BlockSupplier}.
+ /**
+ * Return a {@code CachedCellImg} which copies cells from this {@code BlockSupplier}.
+ *
+ * @param dimensions
+ * dimensions of the {@code CachedCellImg} to create
+ * @param cellDimensions
+ * block size of the {@code CachedCellImg} to create.
+ * This is extended or truncated as necessary.
+ * For example if {@code cellDimensions={64,32}} then for creating a 3D
+ * image it will be augmented to {@code {64,32,32}}. For creating a 1D image
+ * it will be truncated to {@code {64}}.
+ *
+ * @return a {@code CachedCellImg} which copies cells from this {@code BlockSupplier}.
+ */
+ default CachedCellImg< T, ? > toCellImg( final long[] dimensions, final int... cellDimensions )
+ {
+ return BlockAlgoUtils.cellImg( this, dimensions, cellDimensions );
+ }
+
+ /**
+ * Returns a new {@code BlockSupplier} that handles {@link #copy} requests
+ * by splitting into {@code tileSize} portions that are each handled by this
+ * {@code BlockSupplier} and assembled into the final result.
+ *
+ *
+ *
+ * @param tileSize
+ * (maximum) dimensions of a request to the {@code srcSupplier}.
+ * {@code tileSize} is expanded or truncated to the necessary size. For
+ * example, if {@code tileSize=={64}} and this {@code BlockSupplier} is 3D,
+ * then {@code tileSize} is expanded to {@code {64, 64, 64}}.
*/
-// static < T extends NativeType< T > > BlockSupplier< T > of( PrimitiveBlocks< T > blocks )
-// {
-// return new PrimitiveBlocksSupplier<>( blocks );
-// }
+ default BlockSupplier< T > tile( int... tileSize )
+ {
+ return this.andThen( new TilingUnaryBlockOperator<>( getType(), numDimensions(), tileSize ) );
+ }
}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/ConcatenatedBlockProcessor.java b/src/main/java/net/imglib2/algorithm/blocks/ConcatenatedBlockProcessor.java
deleted file mode 100644
index 6b2d26040..000000000
--- a/src/main/java/net/imglib2/algorithm/blocks/ConcatenatedBlockProcessor.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*-
- * #%L
- * ImgLib2: a general-purpose, multidimensional image processing library.
- * %%
- * Copyright (C) 2009 - 2024 Tobias Pietzsch, Stephan Preibisch, Stephan Saalfeld,
- * John Bogovic, Albert Cardona, Barry DeZonia, Christian Dietz, Jan Funke,
- * Aivar Grislis, Jonathan Hale, Grant Harris, Stefan Helfrich, Mark Hiner,
- * Martin Horn, Steffen Jaensch, Lee Kamentsky, Larry Lindsey, Melissa Linkert,
- * Mark Longair, Brian Northan, Nick Perry, Curtis Rueden, Johannes Schindelin,
- * Jean-Yves Tinevez and Michael Zinsmaier.
- * %%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * #L%
- */
-package net.imglib2.algorithm.blocks;
-
-import net.imglib2.Interval;
-
-class ConcatenatedBlockProcessor< I, K, O > implements BlockProcessor< I, O >
-{
- private final BlockProcessor< I, K > p0;
-
- private final BlockProcessor< K, O > p1;
-
- public ConcatenatedBlockProcessor(
- BlockProcessor< I, K > p0,
- BlockProcessor< K, O > p1 )
- {
- this.p0 = p0;
- this.p1 = p1;
- }
-
- @Override
- public ConcatenatedBlockProcessor< I, K, O > independentCopy()
- {
- return new ConcatenatedBlockProcessor<>( p0.independentCopy(), p1.independentCopy() );
- }
-
- @Override
- public void setTargetInterval( final Interval interval )
- {
- p1.setTargetInterval( interval );
- p0.setTargetInterval( p1.getSourceInterval() );
- }
-
- @Override
- public long[] getSourcePos()
- {
- return p0.getSourcePos();
- }
-
- @Override
- public int[] getSourceSize()
- {
- return p0.getSourceSize();
- }
-
- @Override
- public Interval getSourceInterval()
- {
- return p0.getSourceInterval();
- }
-
- @Override
- public I getSourceBuffer()
- {
- return p0.getSourceBuffer();
- }
-
- @Override
- public void compute( final I src, final O dest )
- {
- final K temp = p1.getSourceBuffer();
- p0.compute( src, temp );
- p1.compute( temp, dest );
- }
-}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/ConcatenatedBlockSupplier.java b/src/main/java/net/imglib2/algorithm/blocks/ConcatenatedBlockSupplier.java
index b7917073f..691b7572c 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/ConcatenatedBlockSupplier.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/ConcatenatedBlockSupplier.java
@@ -33,26 +33,23 @@
*/
package net.imglib2.algorithm.blocks;
+import net.imglib2.Interval;
import net.imglib2.type.NativeType;
-import net.imglib2.util.Cast;
-class ConcatenatedBlockSupplier< T extends NativeType< T > > extends AbstractBlockSupplier< T >
+class ConcatenatedBlockSupplier< S extends NativeType< S >, T extends NativeType< T > > extends AbstractBlockSupplier< T >
{
- private final BlockSupplier< ? > p0;
+ private final BlockSupplier< S > src;
- private final BlockProcessor< ?, ? > p1;
-
- private final T type;
+ private final UnaryBlockOperator< S, T > operator;
private final int numDimensions;
- public < S extends NativeType< S > > ConcatenatedBlockSupplier(
+ ConcatenatedBlockSupplier(
final BlockSupplier< S > srcSupplier,
final UnaryBlockOperator< S, T > operator )
{
- this.p0 = srcSupplier;
- this.p1 = operator.blockProcessor();
- this.type = operator.getTargetType();
+ this.src = srcSupplier;
+ this.operator = operator;
if ( operator.numSourceDimensions() > 0 )
{
if ( srcSupplier.numDimensions() != operator.numSourceDimensions() )
@@ -65,18 +62,17 @@ public < S extends NativeType< S > > ConcatenatedBlockSupplier(
}
}
- private ConcatenatedBlockSupplier( final ConcatenatedBlockSupplier< T > s )
+ private ConcatenatedBlockSupplier( final ConcatenatedBlockSupplier< S, T > s )
{
- p0 = s.p0.independentCopy();
- p1 = s.p1.independentCopy();
- type = s.type;
+ src = s.src.independentCopy();
+ operator = s.operator.independentCopy();
numDimensions = s.numDimensions;
}
@Override
public T getType()
{
- return type;
+ return operator.getTargetType();
}
@Override
@@ -86,12 +82,9 @@ public int numDimensions()
}
@Override
- public void copy( final long[] srcPos, final Object dest, final int[] size )
+ public void copy( final Interval interval, final Object dest )
{
- p1.setTargetInterval( srcPos, size );
- final Object src = p1.getSourceBuffer();
- p0.copy( p1.getSourcePos(), src, p1.getSourceSize() );
- p1.compute( Cast.unchecked( src ), Cast.unchecked( dest ) );
+ operator.compute( src, interval, dest );
}
@Override
diff --git a/src/main/java/net/imglib2/algorithm/blocks/ConcatenatedUnaryBlockOperator.java b/src/main/java/net/imglib2/algorithm/blocks/ConcatenatedUnaryBlockOperator.java
new file mode 100644
index 000000000..3c8c9907d
--- /dev/null
+++ b/src/main/java/net/imglib2/algorithm/blocks/ConcatenatedUnaryBlockOperator.java
@@ -0,0 +1,80 @@
+package net.imglib2.algorithm.blocks;
+
+import net.imglib2.Interval;
+import net.imglib2.type.NativeType;
+
+class ConcatenatedUnaryBlockOperator<
+ S extends NativeType< S >,
+ T extends NativeType< T >,
+ U extends NativeType< U > >
+ implements UnaryBlockOperator< S, U >
+{
+ private final UnaryBlockOperator< S, T > op1;
+ private final UnaryBlockOperator< T, U > op2;
+ private final int numSourceDimensions;
+ private final int numTargetDimensions;
+
+ ConcatenatedUnaryBlockOperator( UnaryBlockOperator< S, T > op1, UnaryBlockOperator< T, U > op2 )
+ {
+ this.op1 = op1;
+ this.op2 = op2;
+
+ final boolean op1HasDims = op1.numSourceDimensions() > 0;
+ final boolean op2HasDims = op2.numSourceDimensions() > 0;
+ if ( op2HasDims && op1HasDims && op1.numTargetDimensions() != op2.numSourceDimensions() ) {
+ throw new IllegalArgumentException( "UnaryBlockOperator cannot be concatenated: number of dimensions mismatch." );
+ }
+ this.numSourceDimensions = op1HasDims ? op1.numSourceDimensions() : op2.numSourceDimensions();
+ this.numTargetDimensions = op2HasDims ? op2.numTargetDimensions() : op1.numTargetDimensions();
+ }
+
+ private ConcatenatedUnaryBlockOperator( ConcatenatedUnaryBlockOperator< S, T, U > op )
+ {
+ this.op1 = op.op1.independentCopy();
+ this.op2 = op.op2.independentCopy();
+ this.numSourceDimensions = op.numSourceDimensions;
+ this.numTargetDimensions = op.numTargetDimensions;
+ }
+
+ @Override
+ public void compute( final BlockSupplier< S > src, final Interval interval, final Object dest )
+ {
+ applyTo( src ).copy( interval, dest );
+ }
+
+ @Override
+ public S getSourceType()
+ {
+ return op1.getSourceType();
+ }
+
+ @Override
+ public U getTargetType()
+ {
+ return op2.getTargetType();
+ }
+
+ @Override
+ public int numSourceDimensions()
+ {
+ return 0;
+ }
+
+ @Override
+ public int numTargetDimensions()
+ {
+ return 0;
+ }
+
+ @Override
+ public UnaryBlockOperator< S, U > independentCopy()
+ {
+ return new ConcatenatedUnaryBlockOperator<>( this );
+ }
+
+ @Override
+ public BlockSupplier< U > applyTo( final BlockSupplier< S > blocks )
+ {
+ return op2.applyTo( op1.applyTo( blocks ) );
+ }
+}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/DefaultUnaryBlockOperator.java b/src/main/java/net/imglib2/algorithm/blocks/DefaultUnaryBlockOperator.java
index fdba81fcc..cf059fbe2 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/DefaultUnaryBlockOperator.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/DefaultUnaryBlockOperator.java
@@ -33,10 +33,9 @@
*/
package net.imglib2.algorithm.blocks;
-import java.util.function.Supplier;
+import net.imglib2.Interval;
import net.imglib2.type.NativeType;
import net.imglib2.util.Cast;
-import net.imglib2.util.CloseableThreadLocal;
/**
* Default implementation of {@link UnaryBlockOperator}.
@@ -48,117 +47,64 @@
*
* source type
* @param
@@ -66,11 +68,11 @@
* pixel type
* @param
} data.
* }.
+ * } using {@link BlockSupplier#andThen} (or {@link #applyTo},
+ * instead of calling {@code compute()} explicitly.
+ *
- * source type
+ * source pixel type
* @param }.
+ */
+ default BlockSupplier< T > applyTo( BlockSupplier< S > blocks )
+ {
+ return new ConcatenatedBlockSupplier<>( blocks, independentCopy() );
+ }
+
/**
* Returns a {@code UnaryBlockOperator} that is equivalent to applying
* {@code this}, and then applying {@code op} to the result.
*/
default < U extends NativeType< U > > UnaryBlockOperator< S, U > andThen( UnaryBlockOperator< T, U > op )
{
- if ( op instanceof NoOpUnaryBlockOperator )
- return Cast.unchecked( this );
-
- final boolean thisHasDimensions = numSourceDimensions() > 0;
- final boolean opHasDimensions = op.numSourceDimensions() > 0;
- if ( opHasDimensions && thisHasDimensions && numTargetDimensions() != op.numSourceDimensions() ) {
- throw new IllegalArgumentException( "UnaryBlockOperator cannot be concatenated: number of dimensions mismatch." );
- }
- final int numSourceDimensions = thisHasDimensions ? numSourceDimensions() : op.numSourceDimensions();
- final int numTargetDimensions = opHasDimensions ? op.numTargetDimensions() : numTargetDimensions();
- return new DefaultUnaryBlockOperator<>(
- getSourceType(),
- op.getTargetType(),
- numSourceDimensions,
- numTargetDimensions,
- blockProcessor().andThen( op.blockProcessor() ) );
+ return new ConcatenatedUnaryBlockOperator<>( this, op.independentCopy() );
}
/**
@@ -145,10 +137,7 @@ default < U extends NativeType< U > > UnaryBlockOperator< S, U > andThen( UnaryB
*/
default < U extends NativeType< U > > UnaryBlockOperator< U, T > adaptSourceType( U newSourceType, ClampType clamp )
{
- if ( newSourceType.getClass().isInstance( getSourceType() ) )
- return Cast.unchecked( this );
- else
- return Convert.createOperator( newSourceType, getSourceType(), clamp ).andThen( this );
+ return Convert.createOperator( newSourceType, getSourceType(), clamp ).andThen( this );
}
/**
@@ -158,9 +147,6 @@ default < U extends NativeType< U > > UnaryBlockOperator< U, T > adaptSourceType
*/
default < U extends NativeType< U > > UnaryBlockOperator< S, U > adaptTargetType( U newTargetType, ClampType clamp )
{
- if ( newTargetType.getClass().isInstance( getTargetType() ) )
- return Cast.unchecked( this );
- else
- return this.andThen( Convert.createOperator( getTargetType(), newTargetType, clamp ) );
+ return this.andThen( Convert.createOperator( getTargetType(), newTargetType, clamp ) );
}
}
diff --git a/src/main/java/net/imglib2/algorithm/blocks/convert/Convert.java b/src/main/java/net/imglib2/algorithm/blocks/convert/Convert.java
index efff1ad31..922d0032e 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/convert/Convert.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/convert/Convert.java
@@ -37,13 +37,15 @@
import java.util.function.Function;
import java.util.function.Supplier;
+import net.imglib2.Interval;
+import net.imglib2.algorithm.blocks.AbstractUnaryBlockOperator;
import net.imglib2.algorithm.blocks.BlockSupplier;
import net.imglib2.algorithm.blocks.ClampType;
import net.imglib2.algorithm.blocks.DefaultUnaryBlockOperator;
-import net.imglib2.algorithm.blocks.NoOpUnaryBlockOperator;
import net.imglib2.algorithm.blocks.UnaryBlockOperator;
import net.imglib2.converter.Converter;
import net.imglib2.type.NativeType;
+import net.imglib2.util.Cast;
/**
* Create {@link UnaryBlockOperator} to convert blocks between standard ImgLib2 {@code Type}s.
@@ -170,13 +172,51 @@ UnaryBlockOperator< S, T > createOperator( final S sourceType, final T targetTyp
UnaryBlockOperator< S, T > createOperator( final S sourceType, final T targetType, final ClampType clamp )
{
if ( Objects.equals( sourceType.getClass(), targetType.getClass() ) )
- return new NoOpUnaryBlockOperator<>();
+ return Cast.unchecked( new Identity<>( sourceType, 0 ) );
return new DefaultUnaryBlockOperator<>(
sourceType, targetType, 0, 0,
new ConvertBlockProcessor<>( sourceType, targetType, clamp ) );
}
+ // TODO: move to upper level, make public?
+ static class Identity< T extends NativeType< T > > extends AbstractUnaryBlockOperator< T, T >
+ {
+ protected Identity( final T type, final int numDimensions )
+ {
+ super( type, type, numDimensions, numDimensions );
+ }
+
+ protected Identity( final AbstractUnaryBlockOperator< T, T > op )
+ {
+ super( op );
+ }
+
+ @Override
+ public void compute( final BlockSupplier< T > src, final Interval interval, final Object dest )
+ {
+ src.copy( interval, dest );
+ }
+
+ @Override
+ public UnaryBlockOperator< T, T > independentCopy()
+ {
+ return this;
+ }
+
+ @Override
+ public BlockSupplier< T > applyTo( final BlockSupplier< T > blocks )
+ {
+ return blocks;
+ }
+
+ @Override
+ public < U extends NativeType< U > > UnaryBlockOperator< T, U > andThen( final UnaryBlockOperator< T, U > op )
+ {
+ return op;
+ }
+ }
+
/**
* Create {@link UnaryBlockOperator} to convert blocks between {@code
* sourceType} and {@code targetType} with the specified {@code Converter}.
diff --git a/src/main/java/net/imglib2/algorithm/blocks/transform/AbstractTransformProcessor.java b/src/main/java/net/imglib2/algorithm/blocks/transform/AbstractTransformProcessor.java
index a67ce5bd7..bda6bb1a5 100644
--- a/src/main/java/net/imglib2/algorithm/blocks/transform/AbstractTransformProcessor.java
+++ b/src/main/java/net/imglib2/algorithm/blocks/transform/AbstractTransformProcessor.java
@@ -33,19 +33,13 @@
*/
package net.imglib2.algorithm.blocks.transform;
-import static net.imglib2.util.Util.safeInt;
-
import java.util.Arrays;
-import java.util.function.Supplier;
import net.imglib2.Interval;
import net.imglib2.RealInterval;
import net.imglib2.algorithm.blocks.AbstractBlockProcessor;
-import net.imglib2.algorithm.blocks.BlockProcessor;
-import net.imglib2.algorithm.blocks.util.BlockProcessorSourceInterval;
-import net.imglib2.blocks.TempArray;
+import net.imglib2.blocks.BlockInterval;
import net.imglib2.type.PrimitiveType;
-import net.imglib2.util.Intervals;
/**
* Abstract base class for {@link Affine3DProcessor} and {@link
@@ -96,9 +90,7 @@ abstract class AbstractTransformProcessor< P > extends AbstractBlockProcessor< P
@Override
public void setTargetInterval( final Interval interval )
{
- interval.min( destPos );
- Arrays.setAll( destSize, d -> safeInt( interval.dimension( d ) ) );
-
+ BlockInterval.wrap( destPos, destSize ).setFrom( interval );
final RealInterval bounds = estimateBounds( interval );
switch ( interpolation )
{
diff --git a/src/main/java/net/imglib2/algorithm/blocks/util/BlockProcessorSourceInterval.java b/src/main/java/net/imglib2/algorithm/blocks/util/BlockProcessorSourceInterval.java
deleted file mode 100644
index 813c2ccec..000000000
--- a/src/main/java/net/imglib2/algorithm/blocks/util/BlockProcessorSourceInterval.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*-
- * #%L
- * ImgLib2: a general-purpose, multidimensional image processing library.
- * %%
- * Copyright (C) 2009 - 2024 Tobias Pietzsch, Stephan Preibisch, Stephan Saalfeld,
- * John Bogovic, Albert Cardona, Barry DeZonia, Christian Dietz, Jan Funke,
- * Aivar Grislis, Jonathan Hale, Grant Harris, Stefan Helfrich, Mark Hiner,
- * Martin Horn, Steffen Jaensch, Lee Kamentsky, Larry Lindsey, Melissa Linkert,
- * Mark Longair, Brian Northan, Nick Perry, Curtis Rueden, Johannes Schindelin,
- * Jean-Yves Tinevez and Michael Zinsmaier.
- * %%
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- * #L%
- */
-package net.imglib2.algorithm.blocks.util;
-
-import net.imglib2.Interval;
-import net.imglib2.algorithm.blocks.BlockProcessor;
-
-/**
- * Helper class that wraps {@link BlockProcessor#getSourcePos()} and {@link
- * BlockProcessor#getSourceSize()} as an {@code Interval}.
- */
-public class BlockProcessorSourceInterval implements Interval
-{
- private BlockProcessor< ?, ? > p;
-
- public BlockProcessorSourceInterval( BlockProcessor< ?, ? > blockProcessor )
- {
- this.p = blockProcessor;
- }
-
- @Override
- public int numDimensions()
- {
- return p.getSourcePos().length;
- }
-
- @Override
- public long min( final int d )
- {
- return p.getSourcePos()[ d ];
- }
-
- @Override
- public long max( final int d )
- {
- return min( d ) + dimension( d ) - 1;
- }
-
- @Override
- public long dimension( final int d )
- {
- return p.getSourceSize()[ d ];
- }
-}
diff --git a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBenchmarkFull.java b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBenchmarkFull.java
index ccf1b92b5..51c20072b 100644
--- a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBenchmarkFull.java
+++ b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBenchmarkFull.java
@@ -123,7 +123,7 @@ public void setUp() {
centerFloat = new CenterFloat( downsampleInDim );
centerFloat.setTargetInterval( new FinalInterval( Util.int2long( outputSize ) ) );
- System.arraycopy( centerFloat.getSourceSize(), 0, inputSize, 0, inputSize.length );
+ System.arraycopy( centerFloat.getSourceInterval().size(), 0, inputSize, 0, inputSize.length );
inputF = new float[ ( int ) Intervals.numElements( inputSize ) ];
for ( int i = 0; i < inputF.length; i++ )
inputF[ i ] = random.nextFloat();
diff --git a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBenchmarkFull2.java b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBenchmarkFull2.java
index 26490c834..b5e9681bd 100644
--- a/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBenchmarkFull2.java
+++ b/src/test/java/net/imglib2/algorithm/blocks/downsample/DownsampleBenchmarkFull2.java
@@ -124,7 +124,7 @@ public void setUp() {
halfPixelFloat = new HalfPixelFloat( downsampleInDim );
halfPixelFloat.setTargetInterval( new FinalInterval( Util.int2long( outputSize ) ) );
- System.arraycopy( halfPixelFloat.getSourceSize(), 0, inputSize, 0, inputSize.length );
+ System.arraycopy( halfPixelFloat.getSourceInterval().size(), 0, inputSize, 0, inputSize.length );
inputF = new float[ ( int ) Intervals.numElements( inputSize ) ];
for ( int i = 0; i < inputF.length; i++ )
inputF[ i ] = random.nextFloat();
diff --git a/src/test/java/net/imglib2/algorithm/blocks/transform/TransformBenchmark3D.java b/src/test/java/net/imglib2/algorithm/blocks/transform/TransformBenchmark3D.java
index ae0ab159b..60da49cb3 100644
--- a/src/test/java/net/imglib2/algorithm/blocks/transform/TransformBenchmark3D.java
+++ b/src/test/java/net/imglib2/algorithm/blocks/transform/TransformBenchmark3D.java
@@ -39,12 +39,14 @@
import java.util.concurrent.TimeUnit;
import net.imglib2.Cursor;
import net.imglib2.FinalInterval;
+import net.imglib2.Interval;
import net.imglib2.RandomAccessible;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.RealRandomAccessible;
import net.imglib2.algorithm.blocks.BlockProcessor;
import net.imglib2.algorithm.blocks.ClampType;
import net.imglib2.algorithm.blocks.ComputationType;
+import net.imglib2.algorithm.blocks.DefaultUnaryBlockOperator;
import net.imglib2.algorithm.blocks.transform.Transform.Interpolation;
import net.imglib2.blocks.PrimitiveBlocks;
import net.imglib2.converter.Converters;
@@ -154,17 +156,23 @@ public void blocksnaiveSetup()
new RealFloatConverter<>(),
new FloatType() ) );
final FloatType type2 = new FloatType();
- processor = Transform.createAffineOperator( type2, affine, Interpolation.NLINEAR, ComputationType.AUTO, ClampType.CLAMP ).blockProcessor();
+ processor = ( ( DefaultUnaryBlockOperator< ?, ? > )
+ Transform.createAffineOperator( type2, affine, Interpolation.NLINEAR, ComputationType.AUTO, ClampType.CLAMP )
+ ).blockProcessor();
blocksDouble = PrimitiveBlocks.of(
Converters.convert(
Views.extendZero( img ),
new RealDoubleConverter<>(),
new DoubleType() ) );
final DoubleType type1 = new DoubleType();
- processorDouble = Transform.createAffineOperator( type1, affine, Interpolation.NLINEAR, ComputationType.AUTO, ClampType.CLAMP ).blockProcessor();
+ processorDouble = ( ( DefaultUnaryBlockOperator< ?, ? > )
+ Transform.createAffineOperator( type1, affine, Interpolation.NLINEAR, ComputationType.AUTO, ClampType.CLAMP )
+ ).blockProcessor();
blocksUnsignedByte = PrimitiveBlocks.of( Views.extendZero( img ) );
final UnsignedByteType type = new UnsignedByteType();
- processorUnsignedByte = Transform.createAffineOperator( type, affine, Interpolation.NLINEAR, ComputationType.AUTO, ClampType.CLAMP ).blockProcessor();
+ processorUnsignedByte = ( ( DefaultUnaryBlockOperator< ?, ? > )
+ Transform.createAffineOperator( type, affine, Interpolation.NLINEAR, ComputationType.AUTO, ClampType.CLAMP )
+ ).blockProcessor();
blocksFloat();
blocksDouble();
blocksUnsignedByte();
@@ -179,9 +187,10 @@ public Object blocksFloat()
long[] max = new long[ size.length ];
Arrays.setAll( max, d -> min[ d ] + size[ d ] - 1 );
processor.setTargetInterval( FinalInterval.wrap( min, max ) );
- blocks.copy( processor.getSourcePos(), processor.getSourceBuffer(), processor.getSourceSize() );
+ final float[] buf = processor.getSourceBuffer();
+ blocks.copy( processor.getSourceInterval(), buf );
final float[] dest = new float[ ( int ) Intervals.numElements( size ) ];
- processor.compute( processor.getSourceBuffer(), dest );
+ processor.compute( buf, dest );
final RandomAccessibleInterval< FloatType > destImg = ArrayImgs.floats( dest, size[ 0 ], size[ 1 ], size[ 2 ] );
return destImg;
}
@@ -192,9 +201,10 @@ public Object blocksDouble()
long[] max = new long[ size.length ];
Arrays.setAll( max, d -> min[ d ] + size[ d ] - 1 );
processorDouble.setTargetInterval( FinalInterval.wrap( min, max ) );
- blocksDouble.copy( processorDouble.getSourcePos(), processorDouble.getSourceBuffer(), processorDouble.getSourceSize() );
+ final double[] buf = processorDouble.getSourceBuffer();
+ blocksDouble.copy( processorDouble.getSourceInterval(), buf );
final double[] dest = new double[ ( int ) Intervals.numElements( size ) ];
- processorDouble.compute( processorDouble.getSourceBuffer(), dest );
+ processorDouble.compute( buf, dest );
final RandomAccessibleInterval< DoubleType > destImg = ArrayImgs.doubles( dest, size[ 0 ], size[ 1 ], size[ 2 ] );
return destImg;
}
@@ -205,7 +215,8 @@ public Object blocksUnsignedByte()
long[] max = new long[ size.length ];
Arrays.setAll( max, d -> min[ d ] + size[ d ] - 1 );
processorUnsignedByte.setTargetInterval( FinalInterval.wrap( min, max ) );
- blocksUnsignedByte.copy( processorUnsignedByte.getSourcePos(), processorUnsignedByte.getSourceBuffer(), processorUnsignedByte.getSourceSize() );
+ final Interval buf = processorUnsignedByte.getSourceInterval();
+ blocksUnsignedByte.copy( buf, processorUnsignedByte.getSourceBuffer() );
final byte[] dest = new byte[ ( int ) Intervals.numElements( size ) ];
processorUnsignedByte.compute( processorUnsignedByte.getSourceBuffer(), dest );
final RandomAccessibleInterval< UnsignedByteType > destImg = ArrayImgs.unsignedBytes( dest, size[ 0 ], size[ 1 ], size[ 2 ] );
diff --git a/src/test/java/net/imglib2/algorithm/blocks/transform/TransformBenchmark3DonlyCompute.java b/src/test/java/net/imglib2/algorithm/blocks/transform/TransformBenchmark3DonlyCompute.java
index 95d6525e6..987e14778 100644
--- a/src/test/java/net/imglib2/algorithm/blocks/transform/TransformBenchmark3DonlyCompute.java
+++ b/src/test/java/net/imglib2/algorithm/blocks/transform/TransformBenchmark3DonlyCompute.java
@@ -39,6 +39,7 @@
import java.util.concurrent.TimeUnit;
import net.imglib2.FinalInterval;
import net.imglib2.RandomAccessibleInterval;
+import net.imglib2.algorithm.blocks.BlockSupplier;
import net.imglib2.algorithm.blocks.transform.Transform.Interpolation;
import net.imglib2.blocks.PrimitiveBlocks;
import net.imglib2.converter.Converters;
@@ -110,13 +111,14 @@ public TransformBenchmark3DonlyCompute()
blocksnaiveSetup();
}
- PrimitiveBlocks< FloatType > blocks;
+ BlockSupplier< FloatType > blocks;
Affine3DProcessor< float[] > processor;
float[] dest;
+ float[] src;
public void blocksnaiveSetup()
{
- blocks = PrimitiveBlocks.of(
+ blocks = BlockSupplier.of(
Converters.convert(
Views.extendZero( img ),
new RealFloatConverter<>(),
@@ -125,14 +127,15 @@ public void blocksnaiveSetup()
long[] max = new long[ size.length ];
Arrays.setAll( max, d -> min[ d ] + size[ d ] - 1 );
processor.setTargetInterval( FinalInterval.wrap( min, max ) );
- blocks.copy( processor.getSourcePos(), processor.getSourceBuffer(), processor.getSourceSize() );
+ src = processor.getSourceBuffer();
+ blocks.copy( processor.getSourceInterval(), src );
dest = new float[ ( int ) Intervals.numElements( size ) ];
}
@Benchmark
public void compute()
{
- processor.compute( processor.getSourceBuffer(), dest );
+ processor.compute( src, dest );
}
public static void main( String[] args ) throws RunnerException
diff --git a/src/test/java/net/imglib2/algorithm/blocks/transform/TransformPlayground3D.java b/src/test/java/net/imglib2/algorithm/blocks/transform/TransformPlayground3D.java
index b85b9d534..e4b19c0ec 100644
--- a/src/test/java/net/imglib2/algorithm/blocks/transform/TransformPlayground3D.java
+++ b/src/test/java/net/imglib2/algorithm/blocks/transform/TransformPlayground3D.java
@@ -45,6 +45,7 @@
import net.imglib2.RealRandomAccessible;
import net.imglib2.algorithm.blocks.BlockSupplier;
import net.imglib2.algorithm.blocks.transform.Transform.Interpolation;
+import net.imglib2.blocks.BlockInterval;
import net.imglib2.img.Img;
import net.imglib2.img.array.ArrayImg;
import net.imglib2.img.array.ArrayImgFactory;
@@ -107,7 +108,7 @@ public static void main( String[] args )
.of( Views.extendZero( img ) )
.andThen( Transform.affine( affine, Interpolation.NLINEAR ) );
final byte[] dest = new byte[ ( int ) Intervals.numElements( size ) ];
- blocks.copy( min, dest, size );
+ blocks.copy( BlockInterval.wrap( min, size ), dest );
final RandomAccessibleInterval< UnsignedByteType > destImg = ArrayImgs.unsignedBytes( dest, size[ 0 ], size[ 1 ], size[ 2 ] );
// ----------------------------------------------