From 7d426d42f600a4a2ff4af1209b0f4f6f0e0da2d6 Mon Sep 17 00:00:00 2001 From: Gabriel Selzer Date: Mon, 24 Feb 2025 15:27:36 -0600 Subject: [PATCH 01/11] ImagePlusAdapter -> ImagePlusToImgPlus --- .../net/imglib2/imagej/ImageJFunctions.java | 61 ------------------- ...usAdapter.java => ImagePlusToImgPlus.java} | 16 ++--- .../imagej/imageplus/ImagePlusImgs.java | 3 +- .../java/net/imglib2/imagej/io/IJLoader.java | 6 +- .../imagej/ImagePlusToImgLib2Benchmark.java | 9 ++- .../ImagePlusToImgLib2PerformanceTest.java | 3 +- ...rTest.java => ImgPlusToImagePlusTest.java} | 6 +- .../display/ImageJFunctionBehavior.java | 17 +++--- .../imageplus/VirtualStackAdapterTest.java | 13 ++-- .../java/net/imglib2/imagej/io/LoadTest.java | 4 +- 10 files changed, 39 insertions(+), 99 deletions(-) rename src/main/java/net/imglib2/imagej/{imageplus/ImagePlusAdapter.java => ImagePlusToImgPlus.java} (94%) rename src/test/java/net/imglib2/imagej/{imageplus/ImagePlusAdapterTest.java => ImgPlusToImagePlusTest.java} (97%) diff --git a/src/main/java/net/imglib2/imagej/ImageJFunctions.java b/src/main/java/net/imglib2/imagej/ImageJFunctions.java index 7aa3cd3..68d10fd 100644 --- a/src/main/java/net/imglib2/imagej/ImageJFunctions.java +++ b/src/main/java/net/imglib2/imagej/ImageJFunctions.java @@ -50,9 +50,7 @@ import net.imglib2.imagej.display.ImageJVirtualStackFloat; import net.imglib2.imagej.display.ImageJVirtualStackUnsignedByte; import net.imglib2.imagej.display.ImageJVirtualStackUnsignedShort; -import net.imglib2.imagej.imageplus.ImagePlusAdapter; import net.imglib2.img.Img; -import net.imglib2.type.NativeType; import net.imglib2.type.logic.BitType; import net.imglib2.type.numeric.ARGBType; import net.imglib2.type.numeric.ComplexType; @@ -60,7 +58,6 @@ import net.imglib2.type.numeric.NumericType; import net.imglib2.type.numeric.RealType; import net.imglib2.type.numeric.integer.UnsignedByteType; -import net.imglib2.type.numeric.integer.UnsignedIntType; import net.imglib2.type.numeric.integer.UnsignedShortType; import net.imglib2.type.numeric.real.FloatType; import net.imglib2.util.Cast; @@ -95,64 +92,6 @@ public class ImageJFunctions { final static AtomicInteger ai = new AtomicInteger(); - public static < T extends NumericType< T > & NativeType< T > > Img< T > wrap( final ImagePlus imp ) - { - return ImagePlusAdapter.wrap( imp ); - } - - @SuppressWarnings( "unchecked" ) - public static < T extends RealType< T > > Img< T > wrapReal( final ImagePlus imp ) - { - return ImagePlusAdapter.wrapReal( imp ); - } - - @SuppressWarnings( "unchecked" ) - public static < T extends RealType< T > & NativeType< T > > Img< T > wrapRealNative( final ImagePlus imp ) - { - return ImagePlusAdapter.wrapReal( imp ); - } - - @SuppressWarnings( "unchecked" ) - public static < T extends NumericType< T > > Img< T > wrapNumeric( final ImagePlus imp ) - { - return ImagePlusAdapter.wrapNumeric( imp ); - } - - public static < T extends NumericType< T > & NativeType< T > > Img< T > wrapNumericNative( final ImagePlus imp ) - { - return wrap( imp ); - } - - public static Img< UnsignedByteType > wrapByte( final ImagePlus imp ) - { - return ImagePlusAdapter.wrapByte( imp ); - } - - public static Img< UnsignedShortType > wrapShort( final ImagePlus imp ) - { - return ImagePlusAdapter.wrapShort( imp ); - } - - public static Img< UnsignedIntType > wrapInt( final ImagePlus imp ) - { - return ImagePlusAdapter.wrapInt( imp ); - } - - public static Img< ARGBType > wrapRGBA( final ImagePlus imp ) - { - return ImagePlusAdapter.wrapRGBA( imp ); - } - - public static Img< FloatType > wrapFloat( final ImagePlus imp ) - { - return ImagePlusAdapter.wrapFloat( imp ); - } - - public static Img< FloatType > convertFloat( final ImagePlus imp ) - { - return ImagePlusAdapter.convertFloat( imp ); - } - /** * Display and return a single channel {@link ImagePlus}, wrapping a * {@link RandomAccessibleInterval}. The image type of the result diff --git a/src/main/java/net/imglib2/imagej/imageplus/ImagePlusAdapter.java b/src/main/java/net/imglib2/imagej/ImagePlusToImgPlus.java similarity index 94% rename from src/main/java/net/imglib2/imagej/imageplus/ImagePlusAdapter.java rename to src/main/java/net/imglib2/imagej/ImagePlusToImgPlus.java index 3684341..9ab8745 100644 --- a/src/main/java/net/imglib2/imagej/imageplus/ImagePlusAdapter.java +++ b/src/main/java/net/imglib2/imagej/ImagePlusToImgPlus.java @@ -32,14 +32,14 @@ * #L% */ -package net.imglib2.imagej.imageplus; +package net.imglib2.imagej; import net.imagej.ImgPlus; import net.imagej.axis.Axes; import net.imglib2.Cursor; import net.imglib2.converter.Converter; import net.imglib2.imagej.display.CalibrationUtils; -import net.imglib2.imagej.ImageJFunctions; +import net.imglib2.imagej.imageplus.*; import net.imglib2.img.Img; import net.imglib2.type.NativeType; import net.imglib2.type.Type; @@ -62,10 +62,10 @@ * @author Stephan Preibisch * @author Stephan Saalfeld */ -public class ImagePlusAdapter +public class ImagePlusToImgPlus { @SuppressWarnings( "unchecked" ) - public static < T extends NumericType< T > & NativeType< T > > ImagePlusImg< T, ? > wrap( final ImagePlus imp ) + public static < T extends NumericType< T > & NativeType< T > > ImagePlusImg< T, ? > wrap(final ImagePlus imp ) { return ( ImagePlusImg< T, ? > ) wrapLocal( imp ); } @@ -144,7 +144,7 @@ protected static < T extends NumericType< T > & NativeType< T > > void setAxesFr } - public static ByteImagePlus< UnsignedByteType > wrapByte( final ImagePlus imp ) + public static ByteImagePlus< UnsignedByteType > wrapByte(final ImagePlus imp ) { if ( imp.getType() != ImagePlus.GRAY8 ) return null; @@ -160,7 +160,7 @@ public static ByteImagePlus< UnsignedByteType > wrapByte( final ImagePlus imp ) return container; } - public static ShortImagePlus< UnsignedShortType > wrapShort( final ImagePlus imp ) + public static ShortImagePlus< UnsignedShortType > wrapShort(final ImagePlus imp ) { if ( imp.getType() != ImagePlus.GRAY16 ) return null; @@ -176,7 +176,7 @@ public static ShortImagePlus< UnsignedShortType > wrapShort( final ImagePlus imp return container; } - public static IntImagePlus< UnsignedIntType > wrapInt( final ImagePlus imp ) + public static IntImagePlus< UnsignedIntType > wrapInt(final ImagePlus imp ) { if( imp.getType() != ImagePlus.COLOR_RGB ) return null; @@ -208,7 +208,7 @@ public static IntImagePlus< ARGBType > wrapRGBA( final ImagePlus imp ) return container; } - public static FloatImagePlus< FloatType > wrapFloat( final ImagePlus imp ) + public static FloatImagePlus< FloatType > wrapFloat(final ImagePlus imp ) { if ( imp.getType() != ImagePlus.GRAY32 ) return null; diff --git a/src/main/java/net/imglib2/imagej/imageplus/ImagePlusImgs.java b/src/main/java/net/imglib2/imagej/imageplus/ImagePlusImgs.java index 0161eaf..5e765cf 100644 --- a/src/main/java/net/imglib2/imagej/imageplus/ImagePlusImgs.java +++ b/src/main/java/net/imglib2/imagej/imageplus/ImagePlusImgs.java @@ -34,6 +34,7 @@ package net.imglib2.imagej.imageplus; +import net.imglib2.imagej.ImagePlusToImgPlus; import net.imglib2.img.basictypeaccess.array.DoubleArray; import net.imglib2.type.NativeType; import net.imglib2.type.Type; @@ -206,6 +207,6 @@ final static public FloatImagePlus< ComplexFloatType > complexFloats( final long */ final static public < T extends NumericType< T > & NativeType< T > > ImagePlusImg< T, ? > from( final ImagePlus imp ) { - return ImagePlusAdapter.< T >wrap( imp ); + return ImagePlusToImgPlus.< T >wrap( imp ); } } diff --git a/src/main/java/net/imglib2/imagej/io/IJLoader.java b/src/main/java/net/imglib2/imagej/io/IJLoader.java index 1184b84..2e3db3c 100644 --- a/src/main/java/net/imglib2/imagej/io/IJLoader.java +++ b/src/main/java/net/imglib2/imagej/io/IJLoader.java @@ -35,8 +35,8 @@ import ij.IJ; import net.imglib2.cache.CacheLoader; +import net.imglib2.imagej.ImagePlusToImgPlus; import net.imglib2.img.Img; -import net.imglib2.imagej.ImageJFunctions; import net.imglib2.img.planar.PlanarImg; import net.imglib2.type.NativeType; import net.imglib2.type.numeric.NumericType; @@ -45,7 +45,7 @@ * An ImageJ-powered implementation of a disk-based {@link CacheLoader}: * the file system is the cache, and requests to load image file paths * are executed using ImageJ's {@link IJ#openImage(java.lang.String)}, - * and wrapped as {@link PlanarImg} via the {@link ImageJFunctions#wrap(ij.ImagePlus)}. + * and wrapped as {@link PlanarImg} via the {@link net.imglib2.imagej.ImagePlusToImgPlus#wrap(ij.ImagePlus)}. * * @author Albert Cardona * @@ -56,6 +56,6 @@ public class IJLoader< T extends NumericType< T > & NativeType< T > > implements @Override public Img< T > get( final String path ) { - return ImageJFunctions.wrap( IJ.openImage( path ) ); + return ImagePlusToImgPlus.wrap( IJ.openImage( path ) ); } } diff --git a/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2Benchmark.java b/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2Benchmark.java index 5b19e2a..8899946 100644 --- a/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2Benchmark.java +++ b/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2Benchmark.java @@ -36,7 +36,6 @@ import net.imagej.ImgPlus; import net.imglib2.RandomAccessibleInterval; import net.imglib2.imagej.imageplus.ByteImagePlus; -import net.imglib2.imagej.imageplus.ImagePlusAdapter; import net.imglib2.imagej.imageplus.VirtualStackAdapter; import net.imglib2.type.numeric.integer.UnsignedByteType; import net.imglib2.view.Views; @@ -82,23 +81,23 @@ public void wrapWide() @Benchmark public void wrapSmallOld() { - ImagePlusAdapter.wrap( small ); + ImagePlusToImgPlus.wrap( small ); } @Benchmark public void wrapDeepOld() { - ImagePlusAdapter.wrap( deep ); + ImagePlusToImgPlus.wrap( deep ); } @Benchmark public void wrapWideOld() { - ImagePlusAdapter.wrap( wide ); + ImagePlusToImgPlus.wrap( wide ); } private final ImgPlus< UnsignedByteType > wrapped = VirtualStackAdapter.wrapByte( imageForIteration ); - private final ByteImagePlus< UnsignedByteType > wrappedOld = ImagePlusAdapter.wrapByte( imageForIteration ); + private final ByteImagePlus< UnsignedByteType > wrappedOld = ImagePlusToImgPlus.wrapByte( imageForIteration ); @Benchmark public void iterateWrapped() diff --git a/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2PerformanceTest.java b/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2PerformanceTest.java index 09824ab..be1c270 100644 --- a/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2PerformanceTest.java +++ b/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2PerformanceTest.java @@ -38,7 +38,6 @@ import java.util.concurrent.atomic.AtomicInteger; import net.imglib2.RandomAccessibleInterval; -import net.imglib2.imagej.imageplus.ImagePlusAdapter; import net.imglib2.imagej.imageplus.VirtualStackAdapter; import net.imglib2.img.Img; import net.imglib2.type.numeric.RealType; @@ -79,7 +78,7 @@ public void testIterateImagePlusAdapter() { final AtomicInteger counter = new AtomicInteger(); final ImagePlus image = countingImagePlus( counter ); - final Img< ? extends RealType< ? > > img = ImagePlusAdapter.wrapByte( image ); + final Img< ? extends RealType< ? > > img = ImagePlusToImgPlus.wrapByte( image ); runFlatIteration( Views.permute( img, 0, 2 ) ); assertTrue( counter.get() < 120 ); // don't call getProcessor too often } diff --git a/src/test/java/net/imglib2/imagej/imageplus/ImagePlusAdapterTest.java b/src/test/java/net/imglib2/imagej/ImgPlusToImagePlusTest.java similarity index 97% rename from src/test/java/net/imglib2/imagej/imageplus/ImagePlusAdapterTest.java rename to src/test/java/net/imglib2/imagej/ImgPlusToImagePlusTest.java index 5c92391..0a5c5c7 100644 --- a/src/test/java/net/imglib2/imagej/imageplus/ImagePlusAdapterTest.java +++ b/src/test/java/net/imglib2/imagej/ImgPlusToImagePlusTest.java @@ -32,7 +32,7 @@ * #L% */ -package net.imglib2.imagej.imageplus; +package net.imglib2.imagej; import static org.junit.Assert.assertEquals; @@ -47,7 +47,7 @@ import ij.gui.NewImage; import ij.measure.Calibration; -public class ImagePlusAdapterTest< T extends NumericType< T > & NativeType< T > > +public class ImgPlusToImagePlusTest< T extends NumericType< T > & NativeType< T > > { /** Which dimensions to test. */ @@ -88,7 +88,7 @@ public void testDimensionality() private void testDimensionality( final int[] dim, final float[] calibration ) { final ImagePlus imp = createCalibratedImagePlus( dim, calibration ); - final ImgPlus< T > img = ImagePlusAdapter.wrapImgPlus( imp ); + final ImgPlus< T > img = ImagePlusToImgPlus.wrapImgPlus( imp ); // Print stuff // System.out.println( "got: " + img.getName() ); // for ( int d = 0; d < img.numDimensions(); d++ ) diff --git a/src/test/java/net/imglib2/imagej/display/ImageJFunctionBehavior.java b/src/test/java/net/imglib2/imagej/display/ImageJFunctionBehavior.java index 0296c7d..3e91a4e 100644 --- a/src/test/java/net/imglib2/imagej/display/ImageJFunctionBehavior.java +++ b/src/test/java/net/imglib2/imagej/display/ImageJFunctionBehavior.java @@ -35,6 +35,7 @@ package net.imglib2.imagej.display; import net.imglib2.imagej.ImageJFunctions; +import net.imglib2.imagej.ImagePlusToImgPlus; import net.imglib2.img.Img; import net.imglib2.type.numeric.ARGBType; import net.imglib2.type.numeric.integer.UnsignedByteType; @@ -69,36 +70,36 @@ static public final void main( final String[] arg ) // 1. Test ImagePlus -> Img, specific wrappers IJ.run( imp, "8-bit", "" ); - final Img< UnsignedByteType > imgb = ImageJFunctions.wrapByte( imp ); + final Img< UnsignedByteType > imgb = ImagePlusToImgPlus.wrapByte( imp ); print( imgb ); IJ.run( imp, "16-bit", "" ); - final Img< UnsignedShortType > imgs = ImageJFunctions.wrapShort( imp ); + final Img< UnsignedShortType > imgs = ImagePlusToImgPlus.wrapShort( imp ); print( imgs ); IJ.run( imp, "32-bit", "" ); - final Img< FloatType > imgf = ImageJFunctions.wrapFloat( imp ); + final Img< FloatType > imgf = ImagePlusToImgPlus.wrapFloat( imp ); print( imgf ); IJ.run( imp, "RGB Color", "" ); - final Img< ARGBType > imgRGB = ImageJFunctions.wrapRGBA( imp ); + final Img< ARGBType > imgRGB = ImagePlusToImgPlus.wrapRGBA( imp ); print( imgRGB ); // 2. Test ImagePlus -> Img, generic wrapper IJ.run( imp, "8-bit", "" ); - final Img< UnsignedByteType > g_imgb = ImageJFunctions.wrap( imp ); + final Img< UnsignedByteType > g_imgb = ImagePlusToImgPlus.wrap( imp ); print( g_imgb ); IJ.run( imp, "16-bit", "" ); - final Img< UnsignedShortType > g_imgs = ImageJFunctions.wrap( imp ); + final Img< UnsignedShortType > g_imgs = ImagePlusToImgPlus.wrap( imp ); print( g_imgs ); IJ.run( imp, "32-bit", "" ); - final Img< FloatType > g_imgf = ImageJFunctions.wrap( imp ); + final Img< FloatType > g_imgf = ImagePlusToImgPlus.wrap( imp ); print( g_imgf ); IJ.run( imp, "RGB Color", "" ); - final Img< ARGBType > g_imgRGB = ImageJFunctions.wrap( imp ); + final Img< ARGBType > g_imgRGB = ImagePlusToImgPlus.wrap( imp ); print( g_imgRGB ); // 3. Test Img -> ImagePlus, specific wrappers diff --git a/src/test/java/net/imglib2/imagej/imageplus/VirtualStackAdapterTest.java b/src/test/java/net/imglib2/imagej/imageplus/VirtualStackAdapterTest.java index cca5aad..d26877d 100644 --- a/src/test/java/net/imglib2/imagej/imageplus/VirtualStackAdapterTest.java +++ b/src/test/java/net/imglib2/imagej/imageplus/VirtualStackAdapterTest.java @@ -35,6 +35,7 @@ package net.imglib2.imagej.imageplus; import net.imglib2.imagej.ImageJFunctions; +import net.imglib2.imagej.ImagePlusToImgPlus; import net.imglib2.img.Img; import net.imglib2.test.ImgLib2Assert; import net.imglib2.test.RandomImgs; @@ -65,7 +66,7 @@ public void testUnsignedByte() { final ImagePlus image = randomImagePlus( 123, new UnsignedByteType(), DIMENSIONS ); final Img< UnsignedByteType > actual = VirtualStackAdapter.wrapByte( image ); - final Img< UnsignedByteType > expected = ImagePlusAdapter.wrapByte( image ); + final Img< UnsignedByteType > expected = ImagePlusToImgPlus.wrapByte( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -74,7 +75,7 @@ public void testUnsignedShort() { final ImagePlus image = randomImagePlus( 234, new UnsignedShortType(), DIMENSIONS ); final Img< UnsignedShortType > actual = VirtualStackAdapter.wrapShort( image ); - final Img< UnsignedShortType > expected = ImagePlusAdapter.wrapShort( image ); + final Img< UnsignedShortType > expected = ImagePlusToImgPlus.wrapShort( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -83,7 +84,7 @@ public void testRGB() { final ImagePlus image = randomImagePlus( 345, new ARGBType(), DIMENSIONS ); final Img< ARGBType > actual = VirtualStackAdapter.wrapRGBA( image ); - final Img< ARGBType > expected = ImagePlusAdapter.wrapRGBA( image ); + final Img< ARGBType > expected = ImagePlusToImgPlus.wrapRGBA( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -92,7 +93,7 @@ public void testFloat() { final ImagePlus image = randomImagePlus( 456, new FloatType(), DIMENSIONS ); final Img< FloatType > actual = VirtualStackAdapter.wrapFloat( image ); - final Img< FloatType > expected = ImagePlusAdapter.wrapFloat( image ); + final Img< FloatType > expected = ImagePlusToImgPlus.wrapFloat( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -101,7 +102,7 @@ public void testLowerNumDimensions() { final ImagePlus image = randomImagePlus( 567, new UnsignedByteType(), 2, 3, 6 ); final Img< UnsignedByteType > actual = VirtualStackAdapter.wrapByte( image ); - final Img< UnsignedByteType > expected = ImagePlusAdapter.wrapByte( image ); + final Img< UnsignedByteType > expected = ImagePlusToImgPlus.wrapByte( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -110,7 +111,7 @@ public void testSingletonDimensions() { final ImagePlus image = randomImagePlus( 678, new UnsignedByteType(), 2, 1, 1, 6 ); final Img< UnsignedByteType > actual = VirtualStackAdapter.wrapByte( image ); - final Img< UnsignedByteType > expected = ImagePlusAdapter.wrapByte( image ); + final Img< UnsignedByteType > expected = ImagePlusToImgPlus.wrapByte( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } diff --git a/src/test/java/net/imglib2/imagej/io/LoadTest.java b/src/test/java/net/imglib2/imagej/io/LoadTest.java index 690ee9e..691054a 100644 --- a/src/test/java/net/imglib2/imagej/io/LoadTest.java +++ b/src/test/java/net/imglib2/imagej/io/LoadTest.java @@ -46,10 +46,10 @@ import net.imglib2.Cursor; import net.imglib2.RandomAccessibleInterval; import net.imglib2.cache.img.CachedCellImg; +import net.imglib2.imagej.ImagePlusToImgPlus; import net.imglib2.img.array.ArrayImg; import net.imglib2.img.array.ArrayImgs; import net.imglib2.img.basictypeaccess.array.ArrayDataAccess; -import net.imglib2.imagej.ImageJFunctions; import net.imglib2.type.numeric.integer.UnsignedShortType; import net.imglib2.view.IntervalView; import net.imglib2.view.Views; @@ -125,7 +125,7 @@ public void testStackDefault() { final RandomAccessibleInterval< ? > img = Views.stack( Arrays.stream( paths ) .map( IJ::openImage ) - .map( ImageJFunctions::wrap ) + .map( ImagePlusToImgPlus::wrap ) .collect( Collectors.toList() ) ); show( ( RandomAccessibleInterval< UnsignedShortType > )img, "stack", 1, ( int )img.dimension( 2 ), ( int )img.dimension( 3 ) ); From b9b4116a24317c5a3ead4e691d2683f21d3642f9 Mon Sep 17 00:00:00 2001 From: Gabriel Selzer Date: Mon, 24 Feb 2025 16:21:41 -0600 Subject: [PATCH 02/11] Extract ImageJFunctions.wrap to RAIToImagePlus --- .../net/imglib2/imagej/ImageJFunctions.java | 278 +--------------- .../net/imglib2/imagej/RAIToImagePlus.java | 313 ++++++++++++++++++ .../display/ImageJFunctionBehavior.java | 27 +- .../ImageJFunctionDatasetTransformation.java | 4 +- .../display/ImageJVirtualStackTest.java | 23 +- .../imageplus/VirtualStackAdapterTest.java | 8 +- 6 files changed, 343 insertions(+), 310 deletions(-) create mode 100644 src/main/java/net/imglib2/imagej/RAIToImagePlus.java diff --git a/src/main/java/net/imglib2/imagej/ImageJFunctions.java b/src/main/java/net/imglib2/imagej/ImageJFunctions.java index 68d10fd..4751540 100644 --- a/src/main/java/net/imglib2/imagej/ImageJFunctions.java +++ b/src/main/java/net/imglib2/imagej/ImageJFunctions.java @@ -34,36 +34,25 @@ package net.imglib2.imagej; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.atomic.AtomicInteger; - -import net.imagej.ImgPlus; -import net.imglib2.Dimensions; +import ij.ImagePlus; import net.imglib2.RandomAccessibleInterval; -import net.imglib2.converter.ComplexPowerGLogFloatConverter; import net.imglib2.converter.Converter; import net.imglib2.converter.Converters; -import net.imglib2.converter.RealUnsignedByteConverter; -import net.imglib2.imagej.display.CalibrationUtils; import net.imglib2.imagej.display.ImageJVirtualStack; -import net.imglib2.imagej.display.ImageJVirtualStackARGB; import net.imglib2.imagej.display.ImageJVirtualStackFloat; -import net.imglib2.imagej.display.ImageJVirtualStackUnsignedByte; -import net.imglib2.imagej.display.ImageJVirtualStackUnsignedShort; import net.imglib2.img.Img; -import net.imglib2.type.logic.BitType; import net.imglib2.type.numeric.ARGBType; import net.imglib2.type.numeric.ComplexType; -import net.imglib2.type.numeric.IntegerType; import net.imglib2.type.numeric.NumericType; import net.imglib2.type.numeric.RealType; import net.imglib2.type.numeric.integer.UnsignedByteType; import net.imglib2.type.numeric.integer.UnsignedShortType; import net.imglib2.type.numeric.real.FloatType; -import net.imglib2.util.Cast; -import ij.ImagePlus; -import ij.VirtualStack; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.AtomicInteger; + +import static net.imglib2.imagej.RAIToImagePlus.*; /** * Provides static convenience methods to facilitate interacting with ImageJ @@ -150,56 +139,6 @@ public static < T extends ComplexType< T > > ImagePlus show( return show( img, converter, title, null ); } - /** - * Create a single channel {@link ImagePlus} from a - * {@link RandomAccessibleInterval}. The image type of the result - * (ImagePlus.GRAY8, ImagePlus.GRAY16, ImagePlus.GRAY32, ImagePlus.COLOR_256 - * or ImagePlus.COLOR_RGB) is inferred from the generic type of the input - * {@link RandomAccessibleInterval}. - */ - @SuppressWarnings( { "unchecked", "rawtypes" } ) - public static < T extends NumericType< T > > ImagePlus wrap( final RandomAccessibleInterval< T > img, final String title, - final ExecutorService service ) - { - ImagePlus target; - final T t = img.getType(); - - if ( t instanceof ARGBType ) - target = wrapRGB( Cast.unchecked( img ), title, service ); - else if ( t instanceof UnsignedByteType ) - target = wrapUnsignedByte( Cast.unchecked( img ), title, service ); - else if ( t instanceof BitType ) - target = wrapBit( Cast.unchecked( img ), title, service ); - else if ( t instanceof IntegerType ) - target = wrapUnsignedShort( Cast.unchecked( img ), title, service ); - else if ( t instanceof RealType ) - target = wrapFloat( Cast.unchecked( img ), title, service ); - else if ( t instanceof ComplexType ) - target = wrapFloat( Cast.unchecked( img ), new ComplexPowerGLogFloatConverter(), title, service ); - else - { - System.out.println( "Do not know how to display Type " + t.getClass().getSimpleName() ); - target = null; - } - - // Retrieve and set calibration if we can. ImgPlus has calibration and - // axis types - if ( null != target && img instanceof ImgPlus ) - { - - final ImgPlus< T > imgplus = ( ImgPlus< T > ) img; - CalibrationUtils.copyCalibrationToImagePlus( imgplus, target ); - target.setTitle( imgplus.getName() ); - } - - return target; - } - - public static < T extends NumericType< T > > ImagePlus wrap( final RandomAccessibleInterval< T > img, final String title ) - { - return wrap( img, title, null ); - } - public static < T extends NumericType< T > > ImagePlus show( final RandomAccessibleInterval< T > img, final String title, final ExecutorService service ) { @@ -218,75 +157,6 @@ public static < T extends NumericType< T > > ImagePlus show( final RandomAccessi return show( img, title, null ); } - /** - * Create a single channel 32-bit float {@link ImagePlus} from a - * {@link RandomAccessibleInterval} using a custom {@link Converter}. - */ - public static < T extends RealType< T > > ImagePlus wrapFloat( - final RandomAccessibleInterval< T > img, - final String title, - final ExecutorService service ) - { - final ImageJVirtualStackFloat stack = ImageJVirtualStackFloat.wrap( img ); - stack.setExecutorService( service ); - return makeImagePlus( img, stack, title ); - } - - public static < T extends RealType< T > > ImagePlus wrapFloat( - final RandomAccessibleInterval< T > img, - final String title ) - { - return wrapFloat( img, title, null ); - } - - private static ImagePlus makeImagePlus( final Dimensions dims, final VirtualStack stack, final String title ) - { - final ImagePlus imp = new ImagePlus( title, stack ); - final int n = dims.numDimensions(); - if ( n > 2 ) - { - imp.setOpenAsHyperStack( true ); - final int c = ( int ) dims.dimension( 2 ), s, f; - if ( n > 3 ) - { - s = ( int ) dims.dimension( 3 ); - if ( n > 4 ) - f = ( int ) dims.dimension( 4 ); - else - f = 1; - } - else - { - s = 1; - f = 1; - } - imp.setDimensions( c, s, f ); - } - return imp; - } - - /** - * Create a single channel 32-bit float {@link ImagePlus} from a - * {@link RandomAccessibleInterval} using a custom {@link Converter}. - */ - public static < T > ImagePlus wrapFloat( - final RandomAccessibleInterval< T > img, - final Converter< T, FloatType > converter, - final String title, - final ExecutorService service ) - { - final ImageJVirtualStackFloat stack = new ImageJVirtualStackFloat( img, converter, service ); - return makeImagePlus( img, stack, title ); - } - - public static < T > ImagePlus wrapFloat( - final RandomAccessibleInterval< T > img, - final Converter< T, FloatType > converter, - final String title ) - { - return wrapFloat( img, converter, title, null ); - } - /** * Show a {@link RandomAccessibleInterval} as single channel 32-bit float * {@link ImagePlus} using a custom {@link Converter}. @@ -342,39 +212,6 @@ public static < T extends RealType< T > > ImagePlus showFloat( final RandomAcces return showFloat( img, ( ExecutorService ) null ); } - /** - * Create a 24bit RGB {@link ImagePlus} from a - * {@link RandomAccessibleInterval} a using a default (identity) - * {@link Converter}. - */ - public static ImagePlus wrapRGB( final RandomAccessibleInterval< ARGBType > img, final String title, - final ExecutorService service ) - { - final ImageJVirtualStackARGB stack = ImageJVirtualStackARGB.wrap( img ); - stack.setExecutorService(service); - return makeImagePlus( img, stack, title ); - } - - public static ImagePlus wrapRGB( final RandomAccessibleInterval< ARGBType > img, final String title ) - { - return wrapRGB( img, title, null ); - } - - /** - * Create a 24bit RGB {@link ImagePlus} from a - * {@link RandomAccessibleInterval} a using a custom {@link Converter}. - */ - public static < T > ImagePlus wrapRGB( final RandomAccessibleInterval< T > img, final Converter< T, ARGBType > converter, final String title, - final ExecutorService service ) - { - return wrapRGB( Converters.convert( img, converter, new ARGBType() ), title, service ); - } - - public static < T > ImagePlus wrapRGB( final RandomAccessibleInterval< T > img, final Converter< T, ARGBType > converter, final String title ) - { - return wrapRGB( img, converter, title, null ); - } - /** * Show a {@link RandomAccessibleInterval} as 24bit RGB {@link ImagePlus} * using a custom {@link Converter}. @@ -395,68 +232,6 @@ public static < T > ImagePlus showRGB( final RandomAccessibleInterval< T > img, return showRGB( img, converter, title, null ); } - /** - * Create a single channel 8-bit unsigned integer {@link ImagePlus} from a - * {@link RandomAccessibleInterval} using a custom {@link Converter}. - */ - public static < T extends RealType< T > > ImagePlus wrapUnsignedByte( - final RandomAccessibleInterval< T > img, - final String title, - final ExecutorService service ) - { - final ImageJVirtualStackUnsignedByte stack = ImageJVirtualStackUnsignedByte.wrap( img ); - stack.setExecutorService( service ); - return makeImagePlus( img, stack, title ); - } - - public static < T extends RealType< T > > ImagePlus wrapUnsignedByte( - final RandomAccessibleInterval< T > img, - final String title ) - { - return wrapUnsignedByte( img, title, null ); - } - - /** - * Create a single channel 8-bit unsigned integer {@link ImagePlus} from a - * BitType {@link RandomAccessibleInterval} using a custom {@link Converter} - * . - */ - public static < T extends RealType< T > > ImagePlus wrapBit( - final RandomAccessibleInterval< T > img, - final String title, - final ExecutorService service ) - { - return wrapUnsignedByte( img, new RealUnsignedByteConverter< T >( 0, 1 ), title, service ); - } - - public static < T extends RealType< T > > ImagePlus wrapBit( - final RandomAccessibleInterval< T > img, - final String title ) - { - return wrapBit( img, title, null ); - } - - /** - * Create a single channel 8-bit unsigned integer {@link ImagePlus} from a - * {@link RandomAccessibleInterval} using a custom {@link Converter}. - */ - public static < T > ImagePlus wrapUnsignedByte( - final RandomAccessibleInterval< T > img, - final Converter< T, UnsignedByteType > converter, - final String title, - final ExecutorService service ) - { - return wrapUnsignedByte( Converters.convert( img, converter, new UnsignedByteType() ), title, service ); - } - - public static < T > ImagePlus wrapUnsignedByte( - final RandomAccessibleInterval< T > img, - final Converter< T, UnsignedByteType > converter, - final String title ) - { - return wrapUnsignedByte( img, converter, title, null ); - } - /** * Show a {@link RandomAccessibleInterval} as single channel 8-bit unsigned * integer {@link ImagePlus} using a custom {@link Converter}. @@ -518,49 +293,6 @@ public static < T extends RealType< T > > ImagePlus showUnsignedByte( final Rand return showUnsignedByte( img, ( ExecutorService ) null ); } - /** - * Create a single channel 16-bit unsigned integer {@link ImagePlus} from a - * {@link RandomAccessibleInterval} using a default {@link Converter} (clamp - * values to range [0, 65535]). - */ - public static < T extends RealType< T > > ImagePlus wrapUnsignedShort( - final RandomAccessibleInterval< T > img, - final String title, - final ExecutorService service ) - { - final ImageJVirtualStackUnsignedShort stack = ImageJVirtualStackUnsignedShort.wrap( img ); - stack.setExecutorService( service ); - return makeImagePlus( img, stack, title ); - } - - public static < T extends RealType< T > > ImagePlus wrapUnsignedShort( - final RandomAccessibleInterval< T > img, - final String title ) - { - return wrapUnsignedShort( img, title, null ); - } - - /** - * Create a single channel 16-bit unsigned integer {@link ImagePlus} from a - * {@link RandomAccessibleInterval} using a custom {@link Converter}. - */ - public static < T > ImagePlus wrapUnsignedShort( - final RandomAccessibleInterval< T > img, - final Converter< T, UnsignedShortType > converter, - final String title, - final ExecutorService service ) - { - return wrapUnsignedShort( Converters.convert( img, converter, new UnsignedShortType() ), title, service ); - } - - public static < T > ImagePlus wrapUnsignedShort( - final RandomAccessibleInterval< T > img, - final Converter< T, UnsignedShortType > converter, - final String title ) - { - return wrapUnsignedShort( img, converter, title, null ); - } - /** * Show a {@link RandomAccessibleInterval} as single channel 16-bit unsigned * integer {@link ImagePlus} using a custom {@link Converter}. diff --git a/src/main/java/net/imglib2/imagej/RAIToImagePlus.java b/src/main/java/net/imglib2/imagej/RAIToImagePlus.java new file mode 100644 index 0000000..22b0c07 --- /dev/null +++ b/src/main/java/net/imglib2/imagej/RAIToImagePlus.java @@ -0,0 +1,313 @@ +package net.imglib2.imagej; + +import ij.ImagePlus; +import ij.VirtualStack; +import net.imagej.ImgPlus; +import net.imglib2.Dimensions; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.converter.ComplexPowerGLogFloatConverter; +import net.imglib2.converter.Converter; +import net.imglib2.converter.Converters; +import net.imglib2.converter.RealUnsignedByteConverter; +import net.imglib2.imagej.display.*; +import net.imglib2.type.logic.BitType; +import net.imglib2.type.numeric.*; +import net.imglib2.type.numeric.integer.UnsignedByteType; +import net.imglib2.type.numeric.integer.UnsignedShortType; +import net.imglib2.type.numeric.real.FloatType; +import net.imglib2.util.Cast; + +import java.util.concurrent.ExecutorService; + +/** + * Utilities for wrapping {@link RandomAccessibleInterval}s + * into {@link ImagePlus}es. + *

+ * Under the hood, conversion utilizes {@link ImageJVirtualStack}, + * meaning the resulting objects are read-only unless + * {@link ImageJVirtualStack#setWritable(boolean)} is called. + *

+ * + * @author Tobis Pietzsch + * @author Stephan Preibisch + * @author Stephan Saalfeld + */ +public class RAIToImagePlus { + + // Prevent instantiation of utility class + private RAIToImagePlus() {} + + /** + * Create a single channel {@link ImagePlus} from a + * {@link RandomAccessibleInterval}. The image type of the result + * (ImagePlus.GRAY8, ImagePlus.GRAY16, ImagePlus.GRAY32, ImagePlus.COLOR_256 + * or ImagePlus.COLOR_RGB) is inferred from the generic type of the input + * {@link RandomAccessibleInterval}. + * + * @param img the {@link RandomAccessibleInterval} to wrap + * @param title the name to assign to the wrapped {@link ImagePlus} + * @param service an {@link ExecutorService} to manage asynchronous tasks + * @return an {@link ImagePlus} wrapping {@code img} named {@code title} + */ + @SuppressWarnings( { "unchecked", "rawtypes" } ) + public static < T extends NumericType< T > > ImagePlus wrap( final RandomAccessibleInterval< T > img, final String title, + final ExecutorService service ) + { + ImagePlus target; + final T t = img.getType(); + + if ( t instanceof ARGBType ) + target = wrapRGB( Cast.unchecked( img ), title, service ); + else if ( t instanceof UnsignedByteType ) + target = wrapUnsignedByte( Cast.unchecked( img ), title, service ); + else if ( t instanceof BitType ) + target = wrapBit( Cast.unchecked( img ), title, service ); + else if ( t instanceof IntegerType ) + target = wrapUnsignedShort( Cast.unchecked( img ), title, service ); + else if ( t instanceof RealType ) + target = wrapFloat( Cast.unchecked( img ), title, service ); + else if ( t instanceof ComplexType ) + target = wrapFloat( Cast.unchecked( img ), new ComplexPowerGLogFloatConverter(), title, service ); + else + { + System.out.println( "Do not know how to display Type " + t.getClass().getSimpleName() ); + target = null; + } + + // Retrieve and set calibration if we can. ImgPlus has calibration and + // axis types + if ( null != target && img instanceof ImgPlus ) + { + + final ImgPlus< T > imgplus = ( ImgPlus< T > ) img; + CalibrationUtils.copyCalibrationToImagePlus( imgplus, target ); + target.setTitle( imgplus.getName() ); + } + + return target; + } + + /** + * Create a single channel {@link ImagePlus} from a + * {@link RandomAccessibleInterval}. The image type of the result + * (ImagePlus.GRAY8, ImagePlus.GRAY16, ImagePlus.GRAY32, ImagePlus.COLOR_256 + * or ImagePlus.COLOR_RGB) is inferred from the generic type of the input + * {@link RandomAccessibleInterval}. + * + * @param img the {@link RandomAccessibleInterval} to wrap + * @param title the name to assign to the wrapped {@link ImagePlus} + * @return an {@link ImagePlus} wrapping {@code img} named {@code title} + */ + public static < T extends NumericType< T > > ImagePlus wrap( final RandomAccessibleInterval< T > img, final String title ) + { + return wrap( img, title, null ); + } + + /** + * Create a single channel 32-bit float {@link ImagePlus} from a + * {@link RandomAccessibleInterval} using a custom {@link Converter}. + */ + public static < T extends RealType< T > > ImagePlus wrapFloat( + final RandomAccessibleInterval< T > img, + final String title, + final ExecutorService service ) + { + final ImageJVirtualStackFloat stack = ImageJVirtualStackFloat.wrap( img ); + stack.setExecutorService( service ); + return makeImagePlus( img, stack, title ); + } + + public static < T extends RealType< T > > ImagePlus wrapFloat( + final RandomAccessibleInterval< T > img, + final String title ) + { + return wrapFloat( img, title, null ); + } + + /** + * Create a single channel 32-bit float {@link ImagePlus} from a + * {@link RandomAccessibleInterval} using a custom {@link Converter}. + */ + public static < T > ImagePlus wrapFloat( + final RandomAccessibleInterval< T > img, + final Converter< T, FloatType> converter, + final String title, + final ExecutorService service ) + { + final ImageJVirtualStackFloat stack = new ImageJVirtualStackFloat( img, converter, service ); + return makeImagePlus( img, stack, title ); + } + + public static < T > ImagePlus wrapFloat( + final RandomAccessibleInterval< T > img, + final Converter< T, FloatType > converter, + final String title ) + { + return wrapFloat( img, converter, title, null ); + } + + /** + * Create a 24bit RGB {@link ImagePlus} from a + * {@link RandomAccessibleInterval} a using a default (identity) + * {@link Converter}. + */ + public static ImagePlus wrapRGB( final RandomAccessibleInterval< ARGBType > img, final String title, + final ExecutorService service ) + { + final ImageJVirtualStackARGB stack = ImageJVirtualStackARGB.wrap( img ); + stack.setExecutorService(service); + return makeImagePlus( img, stack, title ); + } + + public static ImagePlus wrapRGB( final RandomAccessibleInterval< ARGBType > img, final String title ) + { + return wrapRGB( img, title, null ); + } + + /** + * Create a 24bit RGB {@link ImagePlus} from a + * {@link RandomAccessibleInterval} a using a custom {@link Converter}. + */ + public static < T > ImagePlus wrapRGB( final RandomAccessibleInterval< T > img, final Converter< T, ARGBType > converter, final String title, + final ExecutorService service ) + { + return wrapRGB( Converters.convert( img, converter, new ARGBType() ), title, service ); + } + + public static < T > ImagePlus wrapRGB( final RandomAccessibleInterval< T > img, final Converter< T, ARGBType > converter, final String title ) + { + return wrapRGB( img, converter, title, null ); + } + + /** + * Create a single channel 8-bit unsigned integer {@link ImagePlus} from a + * {@link RandomAccessibleInterval} using a custom {@link Converter}. + */ + public static < T extends RealType< T > > ImagePlus wrapUnsignedByte( + final RandomAccessibleInterval< T > img, + final String title, + final ExecutorService service ) + { + final ImageJVirtualStackUnsignedByte stack = ImageJVirtualStackUnsignedByte.wrap( img ); + stack.setExecutorService( service ); + return makeImagePlus( img, stack, title ); + } + + public static < T extends RealType< T > > ImagePlus wrapUnsignedByte( + final RandomAccessibleInterval< T > img, + final String title ) + { + return wrapUnsignedByte( img, title, null ); + } + + /** + * Create a single channel 8-bit unsigned integer {@link ImagePlus} from a + * BitType {@link RandomAccessibleInterval} using a custom {@link Converter} + * . + */ + public static < T extends RealType< T > > ImagePlus wrapBit( + final RandomAccessibleInterval< T > img, + final String title, + final ExecutorService service ) + { + return wrapUnsignedByte( img, new RealUnsignedByteConverter< T >( 0, 1 ), title, service ); + } + + public static < T extends RealType< T > > ImagePlus wrapBit( + final RandomAccessibleInterval< T > img, + final String title ) + { + return wrapBit( img, title, null ); + } + + /** + * Create a single channel 8-bit unsigned integer {@link ImagePlus} from a + * {@link RandomAccessibleInterval} using a custom {@link Converter}. + */ + public static < T > ImagePlus wrapUnsignedByte( + final RandomAccessibleInterval< T > img, + final Converter< T, UnsignedByteType > converter, + final String title, + final ExecutorService service ) + { + return wrapUnsignedByte( Converters.convert( img, converter, new UnsignedByteType() ), title, service ); + } + + public static < T > ImagePlus wrapUnsignedByte( + final RandomAccessibleInterval< T > img, + final Converter< T, UnsignedByteType > converter, + final String title ) + { + return wrapUnsignedByte( img, converter, title, null ); + } + + /** + * Create a single channel 16-bit unsigned integer {@link ImagePlus} from a + * {@link RandomAccessibleInterval} using a default {@link Converter} (clamp + * values to range [0, 65535]). + */ + public static < T extends RealType< T > > ImagePlus wrapUnsignedShort( + final RandomAccessibleInterval< T > img, + final String title, + final ExecutorService service ) + { + final ImageJVirtualStackUnsignedShort stack = ImageJVirtualStackUnsignedShort.wrap( img ); + stack.setExecutorService( service ); + return makeImagePlus( img, stack, title ); + } + + public static < T extends RealType< T > > ImagePlus wrapUnsignedShort( + final RandomAccessibleInterval< T > img, + final String title ) + { + return wrapUnsignedShort( img, title, null ); + } + + /** + * Create a single channel 16-bit unsigned integer {@link ImagePlus} from a + * {@link RandomAccessibleInterval} using a custom {@link Converter}. + */ + public static < T > ImagePlus wrapUnsignedShort( + final RandomAccessibleInterval< T > img, + final Converter< T, UnsignedShortType> converter, + final String title, + final ExecutorService service ) + { + return wrapUnsignedShort( Converters.convert( img, converter, new UnsignedShortType() ), title, service ); + } + + public static < T > ImagePlus wrapUnsignedShort( + final RandomAccessibleInterval< T > img, + final Converter< T, UnsignedShortType > converter, + final String title ) + { + return wrapUnsignedShort( img, converter, title, null ); + } + + private static ImagePlus makeImagePlus( final Dimensions dims, final VirtualStack stack, final String title ) + { + final ImagePlus imp = new ImagePlus( title, stack ); + final int n = dims.numDimensions(); + if ( n > 2 ) + { + imp.setOpenAsHyperStack( true ); + final int c = ( int ) dims.dimension( 2 ), s, f; + if ( n > 3 ) + { + s = ( int ) dims.dimension( 3 ); + if ( n > 4 ) + f = ( int ) dims.dimension( 4 ); + else + f = 1; + } + else + { + s = 1; + f = 1; + } + imp.setDimensions( c, s, f ); + } + return imp; + } + +} diff --git a/src/test/java/net/imglib2/imagej/display/ImageJFunctionBehavior.java b/src/test/java/net/imglib2/imagej/display/ImageJFunctionBehavior.java index 3e91a4e..4dc42e6 100644 --- a/src/test/java/net/imglib2/imagej/display/ImageJFunctionBehavior.java +++ b/src/test/java/net/imglib2/imagej/display/ImageJFunctionBehavior.java @@ -34,17 +34,16 @@ package net.imglib2.imagej.display; -import net.imglib2.imagej.ImageJFunctions; +import ij.IJ; +import ij.ImagePlus; import net.imglib2.imagej.ImagePlusToImgPlus; +import net.imglib2.imagej.RAIToImagePlus; import net.imglib2.img.Img; import net.imglib2.type.numeric.ARGBType; import net.imglib2.type.numeric.integer.UnsignedByteType; import net.imglib2.type.numeric.integer.UnsignedShortType; import net.imglib2.type.numeric.real.FloatType; -import ij.IJ; -import ij.ImagePlus; - /** * TODO * @@ -52,12 +51,12 @@ public class ImageJFunctionBehavior { - static private final void print( final Img< ? > img ) + static private void print(final Img img) { System.out.println( "img: " + img ); } - static private final void print( final ImagePlus imp ) + static private void print(final ImagePlus imp) { System.out.println( "imp: " + imp ); } @@ -103,29 +102,29 @@ static public final void main( final String[] arg ) print( g_imgRGB ); // 3. Test Img -> ImagePlus, specific wrappers - final ImagePlus impb = ImageJFunctions.wrapUnsignedByte( imgb, "byte Img" ); + final ImagePlus impb = RAIToImagePlus.wrapUnsignedByte( imgb, "byte Img" ); print( impb ); - final ImagePlus imps = ImageJFunctions.wrapUnsignedShort( imgs, "short Img" ); + final ImagePlus imps = RAIToImagePlus.wrapUnsignedShort( imgs, "short Img" ); print( imps ); - final ImagePlus impf = ImageJFunctions.wrapFloat( imgf, "float Img" ); + final ImagePlus impf = RAIToImagePlus.wrapFloat( imgf, "float Img" ); print( impf ); - final ImagePlus impRGB = ImageJFunctions.wrapRGB( imgRGB, "RGB Img" ); + final ImagePlus impRGB = RAIToImagePlus.wrapRGB( imgRGB, "RGB Img" ); print( impRGB ); // 4. Test Img -> ImagePlus, generic wrappers - final ImagePlus g_impb = ImageJFunctions.wrap( imgb, "byte Img" ); + final ImagePlus g_impb = RAIToImagePlus.wrap( imgb, "byte Img" ); print( g_impb ); - final ImagePlus g_imps = ImageJFunctions.wrap( imgs, "short Img" ); + final ImagePlus g_imps = RAIToImagePlus.wrap( imgs, "short Img" ); print( g_imps ); - final ImagePlus g_impf = ImageJFunctions.wrap( imgf, "float Img" ); + final ImagePlus g_impf = RAIToImagePlus.wrap( imgf, "float Img" ); print( g_impf ); - final ImagePlus g_impRGB = ImageJFunctions.wrap( imgRGB, "RGB Img" ); + final ImagePlus g_impRGB = RAIToImagePlus.wrap( imgRGB, "RGB Img" ); print( g_impRGB ); } } diff --git a/src/test/java/net/imglib2/imagej/display/ImageJFunctionDatasetTransformation.java b/src/test/java/net/imglib2/imagej/display/ImageJFunctionDatasetTransformation.java index 691e3a0..66a8420 100644 --- a/src/test/java/net/imglib2/imagej/display/ImageJFunctionDatasetTransformation.java +++ b/src/test/java/net/imglib2/imagej/display/ImageJFunctionDatasetTransformation.java @@ -40,7 +40,7 @@ import ij.ImagePlus; import net.imglib2.Cursor; -import net.imglib2.imagej.ImageJFunctions; +import net.imglib2.imagej.RAIToImagePlus; import net.imglib2.img.Img; import net.imglib2.img.ImgFactory; import net.imglib2.img.cell.CellImgFactory; @@ -74,7 +74,7 @@ public void transformBitDataset() cursor.get().set( new BitType( true ) ); } - ImagePlus imp = ImageJFunctions.wrap( img1, "" ); + ImagePlus imp = RAIToImagePlus.wrap( img1, "" ); Assert.assertEquals( ImagePlus.GRAY8, imp.getType() ); Assert.assertEquals( 255, imp.getStatistics().min, 0 ); diff --git a/src/test/java/net/imglib2/imagej/display/ImageJVirtualStackTest.java b/src/test/java/net/imglib2/imagej/display/ImageJVirtualStackTest.java index 3c95e6d..d20eb4f 100644 --- a/src/test/java/net/imglib2/imagej/display/ImageJVirtualStackTest.java +++ b/src/test/java/net/imglib2/imagej/display/ImageJVirtualStackTest.java @@ -34,31 +34,22 @@ package net.imglib2.imagej.display; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertTrue; - +import ij.ImagePlus; +import ij.ImageStack; +import ij.VirtualStack; +import ij.process.*; import net.imglib2.RandomAccess; -import net.imglib2.imagej.ImageJFunctions; +import net.imglib2.imagej.RAIToImagePlus; import net.imglib2.img.Img; import net.imglib2.img.array.ArrayImgs; import net.imglib2.test.RandomImgs; import net.imglib2.type.numeric.ARGBType; import net.imglib2.type.numeric.integer.UnsignedByteType; - import net.imglib2.type.numeric.integer.UnsignedShortType; import net.imglib2.type.numeric.real.FloatType; import org.junit.Test; -import ij.ImagePlus; -import ij.ImageStack; -import ij.VirtualStack; -import ij.process.ByteProcessor; -import ij.process.ColorProcessor; -import ij.process.FloatProcessor; -import ij.process.ImageProcessor; -import ij.process.ShortProcessor; +import static org.junit.Assert.*; public class ImageJVirtualStackTest { @@ -243,7 +234,7 @@ public void testSetVoxels() { public void testProcessorPerPlane() { final Img< UnsignedByteType > expected = RandomImgs.seed(54321).nextImage( new UnsignedByteType(), 100, 100, 100 ); - final ImagePlus imagePlus = ImageJFunctions.wrap( expected, "title" ); + final ImagePlus imagePlus = RAIToImagePlus.wrap( expected, "title" ); final ImageStack stack = imagePlus.getStack(); final ImageProcessor p1 = stack.getProcessor( 1 ); final ImageProcessor p2 = stack.getProcessor( 2 ); diff --git a/src/test/java/net/imglib2/imagej/imageplus/VirtualStackAdapterTest.java b/src/test/java/net/imglib2/imagej/imageplus/VirtualStackAdapterTest.java index d26877d..b6dbbcc 100644 --- a/src/test/java/net/imglib2/imagej/imageplus/VirtualStackAdapterTest.java +++ b/src/test/java/net/imglib2/imagej/imageplus/VirtualStackAdapterTest.java @@ -34,8 +34,9 @@ package net.imglib2.imagej.imageplus; -import net.imglib2.imagej.ImageJFunctions; +import ij.ImagePlus; import net.imglib2.imagej.ImagePlusToImgPlus; +import net.imglib2.imagej.RAIToImagePlus; import net.imglib2.img.Img; import net.imglib2.test.ImgLib2Assert; import net.imglib2.test.RandomImgs; @@ -45,11 +46,8 @@ import net.imglib2.type.numeric.integer.UnsignedByteType; import net.imglib2.type.numeric.integer.UnsignedShortType; import net.imglib2.type.numeric.real.FloatType; - import org.junit.Test; -import ij.ImagePlus; - /** * Tests {@link VirtualStackAdapter}. * @@ -118,7 +116,7 @@ public void testSingletonDimensions() private < T extends NativeType< T > & NumericType< T > > ImagePlus randomImagePlus( final int seed, final T type, final long... dimensions ) { final Img< T > random = RandomImgs.seed(seed).nextImage( type, dimensions ); - return ImageJFunctions.wrap( random, "test" ); + return RAIToImagePlus.wrap( random, "test" ); } } From c74008a27c4bf363c58ab52d0030f47e76169e8e Mon Sep 17 00:00:00 2001 From: Gabriel Selzer Date: Mon, 24 Feb 2025 16:56:23 -0600 Subject: [PATCH 03/11] Combine VirtualStackAdapter, ImagePlusToImgPlus They are doing very similar things and people might miss VirtualStackAdapter's functionality if the name doesn't convey the purpose --- .../imglib2/imagej/ImagePlusToImgPlus.java | 160 +++++++++++++- .../imagej/imageplus/VirtualStackAdapter.java | 209 ------------------ .../imagej/ImagePlusToImgLib2Benchmark.java | 17 +- .../ImagePlusToImgLib2PerformanceTest.java | 7 +- .../display/PlanarImgToVirtualStackTest.java | 4 +- ...rTest.java => ImagePlusToImgPlusTest.java} | 28 +-- 6 files changed, 186 insertions(+), 239 deletions(-) delete mode 100644 src/main/java/net/imglib2/imagej/imageplus/VirtualStackAdapter.java rename src/test/java/net/imglib2/imagej/imageplus/{VirtualStackAdapterTest.java => ImagePlusToImgPlusTest.java} (75%) diff --git a/src/main/java/net/imglib2/imagej/ImagePlusToImgPlus.java b/src/main/java/net/imglib2/imagej/ImagePlusToImgPlus.java index 9ab8745..e76a338 100644 --- a/src/main/java/net/imglib2/imagej/ImagePlusToImgPlus.java +++ b/src/main/java/net/imglib2/imagej/ImagePlusToImgPlus.java @@ -36,12 +36,18 @@ import net.imagej.ImgPlus; import net.imagej.axis.Axes; +import net.imagej.axis.CalibratedAxis; import net.imglib2.Cursor; +import net.imglib2.cache.Cache; +import net.imglib2.cache.ref.SoftRefLoaderCache; import net.imglib2.converter.Converter; import net.imglib2.imagej.display.CalibrationUtils; import net.imglib2.imagej.imageplus.*; import net.imglib2.img.Img; +import net.imglib2.img.basictypeaccess.array.*; +import net.imglib2.img.planar.PlanarImg; import net.imglib2.type.NativeType; +import net.imglib2.type.NativeTypeFactory; import net.imglib2.type.Type; import net.imglib2.type.numeric.ARGBType; import net.imglib2.type.numeric.ComplexType; @@ -52,15 +58,25 @@ import net.imglib2.type.numeric.real.FloatType; import ij.ImagePlus; +import net.imglib2.util.Fraction; + +import java.util.AbstractList; +import java.util.concurrent.ExecutionException; +import java.util.function.Function; +import java.util.stream.LongStream; /** * Provides convenience functions to wrap ImageJ 1.x data structures as ImgLib2 * ones. + *

+ * Some functions wrap lazily, using imglib2-caches. These functions load + * planes on-demand, which is especially useful when wrapping a virtual stack. + *

* - * @see ImageJFunctions * * @author Stephan Preibisch * @author Stephan Saalfeld + * @author Matthias Arzt */ public class ImagePlusToImgPlus { @@ -242,6 +258,106 @@ public static Img< FloatType > convertFloat( final ImagePlus imp ) } } + // -- Lazy conversions -- // + + /** + * Wraps a 8 bit {@link ImagePlus}, into an {@link ImgPlus}, that is backed + * by a {@link PlanarImg}. The {@link PlanarImg} loads the planes only if + * needed, and caches them. The axes of the returned image are set according + * to the calibration of the given image. + */ + public static ImgPlus< UnsignedByteType > wrapByteLazily(final ImagePlus image ) + { + return internWrapLazily( image, ImagePlus.GRAY8, new UnsignedByteType(), array -> new ByteArray( ( byte[] ) array ) ); + } + + /** + * Wraps a 16 bit {@link ImagePlus}, into an {@link ImgPlus}, that is backed + * by a {@link PlanarImg}. The {@link PlanarImg} loads the planes only if + * needed, and caches them. The axes of the returned image are set according + * to the calibration of the given image. + */ + public static ImgPlus< UnsignedShortType > wrapShortLazily(final ImagePlus image ) + { + return internWrapLazily( image, ImagePlus.GRAY16, new UnsignedShortType(), array -> new ShortArray( ( short[] ) array ) ); + } + + /** + * Wraps a 32 bit {@link ImagePlus}, into an {@link ImgPlus}, that is backed + * by a {@link PlanarImg}. The {@link PlanarImg} loads the planes only if + * needed, and caches them. The axes of the returned image are set according + * to the calibration of the given image. + */ + public static ImgPlus< FloatType > wrapFloatLazily(final ImagePlus image ) + { + return internWrapLazily( image, ImagePlus.GRAY32, new FloatType(), array -> new FloatArray( ( float[] ) array ) ); + } + + /** + * Wraps a 32 bit {@link ImagePlus}, into an {@link ImgPlus}, that is backed + * by a {@link PlanarImg}. The {@link PlanarImg} loads the planes only if + * needed, and caches them. The axes of the returned image are set according + * to the calibration of the given image. + */ + public static ImgPlus< UnsignedIntType > wrapIntLazily(final ImagePlus image ) + { + return internWrapLazily( image, ImagePlus.COLOR_RGB, new UnsignedIntType(), array -> new IntArray( ( int[] ) array ) ); + } + + /** + * Wraps a 24 bit {@link ImagePlus}, into an {@link ImgPlus}, that is backed + * by a {@link PlanarImg}. The {@link PlanarImg} loads the planes only if + * needed, and caches them. The axes of the returned image are set according + * to the calibration of the given image. + */ + public static ImgPlus< ARGBType > wrapRGBALazily(final ImagePlus image ) + { + return internWrapLazily( image, ImagePlus.COLOR_RGB, new ARGBType(), array -> new IntArray( ( int[] ) array ) ); + } + + /** + * Wraps an {@link ImagePlus}, into an {@link ImgPlus}, that is backed by a + * {@link PlanarImg}. The {@link PlanarImg} loads the planes only if needed, + * and caches them. The pixel type of the returned image depends on the type + * of the ImagePlus. The axes of the returned image are set according to the + * calibration of the given image. + */ + public static ImgPlus< ? > wrapLazily(final ImagePlus image ) + { + switch ( image.getType() ) + { + case ImagePlus.GRAY8: + return wrapByteLazily( image ); + case ImagePlus.GRAY16: + return wrapShortLazily( image ); + case ImagePlus.GRAY32: + return wrapFloatLazily( image ); + case ImagePlus.COLOR_RGB: + return wrapRGBALazily( image ); + } + throw new RuntimeException( "Only 8, 16, 32-bit and RGB supported!" ); + } + + private static < T extends NativeType< T >, A extends ArrayDataAccess< A > > ImgPlus< T > internWrapLazily(final ImagePlus image, final int expectedType, final T type, final Function< Object, A > createArrayAccess ) + { + if ( image.getType() != expectedType ) + throw new IllegalArgumentException(); + final ImagePlusLoader< A > loader = new ImagePlusLoader<>( image, createArrayAccess ); + final long[] dimensions = getNonTrivialDimensions( image ); + final PlanarImg< T, A > cached = new PlanarImg<>( loader, dimensions, new Fraction() ); + cached.setLinkedType( ( (NativeTypeFactory< T, A >) type.getNativeTypeFactory() ).createLinkedType( cached ) ); + final CalibratedAxis[] axes = CalibrationUtils.getNonTrivialAxes( image ); + final ImgPlus< T > wrap = new ImgPlus<>( cached, image.getTitle(), axes ); + return wrap; + } + + private static long[] getNonTrivialDimensions(final ImagePlus image ) + { + final LongStream xy = LongStream.of( image.getWidth(), image.getHeight() ); + final LongStream czt = LongStream.of( image.getNChannels(), image.getNSlices(), image.getNFrames() ); + return LongStream.concat( xy, czt.filter( x -> x > 1 ) ).toArray(); + } + static private class ARGBtoFloatConverter implements Converter< ARGBType, FloatType > { /** Luminance times alpha. */ @@ -280,4 +396,46 @@ protected static < T extends Type< T > > Img< FloatType > convertToFloat( return output; } + + private static class ImagePlusLoader< A extends ArrayDataAccess< A >> extends AbstractList< A > + { + private final ImagePlus image; + + private final Cache< Integer, A > cache; + + private final Function< Object, A > arrayFactory; + + public ImagePlusLoader( final ImagePlus image, final Function< Object, A > arrayFactory ) + { + this.arrayFactory = arrayFactory; + this.image = image; + cache = new SoftRefLoaderCache< Integer, A >().withLoader( this::load ); + } + + @Override + public A get( final int key ) + { + try + { + return cache.get( key ); + } + catch ( final ExecutionException e ) + { + throw new RuntimeException( e ); + } + } + + private A load( final Integer key ) + { + return arrayFactory.apply( image.getStack().getPixels( key + 1 ) ); + } + + @Override + public int size() + { + return image.getStackSize(); + } + } + + // } diff --git a/src/main/java/net/imglib2/imagej/imageplus/VirtualStackAdapter.java b/src/main/java/net/imglib2/imagej/imageplus/VirtualStackAdapter.java deleted file mode 100644 index e77205e..0000000 --- a/src/main/java/net/imglib2/imagej/imageplus/VirtualStackAdapter.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * #%L - * ImgLib2: a general-purpose, multidimensional image processing library. - * %% - * Copyright (C) 2009 - 2025 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.imagej.imageplus; - -import java.util.AbstractList; -import java.util.concurrent.ExecutionException; -import java.util.function.Function; -import java.util.stream.LongStream; - -import net.imagej.ImgPlus; -import net.imagej.axis.CalibratedAxis; -import net.imglib2.cache.Cache; -import net.imglib2.cache.ref.SoftRefLoaderCache; -import net.imglib2.img.basictypeaccess.array.ArrayDataAccess; -import net.imglib2.img.basictypeaccess.array.ByteArray; -import net.imglib2.img.basictypeaccess.array.FloatArray; -import net.imglib2.img.basictypeaccess.array.IntArray; -import net.imglib2.img.basictypeaccess.array.ShortArray; -import net.imglib2.imagej.display.CalibrationUtils; -import net.imglib2.img.planar.PlanarImg; -import net.imglib2.type.NativeType; -import net.imglib2.type.NativeTypeFactory; -import net.imglib2.type.numeric.ARGBType; -import net.imglib2.type.numeric.integer.UnsignedByteType; -import net.imglib2.type.numeric.integer.UnsignedIntType; -import net.imglib2.type.numeric.integer.UnsignedShortType; -import net.imglib2.type.numeric.real.FloatType; -import net.imglib2.util.Fraction; - -import ij.ImagePlus; - -/** - * Wrapper for ImagePlus using imglib2-caches. It loads the planes lazily, which - * is especially useful when wrapping a virtual stack. - * - * @author Matthias Arzt - */ -public class VirtualStackAdapter -{ - /** - * Wraps a 8 bit {@link ImagePlus}, into an {@link ImgPlus}, that is backed - * by a {@link PlanarImg}. The {@link PlanarImg} loads the planes only if - * needed, and caches them. The axes of the returned image are set according - * to the calibration of the given image. - */ - public static ImgPlus< UnsignedByteType > wrapByte( final ImagePlus image ) - { - return internWrap( image, ImagePlus.GRAY8, new UnsignedByteType(), array -> new ByteArray( ( byte[] ) array ) ); - } - - /** - * Wraps a 16 bit {@link ImagePlus}, into an {@link ImgPlus}, that is backed - * by a {@link PlanarImg}. The {@link PlanarImg} loads the planes only if - * needed, and caches them. The axes of the returned image are set according - * to the calibration of the given image. - */ - public static ImgPlus< UnsignedShortType > wrapShort( final ImagePlus image ) - { - return internWrap( image, ImagePlus.GRAY16, new UnsignedShortType(), array -> new ShortArray( ( short[] ) array ) ); - } - - /** - * Wraps a 32 bit {@link ImagePlus}, into an {@link ImgPlus}, that is backed - * by a {@link PlanarImg}. The {@link PlanarImg} loads the planes only if - * needed, and caches them. The axes of the returned image are set according - * to the calibration of the given image. - */ - public static ImgPlus< FloatType > wrapFloat( final ImagePlus image ) - { - return internWrap( image, ImagePlus.GRAY32, new FloatType(), array -> new FloatArray( ( float[] ) array ) ); - } - - /** - * Wraps a 32 bit {@link ImagePlus}, into an {@link ImgPlus}, that is backed - * by a {@link PlanarImg}. The {@link PlanarImg} loads the planes only if - * needed, and caches them. The axes of the returned image are set according - * to the calibration of the given image. - */ - public static ImgPlus< UnsignedIntType > wrapInt( final ImagePlus image ) - { - return internWrap( image, ImagePlus.COLOR_RGB, new UnsignedIntType(), array -> new IntArray( ( int[] ) array ) ); - } - - /** - * Wraps a 24 bit {@link ImagePlus}, into an {@link ImgPlus}, that is backed - * by a {@link PlanarImg}. The {@link PlanarImg} loads the planes only if - * needed, and caches them. The axes of the returned image are set according - * to the calibration of the given image. - */ - public static ImgPlus< ARGBType > wrapRGBA( final ImagePlus image ) - { - return internWrap( image, ImagePlus.COLOR_RGB, new ARGBType(), array -> new IntArray( ( int[] ) array ) ); - } - - /** - * Wraps an {@link ImagePlus}, into an {@link ImgPlus}, that is backed by a - * {@link PlanarImg}. The {@link PlanarImg} loads the planes only if needed, - * and caches them. The pixel type of the returned image depends on the type - * of the ImagePlus. The axes of the returned image are set according to the - * calibration of the given image. - */ - public static ImgPlus< ? > wrap( final ImagePlus image ) - { - switch ( image.getType() ) - { - case ImagePlus.GRAY8: - return wrapByte( image ); - case ImagePlus.GRAY16: - return wrapShort( image ); - case ImagePlus.GRAY32: - return wrapFloat( image ); - case ImagePlus.COLOR_RGB: - return wrapRGBA( image ); - } - throw new RuntimeException( "Only 8, 16, 32-bit and RGB supported!" ); - } - - private static < T extends NativeType< T >, A extends ArrayDataAccess< A > > ImgPlus< T > internWrap( final ImagePlus image, final int expectedType, final T type, final Function< Object, A > createArrayAccess ) - { - if ( image.getType() != expectedType ) - throw new IllegalArgumentException(); - final ImagePlusLoader< A > loader = new ImagePlusLoader<>( image, createArrayAccess ); - final long[] dimensions = getNonTrivialDimensions( image ); - final PlanarImg< T, A > cached = new PlanarImg<>( loader, dimensions, new Fraction() ); - cached.setLinkedType( ( ( NativeTypeFactory< T, A > ) type.getNativeTypeFactory() ).createLinkedType( cached ) ); - final CalibratedAxis[] axes = CalibrationUtils.getNonTrivialAxes( image ); - final ImgPlus< T > wrap = new ImgPlus<>( cached, image.getTitle(), axes ); - return wrap; - } - - private static long[] getNonTrivialDimensions( final ImagePlus image ) - { - final LongStream xy = LongStream.of( image.getWidth(), image.getHeight() ); - final LongStream czt = LongStream.of( image.getNChannels(), image.getNSlices(), image.getNFrames() ); - return LongStream.concat( xy, czt.filter( x -> x > 1 ) ).toArray(); - } - - private static class ImagePlusLoader< A extends ArrayDataAccess< A > > extends AbstractList< A > - { - private final ImagePlus image; - - private final Cache< Integer, A > cache; - - private final Function< Object, A > arrayFactory; - - public ImagePlusLoader( final ImagePlus image, final Function< Object, A > arrayFactory ) - { - this.arrayFactory = arrayFactory; - this.image = image; - cache = new SoftRefLoaderCache< Integer, A >().withLoader( this::load ); - } - - @Override - public A get( final int key ) - { - try - { - return cache.get( key ); - } - catch ( final ExecutionException e ) - { - throw new RuntimeException( e ); - } - } - - private A load( final Integer key ) - { - return arrayFactory.apply( image.getStack().getPixels( key + 1 ) ); - } - - @Override - public int size() - { - return image.getStackSize(); - } - } -} diff --git a/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2Benchmark.java b/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2Benchmark.java index 8899946..b9a68e6 100644 --- a/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2Benchmark.java +++ b/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2Benchmark.java @@ -36,7 +36,6 @@ import net.imagej.ImgPlus; import net.imglib2.RandomAccessibleInterval; import net.imglib2.imagej.imageplus.ByteImagePlus; -import net.imglib2.imagej.imageplus.VirtualStackAdapter; import net.imglib2.type.numeric.integer.UnsignedByteType; import net.imglib2.view.Views; @@ -63,41 +62,41 @@ public class ImagePlusToImgLib2Benchmark @Benchmark public void wrapSmall() { - VirtualStackAdapter.wrap( small ); + net.imglib2.imagej.ImagePlusToImgPlus.wrapLazily( small ); } @Benchmark public void wrapDeep() { - VirtualStackAdapter.wrap( deep ); + net.imglib2.imagej.ImagePlusToImgPlus.wrapLazily( deep ); } @Benchmark public void wrapWide() { - VirtualStackAdapter.wrap( wide ); + ImagePlusToImgPlus.wrapLazily( wide ); } @Benchmark public void wrapSmallOld() { - ImagePlusToImgPlus.wrap( small ); + net.imglib2.imagej.ImagePlusToImgPlus.wrap( small ); } @Benchmark public void wrapDeepOld() { - ImagePlusToImgPlus.wrap( deep ); + net.imglib2.imagej.ImagePlusToImgPlus.wrap( deep ); } @Benchmark public void wrapWideOld() { - ImagePlusToImgPlus.wrap( wide ); + net.imglib2.imagej.ImagePlusToImgPlus.wrap( wide ); } - private final ImgPlus< UnsignedByteType > wrapped = VirtualStackAdapter.wrapByte( imageForIteration ); - private final ByteImagePlus< UnsignedByteType > wrappedOld = ImagePlusToImgPlus.wrapByte( imageForIteration ); + private final ImgPlus< UnsignedByteType > wrapped = net.imglib2.imagej.ImagePlusToImgPlus.wrapByteLazily( imageForIteration ); + private final ByteImagePlus< UnsignedByteType > wrappedOld = net.imglib2.imagej.ImagePlusToImgPlus.wrapByte( imageForIteration ); @Benchmark public void iterateWrapped() diff --git a/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2PerformanceTest.java b/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2PerformanceTest.java index be1c270..d5738f2 100644 --- a/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2PerformanceTest.java +++ b/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2PerformanceTest.java @@ -38,7 +38,6 @@ import java.util.concurrent.atomic.AtomicInteger; import net.imglib2.RandomAccessibleInterval; -import net.imglib2.imagej.imageplus.VirtualStackAdapter; import net.imglib2.img.Img; import net.imglib2.type.numeric.RealType; import net.imglib2.view.Views; @@ -58,7 +57,7 @@ public void testIterateVirtualStack() { final AtomicInteger counter = new AtomicInteger(); final ImagePlus image = countingImagePlus( counter ); - final Img< ? extends RealType< ? > > img = VirtualStackAdapter.wrapByte( image ); + final Img< ? extends RealType< ? > > img = net.imglib2.imagej.ImagePlusToImgPlus.wrapByteLazily( image ); runFlatIteration( img ); assertTrue( counter.get() < 120 ); // don't call getProcessor too often } @@ -68,7 +67,7 @@ public void testIteratePermutedVirtualStack() { final AtomicInteger counter = new AtomicInteger(); final ImagePlus image = countingImagePlus( counter ); - final Img< ? extends RealType< ? > > img = VirtualStackAdapter.wrapByte( image ); + final Img< ? extends RealType< ? > > img = ImagePlusToImgPlus.wrapByteLazily( image ); runFlatIteration( Views.permute( img, 0, 2 ) ); assertTrue( counter.get() < 120 ); // don't call getProcessor too often } @@ -78,7 +77,7 @@ public void testIterateImagePlusAdapter() { final AtomicInteger counter = new AtomicInteger(); final ImagePlus image = countingImagePlus( counter ); - final Img< ? extends RealType< ? > > img = ImagePlusToImgPlus.wrapByte( image ); + final Img< ? extends RealType< ? > > img = net.imglib2.imagej.ImagePlusToImgPlus.wrapByte( image ); runFlatIteration( Views.permute( img, 0, 2 ) ); assertTrue( counter.get() < 120 ); // don't call getProcessor too often } diff --git a/src/test/java/net/imglib2/imagej/display/PlanarImgToVirtualStackTest.java b/src/test/java/net/imglib2/imagej/display/PlanarImgToVirtualStackTest.java index cf6b3e1..1779c92 100644 --- a/src/test/java/net/imglib2/imagej/display/PlanarImgToVirtualStackTest.java +++ b/src/test/java/net/imglib2/imagej/display/PlanarImgToVirtualStackTest.java @@ -44,7 +44,7 @@ import net.imagej.axis.Axes; import net.imagej.axis.AxisType; import net.imglib2.RandomAccessibleInterval; -import net.imglib2.imagej.imageplus.VirtualStackAdapter; +import net.imglib2.imagej.ImagePlusToImgPlus; import net.imglib2.img.basictypeaccess.array.FloatArray; import net.imglib2.img.basictypeaccess.array.IntArray; import net.imglib2.img.planar.PlanarImg; @@ -165,7 +165,7 @@ public void testGetProcessorForColorProcessor() { @Test public void testConvertingBackAndForth() { ImagePlus imagePlus = IJ.createImage( "test", "8-bit ramp", 3, 3, 3 ); - ImgPlus< UnsignedByteType > convertedImg = VirtualStackAdapter.wrapByte( imagePlus ); + ImgPlus< UnsignedByteType > convertedImg = ImagePlusToImgPlus.wrapByteLazily( imagePlus ); ImagePlus twiceConvertedImagePlus = PlanarImgToVirtualStack.wrap( convertedImg ); twiceConvertedImagePlus.getStack().getProcessor( 1 ).set( 0, 0, 5 ); assertEquals( 5, imagePlus.getStack().getProcessor( 1 ).get( 0, 0 ) ); diff --git a/src/test/java/net/imglib2/imagej/imageplus/VirtualStackAdapterTest.java b/src/test/java/net/imglib2/imagej/imageplus/ImagePlusToImgPlusTest.java similarity index 75% rename from src/test/java/net/imglib2/imagej/imageplus/VirtualStackAdapterTest.java rename to src/test/java/net/imglib2/imagej/imageplus/ImagePlusToImgPlusTest.java index b6dbbcc..c13c5c9 100644 --- a/src/test/java/net/imglib2/imagej/imageplus/VirtualStackAdapterTest.java +++ b/src/test/java/net/imglib2/imagej/imageplus/ImagePlusToImgPlusTest.java @@ -49,11 +49,11 @@ import org.junit.Test; /** - * Tests {@link VirtualStackAdapter}. + * Tests {@link ImagePlusToImgPlus}. * * @author Matthias Arzt */ -public class VirtualStackAdapterTest +public class ImagePlusToImgPlusTest { private static final long[] DIMENSIONS = { 2, 3, 4, 5, 6 }; @@ -63,8 +63,8 @@ public class VirtualStackAdapterTest public void testUnsignedByte() { final ImagePlus image = randomImagePlus( 123, new UnsignedByteType(), DIMENSIONS ); - final Img< UnsignedByteType > actual = VirtualStackAdapter.wrapByte( image ); - final Img< UnsignedByteType > expected = ImagePlusToImgPlus.wrapByte( image ); + final Img< UnsignedByteType > actual = net.imglib2.imagej.ImagePlusToImgPlus.wrapByteLazily( image ); + final Img< UnsignedByteType > expected = net.imglib2.imagej.ImagePlusToImgPlus.wrapByte( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -72,8 +72,8 @@ public void testUnsignedByte() public void testUnsignedShort() { final ImagePlus image = randomImagePlus( 234, new UnsignedShortType(), DIMENSIONS ); - final Img< UnsignedShortType > actual = VirtualStackAdapter.wrapShort( image ); - final Img< UnsignedShortType > expected = ImagePlusToImgPlus.wrapShort( image ); + final Img< UnsignedShortType > actual = net.imglib2.imagej.ImagePlusToImgPlus.wrapShortLazily( image ); + final Img< UnsignedShortType > expected = net.imglib2.imagej.ImagePlusToImgPlus.wrapShort( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -81,8 +81,8 @@ public void testUnsignedShort() public void testRGB() { final ImagePlus image = randomImagePlus( 345, new ARGBType(), DIMENSIONS ); - final Img< ARGBType > actual = VirtualStackAdapter.wrapRGBA( image ); - final Img< ARGBType > expected = ImagePlusToImgPlus.wrapRGBA( image ); + final Img< ARGBType > actual = net.imglib2.imagej.ImagePlusToImgPlus.wrapRGBALazily( image ); + final Img< ARGBType > expected = net.imglib2.imagej.ImagePlusToImgPlus.wrapRGBA( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -90,8 +90,8 @@ public void testRGB() public void testFloat() { final ImagePlus image = randomImagePlus( 456, new FloatType(), DIMENSIONS ); - final Img< FloatType > actual = VirtualStackAdapter.wrapFloat( image ); - final Img< FloatType > expected = ImagePlusToImgPlus.wrapFloat( image ); + final Img< FloatType > actual = net.imglib2.imagej.ImagePlusToImgPlus.wrapFloatLazily( image ); + final Img< FloatType > expected = net.imglib2.imagej.ImagePlusToImgPlus.wrapFloat( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -99,8 +99,8 @@ public void testFloat() public void testLowerNumDimensions() { final ImagePlus image = randomImagePlus( 567, new UnsignedByteType(), 2, 3, 6 ); - final Img< UnsignedByteType > actual = VirtualStackAdapter.wrapByte( image ); - final Img< UnsignedByteType > expected = ImagePlusToImgPlus.wrapByte( image ); + final Img< UnsignedByteType > actual = net.imglib2.imagej.ImagePlusToImgPlus.wrapByteLazily( image ); + final Img< UnsignedByteType > expected = net.imglib2.imagej.ImagePlusToImgPlus.wrapByte( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -108,8 +108,8 @@ public void testLowerNumDimensions() public void testSingletonDimensions() { final ImagePlus image = randomImagePlus( 678, new UnsignedByteType(), 2, 1, 1, 6 ); - final Img< UnsignedByteType > actual = VirtualStackAdapter.wrapByte( image ); - final Img< UnsignedByteType > expected = ImagePlusToImgPlus.wrapByte( image ); + final Img< UnsignedByteType > actual = net.imglib2.imagej.ImagePlusToImgPlus.wrapByteLazily( image ); + final Img< UnsignedByteType > expected = net.imglib2.imagej.ImagePlusToImgPlus.wrapByte( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } From aeab4e910be4c356e2aa7b19059d50e0e0c01de7 Mon Sep 17 00:00:00 2001 From: Gabriel Selzer Date: Mon, 24 Feb 2025 18:52:26 -0600 Subject: [PATCH 04/11] Collapse ImgPlus <-> ImagePlus functionality There were many different classes containing methods that do similar things, and it can be hard to discover and compare if they aren't all in one place. --- ...tualStack.java => ImgPlusToImagePlus.java} | 20 +- .../imagej/display/AbstractVirtualStack.java | 2 +- ...ualStack.java => ArrayImgToImagePlus.java} | 13 +- ...tualStack.java => CellImgToImagePlus.java} | 13 +- ...alStack.java => PlanarImgToImagePlus.java} | 15 +- ...t.java => ImagePlusToImgPlusLazyTest.java} | 32 +- .../imagej/ImagePlusToImgPlusTest.java | 184 +++++++++ .../imagej/ImgPlusToImagePlusTest.java | 390 ++++++++++++------ ...Test.java => ArrayImgToImagePlusTest.java} | 12 +- ...kTest.java => CellImgToImagePlusTest.java} | 30 +- ...ageJVirtualStackGetProcessorBenchmark.java | 3 +- .../ImgLib2ToVirtualStackBenchmark.java | 17 +- .../imagej/display/ImgToVirtualStackTest.java | 304 -------------- ...est.java => PlanarImgToImagePlusTest.java} | 18 +- 14 files changed, 528 insertions(+), 525 deletions(-) rename src/main/java/net/imglib2/imagej/{display/ImgToVirtualStack.java => ImgPlusToImagePlus.java} (95%) rename src/main/java/net/imglib2/imagej/display/{ArrayImgToVirtualStack.java => ArrayImgToImagePlus.java} (95%) rename src/main/java/net/imglib2/imagej/display/{CellImgToVirtualStack.java => CellImgToImagePlus.java} (95%) rename src/main/java/net/imglib2/imagej/display/{PlanarImgToVirtualStack.java => PlanarImgToImagePlus.java} (95%) rename src/test/java/net/imglib2/imagej/{imageplus/ImagePlusToImgPlusTest.java => ImagePlusToImgPlusLazyTest.java} (73%) create mode 100644 src/test/java/net/imglib2/imagej/ImagePlusToImgPlusTest.java rename src/test/java/net/imglib2/imagej/display/{ArrayImgToVirtualStackTest.java => ArrayImgToImagePlusTest.java} (91%) rename src/test/java/net/imglib2/imagej/display/{CellImgToVirtualStackTest.java => CellImgToImagePlusTest.java} (77%) delete mode 100644 src/test/java/net/imglib2/imagej/display/ImgToVirtualStackTest.java rename src/test/java/net/imglib2/imagej/display/{PlanarImgToVirtualStackTest.java => PlanarImgToImagePlusTest.java} (91%) diff --git a/src/main/java/net/imglib2/imagej/display/ImgToVirtualStack.java b/src/main/java/net/imglib2/imagej/ImgPlusToImagePlus.java similarity index 95% rename from src/main/java/net/imglib2/imagej/display/ImgToVirtualStack.java rename to src/main/java/net/imglib2/imagej/ImgPlusToImagePlus.java index b24c0ae..0b05abf 100644 --- a/src/main/java/net/imglib2/imagej/display/ImgToVirtualStack.java +++ b/src/main/java/net/imglib2/imagej/ImgPlusToImagePlus.java @@ -32,7 +32,7 @@ * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej; import java.util.Arrays; import java.util.List; @@ -44,7 +44,7 @@ import net.imagej.axis.Axes; import net.imagej.axis.AxisType; import net.imglib2.RandomAccessibleInterval; -import net.imglib2.imagej.ImgPlusViews; +import net.imglib2.imagej.display.*; import net.imglib2.transform.integer.MixedTransform; import net.imglib2.type.logic.BitType; import net.imglib2.type.numeric.ARGBType; @@ -54,7 +54,7 @@ import ij.ImagePlus; -public class ImgToVirtualStack +public class ImgPlusToImagePlus { // TODO move to image-legacy public static ImagePlus wrap( final ImgPlus< ? extends RealType< ? > > imgPlus, final boolean mergeRGB ) @@ -72,27 +72,27 @@ public static ImagePlus wrap( final ImgPlus< ? extends RealType< ? > > imgPlus, * Only up to five dimensions are support. Axes can might be arbitrary. The * image title and calibration are derived from the given image. * - * @see ArrayImgToVirtualStack - * @see ImgToVirtualStack + * @see ArrayImgToImagePlus + * @see ImgPlusToImagePlus */ public static ImagePlus wrap( final ImgPlus< ? > imgPlus ) { - return wrap( imgPlus, ImgToVirtualStack::createVirtualStack ); + return wrap( imgPlus, ImgPlusToImagePlus::createVirtualStack ); } /** * Similar to {@link #wrap(ImgPlus)}, but works only for {@link ImgPlus} of * {@link BitType}. The pixel values of 0 and 1 are scaled to 0 and 255. * - * @see ArrayImgToVirtualStack - * @see ImgToVirtualStack + * @see ArrayImgToImagePlus + * @see ImgPlusToImagePlus */ public static ImagePlus wrapAndScaleBitType( final ImgPlus< BitType > imgPlus ) { - return wrap( imgPlus, ImgToVirtualStack::createVirtualStackBits ); + return wrap( imgPlus, ImgPlusToImagePlus::createVirtualStackBits ); } - private static < T > ImagePlus wrap( ImgPlus< T > imgPlus, final Function< RandomAccessibleInterval< T >, ImageJVirtualStack > imageStackWrapper ) + private static < T > ImagePlus wrap( ImgPlus< T > imgPlus, final Function< RandomAccessibleInterval< T >, ImageJVirtualStack> imageStackWrapper ) { imgPlus = ImgPlusViews.fixAxes( imgPlus ); final RandomAccessibleInterval< T > sorted = ensureXYCZT( imgPlus ); diff --git a/src/main/java/net/imglib2/imagej/display/AbstractVirtualStack.java b/src/main/java/net/imglib2/imagej/display/AbstractVirtualStack.java index c8c2233..e1078bb 100644 --- a/src/main/java/net/imglib2/imagej/display/AbstractVirtualStack.java +++ b/src/main/java/net/imglib2/imagej/display/AbstractVirtualStack.java @@ -56,7 +56,7 @@ /** * Abstract class to simplify the implementation of an {@link VirtualStack}. *

- * This class is intended to be used in {@link ImageJVirtualStack} and {@link PlanarImgToVirtualStack}. + * This class is intended to be used in {@link ImageJVirtualStack} and {@link PlanarImgToImagePlus}. * * @author Matthias Arzt */ diff --git a/src/main/java/net/imglib2/imagej/display/ArrayImgToVirtualStack.java b/src/main/java/net/imglib2/imagej/display/ArrayImgToImagePlus.java similarity index 95% rename from src/main/java/net/imglib2/imagej/display/ArrayImgToVirtualStack.java rename to src/main/java/net/imglib2/imagej/display/ArrayImgToImagePlus.java index e3e9c9a..3c0d06b 100644 --- a/src/main/java/net/imglib2/imagej/display/ArrayImgToVirtualStack.java +++ b/src/main/java/net/imglib2/imagej/display/ArrayImgToImagePlus.java @@ -42,6 +42,7 @@ import net.imagej.axis.Axes; import net.imagej.axis.AxisType; import net.imagej.axis.CalibratedAxis; +import net.imglib2.imagej.ImgPlusToImagePlus; import net.imglib2.imagej.ImgPlusViews; import net.imglib2.img.Img; import net.imglib2.img.array.ArrayImg; @@ -55,9 +56,9 @@ import ij.ImagePlus; import ij.process.ImageProcessor; -public class ArrayImgToVirtualStack +public class ArrayImgToImagePlus { - private ArrayImgToVirtualStack() + private ArrayImgToImagePlus() { // prevent from instantiation } @@ -65,8 +66,8 @@ private ArrayImgToVirtualStack() /** * Indicates if {@link #wrap(ImgPlus)} wrap} supports the image. * - * @see PlanarImgToVirtualStack - * @see ImgToVirtualStack + * @see PlanarImgToImagePlus + * @see ImgPlusToImagePlus */ public static boolean isSupported( ImgPlus< ? > imgPlus ) { @@ -92,8 +93,8 @@ public static boolean isSupported( ImgPlus< ? > imgPlus ) * Use {@link #isSupported(ImgPlus)} to check if an {@link ImagePlus} is * supported. * - * @see PlanarImgToVirtualStack - * @see ImgToVirtualStack + * @see PlanarImgToImagePlus + * @see ImgPlusToImagePlus */ public static ImagePlus wrap( ImgPlus< ? > imgPlus ) { diff --git a/src/main/java/net/imglib2/imagej/display/CellImgToVirtualStack.java b/src/main/java/net/imglib2/imagej/display/CellImgToImagePlus.java similarity index 95% rename from src/main/java/net/imglib2/imagej/display/CellImgToVirtualStack.java rename to src/main/java/net/imglib2/imagej/display/CellImgToImagePlus.java index 5c412a8..365edf1 100644 --- a/src/main/java/net/imglib2/imagej/display/CellImgToVirtualStack.java +++ b/src/main/java/net/imglib2/imagej/display/CellImgToImagePlus.java @@ -40,6 +40,7 @@ import net.imglib2.FinalDimensions; import net.imglib2.RandomAccess; import net.imglib2.RandomAccessible; +import net.imglib2.imagej.ImgPlusToImagePlus; import net.imglib2.img.Img; import net.imglib2.img.basictypeaccess.array.ArrayDataAccess; import net.imglib2.img.cell.AbstractCellImg; @@ -61,11 +62,11 @@ * cells contains exactly one image plane), and certain pixel types: * UnsignedByteType, UnsignedShortType, ARGBType and FloatType. * - * @see ImgToVirtualStack - * @see PlanarImgToVirtualStack - * @see ArrayImgToVirtualStack + * @see ImgPlusToImagePlus + * @see PlanarImgToImagePlus + * @see ArrayImgToImagePlus */ -public class CellImgToVirtualStack +public class CellImgToImagePlus { /** @@ -74,7 +75,7 @@ public class CellImgToVirtualStack public static boolean isSupported( ImgPlus< ? > imgPlus ) { return isCellImgWithPlanarCells( imgPlus.getImg() ) && - PlanarImgToVirtualStack.isSupported( toPlanarImgPlus( imgPlus ) ); + PlanarImgToImagePlus.isSupported( toPlanarImgPlus( imgPlus ) ); } private static boolean isCellImgWithPlanarCells( Img< ? > imgPlus ) @@ -102,7 +103,7 @@ private static boolean areCellsPlanar( CellGrid cellGrid ) */ public static ImagePlus wrap( ImgPlus< ? > imgPlus ) { - return PlanarImgToVirtualStack.wrap( toPlanarImgPlus( imgPlus ) ); + return PlanarImgToImagePlus.wrap( toPlanarImgPlus( imgPlus ) ); } private static < T > ImgPlus< T > toPlanarImgPlus( ImgPlus< T > image ) diff --git a/src/main/java/net/imglib2/imagej/display/PlanarImgToVirtualStack.java b/src/main/java/net/imglib2/imagej/display/PlanarImgToImagePlus.java similarity index 95% rename from src/main/java/net/imglib2/imagej/display/PlanarImgToVirtualStack.java rename to src/main/java/net/imglib2/imagej/display/PlanarImgToImagePlus.java index df83f32..e6f5b3b 100644 --- a/src/main/java/net/imglib2/imagej/display/PlanarImgToVirtualStack.java +++ b/src/main/java/net/imglib2/imagej/display/PlanarImgToImagePlus.java @@ -48,6 +48,7 @@ import net.imagej.axis.CalibratedAxis; import net.imglib2.Interval; import net.imglib2.imagej.ImgPlusViews; +import net.imglib2.imagej.ImgPlusToImagePlus; import net.imglib2.img.Img; import net.imglib2.img.basictypeaccess.PlanarAccess; import net.imglib2.img.basictypeaccess.array.ArrayDataAccess; @@ -73,11 +74,11 @@ * without copying data. It is restricted to certain pixel types: * UnsignedByteType, UnsignedShortType, ARGBType and FloatType. * - * @see ArrayImgToVirtualStack - * @see ImgToVirtualStack - * @see CellImgToVirtualStack + * @see ArrayImgToImagePlus + * @see ImgPlusToImagePlus + * @see CellImgToImagePlus */ -public class PlanarImgToVirtualStack extends AbstractVirtualStack +public class PlanarImgToImagePlus extends AbstractVirtualStack { // static @@ -117,7 +118,7 @@ public static ImagePlus wrap( ImgPlus< ? > imgPlus ) if ( !( img instanceof PlanarImg ) ) throw new IllegalArgumentException( "Image must be a PlanarImg." ); final IntUnaryOperator indexer = getIndexer( imgPlus ); - final VirtualStack stack = new PlanarImgToVirtualStack( ( PlanarImg< ?, ? > ) img, indexer ); + final VirtualStack stack = new PlanarImgToImagePlus( ( PlanarImg< ?, ? > ) img, indexer ); final ImagePlus imagePlus = new ImagePlus( imgPlus.getName(), stack ); imagePlus.setDimensions( dimension( imgPlus, Axes.CHANNEL ), dimension( imgPlus, Axes.Z ), dimension( imgPlus, Axes.TIME ) ); CalibrationUtils.copyCalibrationToImagePlus( imgPlus, imagePlus ); @@ -132,7 +133,7 @@ private static int dimension( final ImgPlus< ? > imgPlus, final AxisType axisTyp public static VirtualStack wrap( final PlanarImg< ?, ? > img ) { - return new PlanarImgToVirtualStack( img, x -> x ); + return new PlanarImgToImagePlus( img, x -> x ); } // fields @@ -143,7 +144,7 @@ public static VirtualStack wrap( final PlanarImg< ?, ? > img ) // constructor - private PlanarImgToVirtualStack( final PlanarImg< ?, ? > img, final IntUnaryOperator indexer ) + private PlanarImgToImagePlus(final PlanarImg< ?, ? > img, final IntUnaryOperator indexer ) { super( ( int ) img.dimension( 0 ), ( int ) img.dimension( 1 ), initSize( img ), getBitDepth( img.randomAccess().get() ) ); this.img = img; diff --git a/src/test/java/net/imglib2/imagej/imageplus/ImagePlusToImgPlusTest.java b/src/test/java/net/imglib2/imagej/ImagePlusToImgPlusLazyTest.java similarity index 73% rename from src/test/java/net/imglib2/imagej/imageplus/ImagePlusToImgPlusTest.java rename to src/test/java/net/imglib2/imagej/ImagePlusToImgPlusLazyTest.java index c13c5c9..82a291f 100644 --- a/src/test/java/net/imglib2/imagej/imageplus/ImagePlusToImgPlusTest.java +++ b/src/test/java/net/imglib2/imagej/ImagePlusToImgPlusLazyTest.java @@ -32,11 +32,9 @@ * #L% */ -package net.imglib2.imagej.imageplus; +package net.imglib2.imagej; import ij.ImagePlus; -import net.imglib2.imagej.ImagePlusToImgPlus; -import net.imglib2.imagej.RAIToImagePlus; import net.imglib2.img.Img; import net.imglib2.test.ImgLib2Assert; import net.imglib2.test.RandomImgs; @@ -49,11 +47,11 @@ import org.junit.Test; /** - * Tests {@link ImagePlusToImgPlus}. + * Tests the lazy wrapping functions of {@link ImagePlusToImgPlus}. * * @author Matthias Arzt */ -public class ImagePlusToImgPlusTest +public class ImagePlusToImgPlusLazyTest { private static final long[] DIMENSIONS = { 2, 3, 4, 5, 6 }; @@ -63,8 +61,8 @@ public class ImagePlusToImgPlusTest public void testUnsignedByte() { final ImagePlus image = randomImagePlus( 123, new UnsignedByteType(), DIMENSIONS ); - final Img< UnsignedByteType > actual = net.imglib2.imagej.ImagePlusToImgPlus.wrapByteLazily( image ); - final Img< UnsignedByteType > expected = net.imglib2.imagej.ImagePlusToImgPlus.wrapByte( image ); + final Img< UnsignedByteType > actual = ImagePlusToImgPlus.wrapByteLazily( image ); + final Img< UnsignedByteType > expected = ImagePlusToImgPlus.wrapByte( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -72,8 +70,8 @@ public void testUnsignedByte() public void testUnsignedShort() { final ImagePlus image = randomImagePlus( 234, new UnsignedShortType(), DIMENSIONS ); - final Img< UnsignedShortType > actual = net.imglib2.imagej.ImagePlusToImgPlus.wrapShortLazily( image ); - final Img< UnsignedShortType > expected = net.imglib2.imagej.ImagePlusToImgPlus.wrapShort( image ); + final Img< UnsignedShortType > actual = ImagePlusToImgPlus.wrapShortLazily( image ); + final Img< UnsignedShortType > expected = ImagePlusToImgPlus.wrapShort( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -81,8 +79,8 @@ public void testUnsignedShort() public void testRGB() { final ImagePlus image = randomImagePlus( 345, new ARGBType(), DIMENSIONS ); - final Img< ARGBType > actual = net.imglib2.imagej.ImagePlusToImgPlus.wrapRGBALazily( image ); - final Img< ARGBType > expected = net.imglib2.imagej.ImagePlusToImgPlus.wrapRGBA( image ); + final Img< ARGBType > actual = ImagePlusToImgPlus.wrapRGBALazily( image ); + final Img< ARGBType > expected = ImagePlusToImgPlus.wrapRGBA( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -90,8 +88,8 @@ public void testRGB() public void testFloat() { final ImagePlus image = randomImagePlus( 456, new FloatType(), DIMENSIONS ); - final Img< FloatType > actual = net.imglib2.imagej.ImagePlusToImgPlus.wrapFloatLazily( image ); - final Img< FloatType > expected = net.imglib2.imagej.ImagePlusToImgPlus.wrapFloat( image ); + final Img< FloatType > actual = ImagePlusToImgPlus.wrapFloatLazily( image ); + final Img< FloatType > expected = ImagePlusToImgPlus.wrapFloat( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -99,8 +97,8 @@ public void testFloat() public void testLowerNumDimensions() { final ImagePlus image = randomImagePlus( 567, new UnsignedByteType(), 2, 3, 6 ); - final Img< UnsignedByteType > actual = net.imglib2.imagej.ImagePlusToImgPlus.wrapByteLazily( image ); - final Img< UnsignedByteType > expected = net.imglib2.imagej.ImagePlusToImgPlus.wrapByte( image ); + final Img< UnsignedByteType > actual = ImagePlusToImgPlus.wrapByteLazily( image ); + final Img< UnsignedByteType > expected = ImagePlusToImgPlus.wrapByte( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -108,8 +106,8 @@ public void testLowerNumDimensions() public void testSingletonDimensions() { final ImagePlus image = randomImagePlus( 678, new UnsignedByteType(), 2, 1, 1, 6 ); - final Img< UnsignedByteType > actual = net.imglib2.imagej.ImagePlusToImgPlus.wrapByteLazily( image ); - final Img< UnsignedByteType > expected = net.imglib2.imagej.ImagePlusToImgPlus.wrapByte( image ); + final Img< UnsignedByteType > actual = ImagePlusToImgPlus.wrapByteLazily( image ); + final Img< UnsignedByteType > expected = ImagePlusToImgPlus.wrapByte( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } diff --git a/src/test/java/net/imglib2/imagej/ImagePlusToImgPlusTest.java b/src/test/java/net/imglib2/imagej/ImagePlusToImgPlusTest.java new file mode 100644 index 0000000..5816abe --- /dev/null +++ b/src/test/java/net/imglib2/imagej/ImagePlusToImgPlusTest.java @@ -0,0 +1,184 @@ +/* + * #%L + * ImgLib2: a general-purpose, multidimensional image processing library. + * %% + * Copyright (C) 2009 - 2025 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.imagej; + +import static org.junit.Assert.assertEquals; + +import net.imagej.ImgPlus; +import net.imagej.axis.Axes; +import net.imglib2.type.NativeType; +import net.imglib2.type.numeric.NumericType; + +import org.junit.Test; + +import ij.ImagePlus; +import ij.gui.NewImage; +import ij.measure.Calibration; + +public class ImagePlusToImgPlusTest< T extends NumericType< T > & NativeType< T > > +{ + + /** Which dimensions to test. */ + final int[][] dim = new int[][] { + // nX nY nC nZ nT + { 128, 128, 1, 1, 1 }, // 2D + { 128, 128, 1, 10, 1 }, // 3D + { 128, 128, 5, 10, 1 }, // 3D over 5 channels + { 128, 128, 1, 10, 30 }, // 4D + { 128, 128, 5, 10, 30 }, // 4D over 5 channels + { 128, 128, 1, 1, 30 }, // 2D + T + { 128, 128, 5, 1, 30 } // 2D + T over 5 channels + + }; + + /** Corresponding calibrations. */ + final float[][] calibration = new float[][] { + // X Y C (ignored) Z T + { 0.2f, 0.2f, Float.NaN, 1.5f, 2 }, + { 0.2f, 0.2f, Float.NaN, 1.5f, 2 }, + { 0.2f, 0.2f, Float.NaN, 1.5f, 2 }, + { 0.2f, 0.2f, Float.NaN, 1.5f, 2 }, + { 0.2f, 0.2f, Float.NaN, 1.5f, 2 }, + { 0.2f, 0.2f, Float.NaN, 1.5f, 2 }, + { 0.2f, 0.2f, Float.NaN, 1.5f, 2 } + + }; + + final String[] units = new String[] { "um", "mm", "cm", "minutes" }; + + @Test + public void testDimensionality() + { + for ( int i = 0; i < dim.length; i++ ) + testDimensionality( dim[ i ], calibration[ i ] ); + } + + private void testDimensionality( final int[] dim, final float[] calibration ) + { + final ImagePlus imp = createCalibratedImagePlus( dim, calibration ); + final ImgPlus< T > img = ImagePlusToImgPlus.wrapImgPlus( imp ); + // Print stuff +// System.out.println( "got: " + img.getName() ); +// for ( int d = 0; d < img.numDimensions(); d++ ) +// { +// System.out.println( " Axis " + d + "\t - " + img.axis( d ) + ", spacing = " + img.calibration( d ) + ", dimension = " + img.dimension( d ) ); +// } + assertEquals( getExpectedNumDimensions( dim ), img.numDimensions() ); + checkDimensionality( dim, img ); + checkCalibration( dim, calibration, img ); + } + + private ImagePlus createCalibratedImagePlus( final int[] dim, final float[] calibration ) + { + // Create ImagePlus + final int slices = dim[ 2 ] * dim[ 3 ] * dim[ 4 ]; + final ImagePlus imp = NewImage.createByteImage( "Test", dim[ 0 ], dim[ 1 ], slices, NewImage.FILL_BLACK ); + imp.setDimensions( dim[ 2 ], dim[ 3 ], dim[ 4 ] ); + + // Set calibration + final Calibration impCal = imp.getCalibration(); + impCal.pixelWidth = calibration[ 0 ]; + impCal.pixelHeight = calibration[ 1 ]; + // 2 is for channels + impCal.pixelDepth = calibration[ 3 ]; + impCal.frameInterval = calibration[ 4 ]; + impCal.setXUnit( units[ 0 ] ); + impCal.setYUnit( units[ 1 ] ); + impCal.setZUnit( units[ 2 ] ); + impCal.setTimeUnit( units[ 3 ] ); + + // Print stuff +// System.out.println( "\nFor ImagePlus " + imp + " with " + imp.getCalibration() ); + return imp; + } + + private int getExpectedNumDimensions( final int[] dim ) + { + // Are num dimension correct? + int expectedNumDimensions = 0; + for ( int d = 0; d < dim.length; d++ ) + { + if ( dim[ d ] > 1 ) + expectedNumDimensions++; + } + return expectedNumDimensions; + } + + private void checkDimensionality( final int[] dim, final ImgPlus< T > img ) + { + int skipDim = 0; + for ( int d = 0; d < dim.length; d++ ) + { + if ( dim[ d ] > 1 ) + { + // imglib skips singleton dimensions, so we must test only + // against non-singleton dimension + assertEquals( + String.format( "For dimension %d, expected %d, but got %d.", d, dim[ d ], img.dimension( skipDim ) ), + dim[ d ], img.dimension( skipDim ) ); + skipDim++; + } + } + } + + private void checkCalibration( final int[] dim, final float[] calibration, final ImgPlus< T > img ) + { + int skipDim = 0; + for ( int d = 0; d < calibration.length; d++ ) + { + if ( dim[ d ] > 1 ) + { + // Is it the channel axis? + if ( d < getExpectedNumDimensions( dim ) && img.axis( d ).type() == Axes.CHANNEL ) + { + + // Then the calibration should be 1, + assertEquals( 1f, img.averageScale( skipDim ), + Float.MIN_VALUE ); + + } + else + { + + // otherwise it should be what we set. + assertEquals( calibration[ d ], img.averageScale( skipDim ), + Float.MIN_VALUE ); + } + skipDim++; + + } + } + } +} diff --git a/src/test/java/net/imglib2/imagej/ImgPlusToImagePlusTest.java b/src/test/java/net/imglib2/imagej/ImgPlusToImagePlusTest.java index 0a5c5c7..965955d 100644 --- a/src/test/java/net/imglib2/imagej/ImgPlusToImagePlusTest.java +++ b/src/test/java/net/imglib2/imagej/ImgPlusToImagePlusTest.java @@ -34,151 +34,271 @@ package net.imglib2.imagej; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import java.util.concurrent.atomic.AtomicInteger; + import net.imagej.ImgPlus; import net.imagej.axis.Axes; -import net.imglib2.type.NativeType; -import net.imglib2.type.numeric.NumericType; +import net.imagej.axis.AxisType; +import net.imglib2.FinalInterval; +import net.imglib2.RandomAccessibleInterval; +import net.imglib2.img.Img; +import net.imglib2.img.ImgView; +import net.imglib2.img.array.ArrayImgs; +import net.imglib2.type.logic.BitType; +import net.imglib2.type.logic.BoolType; +import net.imglib2.type.numeric.IntegerType; +import net.imglib2.type.numeric.RealType; +import net.imglib2.type.numeric.integer.ByteType; +import net.imglib2.type.numeric.integer.IntType; +import net.imglib2.type.numeric.integer.LongType; +import net.imglib2.type.numeric.integer.ShortType; +import net.imglib2.type.numeric.integer.Unsigned128BitType; +import net.imglib2.type.numeric.integer.Unsigned12BitType; +import net.imglib2.type.numeric.integer.Unsigned2BitType; +import net.imglib2.type.numeric.integer.Unsigned4BitType; +import net.imglib2.type.numeric.integer.UnsignedByteType; +import net.imglib2.type.numeric.integer.UnsignedIntType; +import net.imglib2.type.numeric.integer.UnsignedLongType; +import net.imglib2.type.numeric.integer.UnsignedShortType; +import net.imglib2.type.numeric.real.DoubleType; +import net.imglib2.type.numeric.real.FloatType; +import net.imglib2.util.ConstantUtils; +import net.imglib2.view.Views; +import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import ij.ImagePlus; -import ij.gui.NewImage; -import ij.measure.Calibration; +import ij.process.ByteProcessor; +import ij.process.FloatProcessor; +import ij.process.ImageProcessor; +import ij.process.ShortProcessor; -public class ImgPlusToImagePlusTest< T extends NumericType< T > & NativeType< T > > +public class ImgPlusToImagePlusTest { + @Test + public void testAxisOrder() + { + final Img< UnsignedByteType > img = ArrayImgs.unsignedBytes( 1, 1, 2, 3, 4 ); + fill( img ); + final ImgPlus< UnsignedByteType > imgPlus = new ImgPlus<>( img, "title", new AxisType[] { Axes.X, Axes.Y, Axes.TIME, Axes.CHANNEL, Axes.Z } ); + final ImagePlus imagePlus = ImgPlusToImagePlus.wrap( imgPlus, false ); + assertEquals( 2, imagePlus.getStack().getProcessor( imagePlus.getStackIndex( 1, 1, 2 ) ).get( 0, 0 ) ); + assertEquals( 7, imagePlus.getStack().getProcessor( imagePlus.getStackIndex( 1, 2, 1 ) ).get( 0, 0 ) ); + assertEquals( 3, imagePlus.getStack().getProcessor( imagePlus.getStackIndex( 2, 1, 1 ) ).get( 0, 0 ) ); + } + + @Test + public void test1DStack() + { + final Img< UnsignedByteType > img = ArrayImgs.unsignedBytes( 2, 2 ); + fill( img ); + final ImgPlus< UnsignedByteType > imgPlus = new ImgPlus<>( img, "title", new AxisType[] { Axes.TIME, Axes.X } ); + final ImagePlus imagePlus = ImgPlusToImagePlus.wrap( imgPlus, false ); + assertArrayEquals( new byte[] { 1, 3 }, ( byte[] ) imagePlus.getStack().getPixels( imagePlus.getStackIndex( 1, 1, 1 ) ) ); + assertArrayEquals( new byte[] { 2, 4 }, ( byte[] ) imagePlus.getStack().getPixels( imagePlus.getStackIndex( 1, 1, 2 ) ) ); + } + + @Test + public void testNoXY() + { + final Img< UnsignedByteType > img = ArrayImgs.unsignedBytes( 2, 2 ); + fill( img ); + final ImgPlus< UnsignedByteType > imgPlus = new ImgPlus<>( img, "title", new AxisType[] { Axes.TIME, Axes.CHANNEL } ); + final ImagePlus imagePlus = ImgPlusToImagePlus.wrap( imgPlus, false ); + assertArrayEquals( new byte[] { 2 }, ( byte[] ) imagePlus.getStack().getPixels( imagePlus.getStackIndex( 1, 1, 2 ) ) ); + assertArrayEquals( new byte[] { 3 }, ( byte[] ) imagePlus.getStack().getPixels( imagePlus.getStackIndex( 2, 1, 1 ) ) ); + } + + @Ignore( "not supporting more than five dimensions yet" ) + @Test + public void test6d() + { + final Img< UnsignedByteType > img = ArrayImgs.unsignedBytes( 2, 2, 2, 2, 2, 2 ); + fill( img ); + final ImgPlus< UnsignedByteType > imgPlus = new ImgPlus<>( img, "title", new AxisType[] { Axes.X, Axes.Y, Axes.Z, Axes.CHANNEL, Axes.TIME, Axes.CHANNEL } ); + final ImagePlus imagePlus = ImgPlusToImagePlus.wrap( imgPlus, true ); + assertArrayEquals( new byte[] { 2 }, ( byte[] ) imagePlus.getStack().getPixels( imagePlus.getStackIndex( 1, 1, 2 ) ) ); + assertArrayEquals( new byte[] { 3 }, ( byte[] ) imagePlus.getStack().getPixels( imagePlus.getStackIndex( 2, 1, 1 ) ) ); + } + + @Test + public void testColoredAxisOrder() + { + final Img< UnsignedByteType > img = ArrayImgs.unsignedBytes( 1, 1, 2, 3, 4 ); + fill( img ); + final ImgPlus< UnsignedByteType > imgPlus = new ImgPlus<>( img, "title", new AxisType[] { Axes.X, Axes.Y, Axes.TIME, Axes.CHANNEL, Axes.Z } ); + final ImagePlus imagePlus = ImgPlusToImagePlus.wrap( imgPlus, true ); + assertEquals( 0xff020406, imagePlus.getStack().getProcessor( imagePlus.getStackIndex( 1, 1, 2 ) ).get( 0, 0 ) ); + assertEquals( 0xff07090b, imagePlus.getStack().getProcessor( imagePlus.getStackIndex( 1, 2, 1 ) ).get( 0, 0 ) ); + } + + @Test + public void testBitType() + { + testTypeConversion( ByteProcessor.class, 1, new BitType( true ) ); + } + + @Test + public void testBoolType() + { + testTypeConversion( ByteProcessor.class, 1, new BoolType( true ) ); + } + + @Test + public void testUnsigned2BitType() + { + testTypeConversion( ByteProcessor.class, 3, new Unsigned2BitType( 3 ) ); + } + + @Test + public void testUnsigned4BitTypeType() + { + testTypeConversion( ByteProcessor.class, 15, new Unsigned4BitType( 15 ) ); + } + + @Test + public void testUnsignedByteType() + { + testTypeConversion( ByteProcessor.class, 42f, new UnsignedByteType( 42 ) ); + } + + @Test + public void testUnsigned12BitType() + { + testTypeConversion( ShortProcessor.class, 420, new Unsigned12BitType( 420 ) ); + } + + @Test + public void testUnsignedShortType() + { + testTypeConversion( ShortProcessor.class, 42f, new UnsignedShortType( 42 ) ); + } + + @Test + public void testUnsignedIntType() + { + testTypeConversion( FloatProcessor.class, 42, new UnsignedIntType( 42 ) ); + } + + @Test + public void testUnsignedLongType() + { + testTypeConversion( FloatProcessor.class, 42, new UnsignedLongType( 42 ) ); + } + + @Test + public void testUnsigned128BitType() + { + testTypeConversion( FloatProcessor.class, 1000000, new Unsigned128BitType( 1000000, 0 ) ); + } + + @Test + public void testByteType() + { + testTypeConversion( FloatProcessor.class, -42, new ByteType( ( byte ) -42 ) ); + } + + @Test + public void testShortType() + { + testTypeConversion( FloatProcessor.class, -42, new ShortType( ( short ) -42 ) ); + } + + @Test + public void testIntType() + { + testTypeConversion( FloatProcessor.class, -42, new IntType( -42 ) ); + } + + @Test + public void testLongType() + { + testTypeConversion( FloatProcessor.class, -42, new LongType( -42 ) ); + } - /** Which dimensions to test. */ - final int[][] dim = new int[][] { - // nX nY nC nZ nT - { 128, 128, 1, 1, 1 }, // 2D - { 128, 128, 1, 10, 1 }, // 3D - { 128, 128, 5, 10, 1 }, // 3D over 5 channels - { 128, 128, 1, 10, 30 }, // 4D - { 128, 128, 5, 10, 30 }, // 4D over 5 channels - { 128, 128, 1, 1, 30 }, // 2D + T - { 128, 128, 5, 1, 30 } // 2D + T over 5 channels - - }; - - /** Corresponding calibrations. */ - final float[][] calibration = new float[][] { - // X Y C (ignored) Z T - { 0.2f, 0.2f, Float.NaN, 1.5f, 2 }, - { 0.2f, 0.2f, Float.NaN, 1.5f, 2 }, - { 0.2f, 0.2f, Float.NaN, 1.5f, 2 }, - { 0.2f, 0.2f, Float.NaN, 1.5f, 2 }, - { 0.2f, 0.2f, Float.NaN, 1.5f, 2 }, - { 0.2f, 0.2f, Float.NaN, 1.5f, 2 }, - { 0.2f, 0.2f, Float.NaN, 1.5f, 2 } - - }; - - final String[] units = new String[] { "um", "mm", "cm", "minutes" }; - - @Test - public void testDimensionality() - { - for ( int i = 0; i < dim.length; i++ ) - testDimensionality( dim[ i ], calibration[ i ] ); - } - - private void testDimensionality( final int[] dim, final float[] calibration ) - { - final ImagePlus imp = createCalibratedImagePlus( dim, calibration ); - final ImgPlus< T > img = ImagePlusToImgPlus.wrapImgPlus( imp ); - // Print stuff -// System.out.println( "got: " + img.getName() ); -// for ( int d = 0; d < img.numDimensions(); d++ ) -// { -// System.out.println( " Axis " + d + "\t - " + img.axis( d ) + ", spacing = " + img.calibration( d ) + ", dimension = " + img.dimension( d ) ); -// } - assertEquals( getExpectedNumDimensions( dim ), img.numDimensions() ); - checkDimensionality( dim, img ); - checkCalibration( dim, calibration, img ); - } - - private ImagePlus createCalibratedImagePlus( final int[] dim, final float[] calibration ) - { - // Create ImagePlus - final int slices = dim[ 2 ] * dim[ 3 ] * dim[ 4 ]; - final ImagePlus imp = NewImage.createByteImage( "Test", dim[ 0 ], dim[ 1 ], slices, NewImage.FILL_BLACK ); - imp.setDimensions( dim[ 2 ], dim[ 3 ], dim[ 4 ] ); - - // Set calibration - final Calibration impCal = imp.getCalibration(); - impCal.pixelWidth = calibration[ 0 ]; - impCal.pixelHeight = calibration[ 1 ]; - // 2 is for channels - impCal.pixelDepth = calibration[ 3 ]; - impCal.frameInterval = calibration[ 4 ]; - impCal.setXUnit( units[ 0 ] ); - impCal.setYUnit( units[ 1 ] ); - impCal.setZUnit( units[ 2 ] ); - impCal.setTimeUnit( units[ 3 ] ); - - // Print stuff -// System.out.println( "\nFor ImagePlus " + imp + " with " + imp.getCalibration() ); - return imp; - } - - private int getExpectedNumDimensions( final int[] dim ) - { - // Are num dimension correct? - int expectedNumDimensions = 0; - for ( int d = 0; d < dim.length; d++ ) - { - if ( dim[ d ] > 1 ) - expectedNumDimensions++; - } - return expectedNumDimensions; - } - - private void checkDimensionality( final int[] dim, final ImgPlus< T > img ) - { - int skipDim = 0; - for ( int d = 0; d < dim.length; d++ ) - { - if ( dim[ d ] > 1 ) - { - // imglib skips singleton dimensions, so we must test only - // against non-singleton dimension - assertEquals( - String.format( "For dimension %d, expected %d, but got %d.", d, dim[ d ], img.dimension( skipDim ) ), - dim[ d ], img.dimension( skipDim ) ); - skipDim++; - } - } - } - - private void checkCalibration( final int[] dim, final float[] calibration, final ImgPlus< T > img ) - { - int skipDim = 0; - for ( int d = 0; d < calibration.length; d++ ) - { - if ( dim[ d ] > 1 ) - { - // Is it the channel axis? - if ( d < getExpectedNumDimensions( dim ) && img.axis( d ).type() == Axes.CHANNEL ) - { - - // Then the calibration should be 1, - assertEquals( 1f, img.averageScale( skipDim ), - Float.MIN_VALUE ); - - } - else - { - - // otherwise it should be what we set. - assertEquals( calibration[ d ], img.averageScale( skipDim ), - Float.MIN_VALUE ); - } - skipDim++; - - } - } + @Test + public void testFloatType() + { + testTypeConversion( FloatProcessor.class, -42f, new FloatType( -42 ) ); + } + + @Test + public void testDoubleType() + { + testTypeConversion( FloatProcessor.class, -42f, new DoubleType( -42 ) ); + } + + private < T extends RealType< T > > void testTypeConversion( final Class< ? extends ImageProcessor > processorClass, final float expected, final T input ) + { + final RandomAccessibleInterval< T > rai = ConstantUtils.constantRandomAccessibleInterval( input, 2, new FinalInterval( 1, 1 ) ); + final Img< T > image = ImgView.wrap( rai, null ); + final ImgPlus< T > imgPlus = new ImgPlus< T >( image, "title", new AxisType[] { Axes.X, Axes.Y } ); + // process + final ImagePlus imagePlus = ImgPlusToImagePlus.wrap( imgPlus, false ); + // test + final ImageProcessor processor = imagePlus.getProcessor(); + Assert.assertTrue( processorClass.isInstance( processor ) ); + Assert.assertEquals( expected, processor.getPixelValue( 0, 0 ), 0f ); + } + + private void fill( final RandomAccessibleInterval< ? extends IntegerType > img ) + { + final AtomicInteger i = new AtomicInteger(); + Views.flatIterable( img ).forEach( pixel -> pixel.setInteger( i.incrementAndGet() ) ); + } + + @Test + public void testUnknownAxes() + { + final byte[] array = { 1, 2, 3, 4, 5, 6 }; + final Img< UnsignedByteType > img = ArrayImgs.unsignedBytes( array, 1, 1, 2, 3 ); + final AxisType[] axes = { Axes.unknown(), Axes.unknown(), Axes.TIME, Axes.unknown() }; + final ImagePlus result = ImgPlusToImagePlus.wrap( new ImgPlus<>( img, "title", axes ), false ); + assertEquals( 3, result.getNChannels() ); + assertEquals( 2, result.getNFrames() ); + } + + @Test + public void testPersistence() + { + // setup + final Img< FloatType > img = ArrayImgs.floats( 1, 1 ); + final ImgPlus< FloatType > imgPlus = new ImgPlus<>( img, "title", new AxisType[] { Axes.X, Axes.Y } ); + final ImagePlus imagePlus = ImgPlusToImagePlus.wrap( imgPlus, false ); + final float expected = 42; + // process + final ImageProcessor processor = imagePlus.getStack().getProcessor( 1 ); + processor.setf( 0, 0, expected ); + imagePlus.getStack().setPixels( processor.getPixels(), 1 ); // NB: + // required + // to signal + // data + // changed + // test + assertEquals( expected, img.cursor().next().get(), 0.0f ); + } + + @Test + public void testPersistenceBits() + { + // setup + final Img< BitType > img = ArrayImgs.bits( 1, 1 ); + final ImgPlus< BitType > imgPlus = new ImgPlus<>( img, "title", new AxisType[] { Axes.X, Axes.Y } ); + final ImagePlus imagePlus = ImgPlusToImagePlus.wrapAndScaleBitType( imgPlus ); + // process + final ImageProcessor processor = imagePlus.getStack().getProcessor( 1 ); + processor.setf( 0, 0, 255 ); + imagePlus.getStack().setPixels( processor.getPixels(), 1 ); // NB: + // required + // to signal + // data + // changed + // test + assertEquals( true, img.cursor().next().get() ); } } diff --git a/src/test/java/net/imglib2/imagej/display/ArrayImgToVirtualStackTest.java b/src/test/java/net/imglib2/imagej/display/ArrayImgToImagePlusTest.java similarity index 91% rename from src/test/java/net/imglib2/imagej/display/ArrayImgToVirtualStackTest.java rename to src/test/java/net/imglib2/imagej/display/ArrayImgToImagePlusTest.java index 212edda..843c510 100644 --- a/src/test/java/net/imglib2/imagej/display/ArrayImgToVirtualStackTest.java +++ b/src/test/java/net/imglib2/imagej/display/ArrayImgToImagePlusTest.java @@ -53,7 +53,7 @@ import ij.ImagePlus; -public class ArrayImgToVirtualStackTest +public class ArrayImgToImagePlusTest { @Test public void testSharedBuffer() @@ -62,7 +62,7 @@ public void testSharedBuffer() final int height = 3; final byte[] buffer = new byte[ width * height ]; final ImgPlus< UnsignedByteType > img = new ImgPlus<>( ArrayImgs.unsignedBytes( buffer, width, height ) ); - final ImagePlus imagePlus = ArrayImgToVirtualStack.wrap( img ); + final ImagePlus imagePlus = ArrayImgToImagePlus.wrap( img ); assertEquals( width, imagePlus.getWidth() ); assertEquals( height, imagePlus.getHeight() ); assertSame( buffer, imagePlus.getProcessor().getPixels() ); @@ -75,9 +75,9 @@ public void testIsSupported() final ImgPlus< UnsignedByteType > unsupported1 = new ImgPlus<>( ArrayImgs.unsignedBytes( 2, 2, 3 ), "image", new AxisType[] { Axes.X, Axes.Y, Axes.Z } ); final CellImg< UnsignedByteType, ? > cellImg = new CellImgFactory<>( new UnsignedByteType() ).create( 2, 2 ); final ImgPlus< UnsignedByteType > unsupported2 = new ImgPlus<>( cellImg, "image", new AxisType[] { Axes.X, Axes.Y } ); - assertTrue( ArrayImgToVirtualStack.isSupported( supported ) ); - assertFalse( ArrayImgToVirtualStack.isSupported( unsupported1 ) ); - assertFalse( ArrayImgToVirtualStack.isSupported( unsupported2 ) ); + assertTrue( ArrayImgToImagePlus.isSupported( supported ) ); + assertFalse( ArrayImgToImagePlus.isSupported( unsupported1 ) ); + assertFalse( ArrayImgToImagePlus.isSupported( unsupported2 ) ); } @Test @@ -87,7 +87,7 @@ public void testPersistence() final float expected = 42.0f; final Img< FloatType > img = ArrayImgs.floats( 1, 1 ); final ImgPlus< FloatType > imgPlus = new ImgPlus<>( img, "title", new AxisType[] { Axes.X, Axes.Y } ); - final ImagePlus imagePlus = ArrayImgToVirtualStack.wrap( imgPlus ); + final ImagePlus imagePlus = ArrayImgToImagePlus.wrap( imgPlus ); // process imagePlus.getProcessor().setf( 0, 0, expected ); // test diff --git a/src/test/java/net/imglib2/imagej/display/CellImgToVirtualStackTest.java b/src/test/java/net/imglib2/imagej/display/CellImgToImagePlusTest.java similarity index 77% rename from src/test/java/net/imglib2/imagej/display/CellImgToVirtualStackTest.java rename to src/test/java/net/imglib2/imagej/display/CellImgToImagePlusTest.java index 6374c32..842282d 100644 --- a/src/test/java/net/imglib2/imagej/display/CellImgToVirtualStackTest.java +++ b/src/test/java/net/imglib2/imagej/display/CellImgToImagePlusTest.java @@ -55,9 +55,9 @@ import static org.junit.Assert.assertTrue; /** - * Tests {@link CellImgToVirtualStack}. + * Tests {@link CellImgToImagePlus}. */ -public class CellImgToVirtualStackTest +public class CellImgToImagePlusTest { @Test @@ -71,7 +71,7 @@ public void test3D() { private ImageStack wrap( Img< ? > image ) { - return CellImgToVirtualStack.wrap( ImgPlus.wrap( image ) ).getStack(); + return CellImgToImagePlus.wrap( ImgPlus.wrap( image ) ).getStack(); } @Test @@ -98,7 +98,7 @@ public void testAxisOrder() final Img< UnsignedByteType > img = new CellImgFactory<>( new UnsignedByteType(), 1, 1, 1, 1, 1).create( new long[] { 1, 1, 2, 3, 4 } ); fill( img ); final ImgPlus< UnsignedByteType > imgPlus = new ImgPlus<>( img, "title", new AxisType[] { Axes.X, Axes.Y, Axes.TIME, Axes.CHANNEL, Axes.Z } ); - final ImagePlus imagePlus = CellImgToVirtualStack.wrap( imgPlus ); + final ImagePlus imagePlus = CellImgToImagePlus.wrap( imgPlus ); assertEquals( 2, imagePlus.getStack().getProcessor( imagePlus.getStackIndex( 1, 1, 2 ) ).get( 0, 0 ) ); assertEquals( 7, imagePlus.getStack().getProcessor( imagePlus.getStackIndex( 1, 2, 1 ) ).get( 0, 0 ) ); assertEquals( 3, imagePlus.getStack().getProcessor( imagePlus.getStackIndex( 2, 1, 1 ) ).get( 0, 0 ) ); @@ -107,39 +107,39 @@ public void testAxisOrder() @Test public void testIsSupported() { - assertTrue( CellImgToVirtualStack.isSupported( ImgPlus.wrap( new CellImgFactory<>( new UnsignedByteType(), 2, 2 ).create( 2, 2 ) ) ) ); + assertTrue( CellImgToImagePlus.isSupported( ImgPlus.wrap( new CellImgFactory<>( new UnsignedByteType(), 2, 2 ).create( 2, 2 ) ) ) ); } @Test public void testIsSupported_FloatType() { - assertTrue( CellImgToVirtualStack.isSupported( ImgPlus.wrap( new CellImgFactory<>( new FloatType(), 2, 2 ).create( 2, 2 ) ) ) ); + assertTrue( CellImgToImagePlus.isSupported( ImgPlus.wrap( new CellImgFactory<>( new FloatType(), 2, 2 ).create( 2, 2 ) ) ) ); } @Test public void testIsSupported_UnsupportedType() { - assertFalse( CellImgToVirtualStack.isSupported( ImgPlus.wrap( new CellImgFactory<>( new DoubleType(), 2, 2 ).create( 2, 2 ) ) ) ); + assertFalse( CellImgToImagePlus.isSupported( ImgPlus.wrap( new CellImgFactory<>( new DoubleType(), 2, 2 ).create( 2, 2 ) ) ) ); } @Test public void testIsSupported_PlanarCells() { - assertTrue( CellImgToVirtualStack.isSupported( ImgPlus.wrap( new CellImgFactory<>( new FloatType(), 7, 2 ).create( 2, 2 ) ) ) ); - assertTrue( CellImgToVirtualStack.isSupported( ImgPlus.wrap( new CellImgFactory<>( new FloatType(), 2, 2, 3 ).create( 2, 2, 1 ) ) ) ); + assertTrue( CellImgToImagePlus.isSupported( ImgPlus.wrap( new CellImgFactory<>( new FloatType(), 7, 2 ).create( 2, 2 ) ) ) ); + assertTrue( CellImgToImagePlus.isSupported( ImgPlus.wrap( new CellImgFactory<>( new FloatType(), 2, 2, 3 ).create( 2, 2, 1 ) ) ) ); } @Test public void testIsSupported_NoPlanarCells() { - assertFalse( CellImgToVirtualStack.isSupported( ImgPlus.wrap( new CellImgFactory<>( new FloatType(), 1, 2 ).create( 2, 2 ) ) ) ); - assertFalse( CellImgToVirtualStack.isSupported( ImgPlus.wrap( new CellImgFactory<>( new FloatType(), 2, 2, 3 ).create( 2, 2, 3 ) ) ) ); + assertFalse( CellImgToImagePlus.isSupported( ImgPlus.wrap( new CellImgFactory<>( new FloatType(), 1, 2 ).create( 2, 2 ) ) ) ); + assertFalse( CellImgToImagePlus.isSupported( ImgPlus.wrap( new CellImgFactory<>( new FloatType(), 2, 2, 3 ).create( 2, 2, 3 ) ) ) ); } @Test public void testIsSupported_WrongAxis() { final Img< FloatType > cellImg = new CellImgFactory<>( new FloatType(), 2, 2, 3 ).create( 2, 2, 1 ); - assertTrue( CellImgToVirtualStack.isSupported( new ImgPlus<>( cellImg, "title", new AxisType[]{ Axes.X, Axes.Y, Axes.unknown() } ) ) ); - assertFalse( CellImgToVirtualStack.isSupported( new ImgPlus<>( cellImg, "title", new AxisType[]{ Axes.X, Axes.Z, Axes.TIME } ) ) ); + assertTrue( CellImgToImagePlus.isSupported( new ImgPlus<>( cellImg, "title", new AxisType[]{ Axes.X, Axes.Y, Axes.unknown() } ) ) ); + assertFalse( CellImgToImagePlus.isSupported( new ImgPlus<>( cellImg, "title", new AxisType[]{ Axes.X, Axes.Z, Axes.TIME } ) ) ); } private void fill( RandomAccessibleInterval< ? extends IntegerType< ? > > image ) @@ -154,7 +154,7 @@ public void testPersistence() { // setup final Img< FloatType > img = new CellImgFactory<>( new FloatType() ).create( 1, 1, 1 ); - final ImagePlus imagePlus = CellImgToVirtualStack.wrap( ImgPlus.wrap( img ) ); + final ImagePlus imagePlus = CellImgToImagePlus.wrap( ImgPlus.wrap( img ) ); final float expected = 42.0f; // process imagePlus.getProcessor().setf( 0, 0, expected ); @@ -166,7 +166,7 @@ public void testPersistence() public void testSetPixels() { // setup final Img< FloatType > img = new CellImgFactory<>( new FloatType() ).create( 1, 1, 1 ); - final ImagePlus imagePlus = CellImgToVirtualStack.wrap( new ImgPlus<>( img, "title" ) ); + final ImagePlus imagePlus = CellImgToImagePlus.wrap( new ImgPlus<>( img, "title" ) ); final float expected = 42.0f; // process imagePlus.getStack().setPixels( new float[] { expected }, 1 ); diff --git a/src/test/java/net/imglib2/imagej/display/ImageJVirtualStackGetProcessorBenchmark.java b/src/test/java/net/imglib2/imagej/display/ImageJVirtualStackGetProcessorBenchmark.java index d50e166..e186609 100644 --- a/src/test/java/net/imglib2/imagej/display/ImageJVirtualStackGetProcessorBenchmark.java +++ b/src/test/java/net/imglib2/imagej/display/ImageJVirtualStackGetProcessorBenchmark.java @@ -35,6 +35,7 @@ import ij.ImageStack; import net.imagej.ImgPlus; +import net.imglib2.imagej.ImgPlusToImagePlus; import net.imglib2.img.Img; import net.imglib2.img.array.ArrayImgFactory; import net.imglib2.type.NativeType; @@ -106,7 +107,7 @@ public void all() { private < T extends NativeType< T > > void test( T type ) { Img< T > image = getImage( type ); - ImageStack stack = ImgToVirtualStack.wrap( new ImgPlus<>( image ) ).getStack(); + ImageStack stack = ImgPlusToImagePlus.wrap( new ImgPlus<>( image ) ).getStack(); for ( int i = 0; i < stack.getSize(); i++ ) { stack.getProcessor( i + 1 ); diff --git a/src/test/java/net/imglib2/imagej/display/ImgLib2ToVirtualStackBenchmark.java b/src/test/java/net/imglib2/imagej/display/ImgLib2ToVirtualStackBenchmark.java index e96e666..d441086 100644 --- a/src/test/java/net/imglib2/imagej/display/ImgLib2ToVirtualStackBenchmark.java +++ b/src/test/java/net/imglib2/imagej/display/ImgLib2ToVirtualStackBenchmark.java @@ -36,6 +36,7 @@ import net.imagej.ImgPlus; import net.imagej.axis.Axes; import net.imagej.axis.AxisType; +import net.imglib2.imagej.ImgPlusToImagePlus; import net.imglib2.img.Img; import net.imglib2.img.array.ArrayImgs; import net.imglib2.img.cell.CellImgFactory; @@ -71,49 +72,49 @@ public class ImgLib2ToVirtualStackBenchmark @Benchmark public void testSmallCellImg() { - ImgToVirtualStack.wrap( smallCellImage ); + ImgPlusToImagePlus.wrap( smallCellImage ); } @Benchmark public void testDeepCellImg() { - ImgToVirtualStack.wrap( deepCellImage ); + ImgPlusToImagePlus.wrap( deepCellImage ); } @Benchmark public void testCubicCellImg() { - ImgToVirtualStack.wrap( cubicCellImage ); + ImgPlusToImagePlus.wrap( cubicCellImage ); } @Benchmark public void testSmallPlanarImg() { - PlanarImgToVirtualStack.wrap( smallPlanarImg ); + PlanarImgToImagePlus.wrap( smallPlanarImg ); } @Benchmark public void testCubicPlanarImg() { - PlanarImgToVirtualStack.wrap( cubicPlanarImg ); + PlanarImgToImagePlus.wrap( cubicPlanarImg ); } @Benchmark public void testDeepPlanarImg() { - PlanarImgToVirtualStack.wrap( deepPlanarImg ); + PlanarImgToImagePlus.wrap( deepPlanarImg ); } @Benchmark public void testSmall2dArrayImg() { - ArrayImgToVirtualStack.wrap( small2dArrayImg ); + ArrayImgToImagePlus.wrap( small2dArrayImg ); } @Benchmark public void testLarge2dArrayImg() { - ArrayImgToVirtualStack.wrap( big2dArrayImg ); + ArrayImgToImagePlus.wrap( big2dArrayImg ); } private ImgPlus< UnsignedByteType > makeImgPlus( final Img< UnsignedByteType > deepPlanarImg ) diff --git a/src/test/java/net/imglib2/imagej/display/ImgToVirtualStackTest.java b/src/test/java/net/imglib2/imagej/display/ImgToVirtualStackTest.java deleted file mode 100644 index 6040e62..0000000 --- a/src/test/java/net/imglib2/imagej/display/ImgToVirtualStackTest.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * #%L - * ImgLib2: a general-purpose, multidimensional image processing library. - * %% - * Copyright (C) 2009 - 2025 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.imagej.display; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; - -import java.util.concurrent.atomic.AtomicInteger; - -import net.imagej.ImgPlus; -import net.imagej.axis.Axes; -import net.imagej.axis.AxisType; -import net.imglib2.FinalInterval; -import net.imglib2.RandomAccessibleInterval; -import net.imglib2.img.Img; -import net.imglib2.img.ImgView; -import net.imglib2.img.array.ArrayImgs; -import net.imglib2.type.logic.BitType; -import net.imglib2.type.logic.BoolType; -import net.imglib2.type.numeric.IntegerType; -import net.imglib2.type.numeric.RealType; -import net.imglib2.type.numeric.integer.ByteType; -import net.imglib2.type.numeric.integer.IntType; -import net.imglib2.type.numeric.integer.LongType; -import net.imglib2.type.numeric.integer.ShortType; -import net.imglib2.type.numeric.integer.Unsigned128BitType; -import net.imglib2.type.numeric.integer.Unsigned12BitType; -import net.imglib2.type.numeric.integer.Unsigned2BitType; -import net.imglib2.type.numeric.integer.Unsigned4BitType; -import net.imglib2.type.numeric.integer.UnsignedByteType; -import net.imglib2.type.numeric.integer.UnsignedIntType; -import net.imglib2.type.numeric.integer.UnsignedLongType; -import net.imglib2.type.numeric.integer.UnsignedShortType; -import net.imglib2.type.numeric.real.DoubleType; -import net.imglib2.type.numeric.real.FloatType; -import net.imglib2.util.ConstantUtils; -import net.imglib2.view.Views; - -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - -import ij.ImagePlus; -import ij.process.ByteProcessor; -import ij.process.FloatProcessor; -import ij.process.ImageProcessor; -import ij.process.ShortProcessor; - -public class ImgToVirtualStackTest -{ - @Test - public void testAxisOrder() - { - final Img< UnsignedByteType > img = ArrayImgs.unsignedBytes( 1, 1, 2, 3, 4 ); - fill( img ); - final ImgPlus< UnsignedByteType > imgPlus = new ImgPlus<>( img, "title", new AxisType[] { Axes.X, Axes.Y, Axes.TIME, Axes.CHANNEL, Axes.Z } ); - final ImagePlus imagePlus = ImgToVirtualStack.wrap( imgPlus, false ); - assertEquals( 2, imagePlus.getStack().getProcessor( imagePlus.getStackIndex( 1, 1, 2 ) ).get( 0, 0 ) ); - assertEquals( 7, imagePlus.getStack().getProcessor( imagePlus.getStackIndex( 1, 2, 1 ) ).get( 0, 0 ) ); - assertEquals( 3, imagePlus.getStack().getProcessor( imagePlus.getStackIndex( 2, 1, 1 ) ).get( 0, 0 ) ); - } - - @Test - public void test1DStack() - { - final Img< UnsignedByteType > img = ArrayImgs.unsignedBytes( 2, 2 ); - fill( img ); - final ImgPlus< UnsignedByteType > imgPlus = new ImgPlus<>( img, "title", new AxisType[] { Axes.TIME, Axes.X } ); - final ImagePlus imagePlus = ImgToVirtualStack.wrap( imgPlus, false ); - assertArrayEquals( new byte[] { 1, 3 }, ( byte[] ) imagePlus.getStack().getPixels( imagePlus.getStackIndex( 1, 1, 1 ) ) ); - assertArrayEquals( new byte[] { 2, 4 }, ( byte[] ) imagePlus.getStack().getPixels( imagePlus.getStackIndex( 1, 1, 2 ) ) ); - } - - @Test - public void testNoXY() - { - final Img< UnsignedByteType > img = ArrayImgs.unsignedBytes( 2, 2 ); - fill( img ); - final ImgPlus< UnsignedByteType > imgPlus = new ImgPlus<>( img, "title", new AxisType[] { Axes.TIME, Axes.CHANNEL } ); - final ImagePlus imagePlus = ImgToVirtualStack.wrap( imgPlus, false ); - assertArrayEquals( new byte[] { 2 }, ( byte[] ) imagePlus.getStack().getPixels( imagePlus.getStackIndex( 1, 1, 2 ) ) ); - assertArrayEquals( new byte[] { 3 }, ( byte[] ) imagePlus.getStack().getPixels( imagePlus.getStackIndex( 2, 1, 1 ) ) ); - } - - @Ignore( "not supporting more than five dimensions yet" ) - @Test - public void test6d() - { - final Img< UnsignedByteType > img = ArrayImgs.unsignedBytes( 2, 2, 2, 2, 2, 2 ); - fill( img ); - final ImgPlus< UnsignedByteType > imgPlus = new ImgPlus<>( img, "title", new AxisType[] { Axes.X, Axes.Y, Axes.Z, Axes.CHANNEL, Axes.TIME, Axes.CHANNEL } ); - final ImagePlus imagePlus = ImgToVirtualStack.wrap( imgPlus, true ); - assertArrayEquals( new byte[] { 2 }, ( byte[] ) imagePlus.getStack().getPixels( imagePlus.getStackIndex( 1, 1, 2 ) ) ); - assertArrayEquals( new byte[] { 3 }, ( byte[] ) imagePlus.getStack().getPixels( imagePlus.getStackIndex( 2, 1, 1 ) ) ); - } - - @Test - public void testColoredAxisOrder() - { - final Img< UnsignedByteType > img = ArrayImgs.unsignedBytes( 1, 1, 2, 3, 4 ); - fill( img ); - final ImgPlus< UnsignedByteType > imgPlus = new ImgPlus<>( img, "title", new AxisType[] { Axes.X, Axes.Y, Axes.TIME, Axes.CHANNEL, Axes.Z } ); - final ImagePlus imagePlus = ImgToVirtualStack.wrap( imgPlus, true ); - assertEquals( 0xff020406, imagePlus.getStack().getProcessor( imagePlus.getStackIndex( 1, 1, 2 ) ).get( 0, 0 ) ); - assertEquals( 0xff07090b, imagePlus.getStack().getProcessor( imagePlus.getStackIndex( 1, 2, 1 ) ).get( 0, 0 ) ); - } - - @Test - public void testBitType() - { - testTypeConversion( ByteProcessor.class, 1, new BitType( true ) ); - } - - @Test - public void testBoolType() - { - testTypeConversion( ByteProcessor.class, 1, new BoolType( true ) ); - } - - @Test - public void testUnsigned2BitType() - { - testTypeConversion( ByteProcessor.class, 3, new Unsigned2BitType( 3 ) ); - } - - @Test - public void testUnsigned4BitTypeType() - { - testTypeConversion( ByteProcessor.class, 15, new Unsigned4BitType( 15 ) ); - } - - @Test - public void testUnsignedByteType() - { - testTypeConversion( ByteProcessor.class, 42f, new UnsignedByteType( 42 ) ); - } - - @Test - public void testUnsigned12BitType() - { - testTypeConversion( ShortProcessor.class, 420, new Unsigned12BitType( 420 ) ); - } - - @Test - public void testUnsignedShortType() - { - testTypeConversion( ShortProcessor.class, 42f, new UnsignedShortType( 42 ) ); - } - - @Test - public void testUnsignedIntType() - { - testTypeConversion( FloatProcessor.class, 42, new UnsignedIntType( 42 ) ); - } - - @Test - public void testUnsignedLongType() - { - testTypeConversion( FloatProcessor.class, 42, new UnsignedLongType( 42 ) ); - } - - @Test - public void testUnsigned128BitType() - { - testTypeConversion( FloatProcessor.class, 1000000, new Unsigned128BitType( 1000000, 0 ) ); - } - - @Test - public void testByteType() - { - testTypeConversion( FloatProcessor.class, -42, new ByteType( ( byte ) -42 ) ); - } - - @Test - public void testShortType() - { - testTypeConversion( FloatProcessor.class, -42, new ShortType( ( short ) -42 ) ); - } - - @Test - public void testIntType() - { - testTypeConversion( FloatProcessor.class, -42, new IntType( -42 ) ); - } - - @Test - public void testLongType() - { - testTypeConversion( FloatProcessor.class, -42, new LongType( -42 ) ); - } - - @Test - public void testFloatType() - { - testTypeConversion( FloatProcessor.class, -42f, new FloatType( -42 ) ); - } - - @Test - public void testDoubleType() - { - testTypeConversion( FloatProcessor.class, -42f, new DoubleType( -42 ) ); - } - - private < T extends RealType< T > > void testTypeConversion( final Class< ? extends ImageProcessor > processorClass, final float expected, final T input ) - { - final RandomAccessibleInterval< T > rai = ConstantUtils.constantRandomAccessibleInterval( input, 2, new FinalInterval( 1, 1 ) ); - final Img< T > image = ImgView.wrap( rai, null ); - final ImgPlus< T > imgPlus = new ImgPlus< T >( image, "title", new AxisType[] { Axes.X, Axes.Y } ); - // process - final ImagePlus imagePlus = ImgToVirtualStack.wrap( imgPlus, false ); - // test - final ImageProcessor processor = imagePlus.getProcessor(); - Assert.assertTrue( processorClass.isInstance( processor ) ); - Assert.assertEquals( expected, processor.getPixelValue( 0, 0 ), 0f ); - } - - private void fill( final RandomAccessibleInterval< ? extends IntegerType > img ) - { - final AtomicInteger i = new AtomicInteger(); - Views.flatIterable( img ).forEach( pixel -> pixel.setInteger( i.incrementAndGet() ) ); - } - - @Test - public void testUnknownAxes() - { - final byte[] array = { 1, 2, 3, 4, 5, 6 }; - final Img< UnsignedByteType > img = ArrayImgs.unsignedBytes( array, 1, 1, 2, 3 ); - final AxisType[] axes = { Axes.unknown(), Axes.unknown(), Axes.TIME, Axes.unknown() }; - final ImagePlus result = ImgToVirtualStack.wrap( new ImgPlus<>( img, "title", axes ), false ); - assertEquals( 3, result.getNChannels() ); - assertEquals( 2, result.getNFrames() ); - } - - @Test - public void testPersistence() - { - // setup - final Img< FloatType > img = ArrayImgs.floats( 1, 1 ); - final ImgPlus< FloatType > imgPlus = new ImgPlus<>( img, "title", new AxisType[] { Axes.X, Axes.Y } ); - final ImagePlus imagePlus = ImgToVirtualStack.wrap( imgPlus, false ); - final float expected = 42; - // process - final ImageProcessor processor = imagePlus.getStack().getProcessor( 1 ); - processor.setf( 0, 0, expected ); - imagePlus.getStack().setPixels( processor.getPixels(), 1 ); // NB: - // required - // to signal - // data - // changed - // test - assertEquals( expected, img.cursor().next().get(), 0.0f ); - } - - @Test - public void testPersistenceBits() - { - // setup - final Img< BitType > img = ArrayImgs.bits( 1, 1 ); - final ImgPlus< BitType > imgPlus = new ImgPlus<>( img, "title", new AxisType[] { Axes.X, Axes.Y } ); - final ImagePlus imagePlus = ImgToVirtualStack.wrapAndScaleBitType( imgPlus ); - // process - final ImageProcessor processor = imagePlus.getStack().getProcessor( 1 ); - processor.setf( 0, 0, 255 ); - imagePlus.getStack().setPixels( processor.getPixels(), 1 ); // NB: - // required - // to signal - // data - // changed - // test - assertEquals( true, img.cursor().next().get() ); - } -} diff --git a/src/test/java/net/imglib2/imagej/display/PlanarImgToVirtualStackTest.java b/src/test/java/net/imglib2/imagej/display/PlanarImgToImagePlusTest.java similarity index 91% rename from src/test/java/net/imglib2/imagej/display/PlanarImgToVirtualStackTest.java rename to src/test/java/net/imglib2/imagej/display/PlanarImgToImagePlusTest.java index 1779c92..5dcd7f4 100644 --- a/src/test/java/net/imglib2/imagej/display/PlanarImgToVirtualStackTest.java +++ b/src/test/java/net/imglib2/imagej/display/PlanarImgToImagePlusTest.java @@ -62,13 +62,13 @@ import ij.ImagePlus; import ij.VirtualStack; -public class PlanarImgToVirtualStackTest +public class PlanarImgToImagePlusTest { @Test public void testStorageArray() { final PlanarImg< UnsignedByteType, ? > img = example(); - final VirtualStack stack = PlanarImgToVirtualStack.wrap( img ); + final VirtualStack stack = PlanarImgToImagePlus.wrap( img ); assertSame( img.getPlane( 1 ).getCurrentStorageArray(), stack.getPixels( 2 ) ); } @@ -76,7 +76,7 @@ public void testStorageArray() public void testPixelValues() { final PlanarImg< UnsignedByteType, ? > img = example(); - final VirtualStack stack = PlanarImgToVirtualStack.wrap( img ); + final VirtualStack stack = PlanarImgToImagePlus.wrap( img ); assertArrayEquals( new byte[] { 1, 2, 3 }, ( byte[] ) stack.getPixels( 1 ) ); assertArrayEquals( new byte[] { 4, 5, 6 }, ( byte[] ) stack.getPixels( 2 ) ); } @@ -89,7 +89,7 @@ public void testImgPlus() final String title = "test image"; final ImgPlus< UnsignedByteType > imgPlus = new ImgPlus<>( img, title, new AxisType[] { Axes.X, Axes.Y, Axes.TIME } ); // process - final ImagePlus imagePlus = PlanarImgToVirtualStack.wrap( imgPlus ); + final ImagePlus imagePlus = PlanarImgToImagePlus.wrap( imgPlus ); // test assertEquals( title, imagePlus.getTitle() ); assertEquals( 3, imagePlus.getWidth() ); @@ -105,7 +105,7 @@ public void testAxisOrder() final PlanarImg< UnsignedByteType, ? > img = new PlanarImgFactory< UnsignedByteType >().create( new long[] { 1, 1, 2, 3, 4 }, new UnsignedByteType() ); fill( img ); final ImgPlus< UnsignedByteType > imgPlus = new ImgPlus<>( img, "title", new AxisType[] { Axes.X, Axes.Y, Axes.TIME, Axes.CHANNEL, Axes.Z } ); - final ImagePlus imagePlus = PlanarImgToVirtualStack.wrap( imgPlus ); + final ImagePlus imagePlus = PlanarImgToImagePlus.wrap( imgPlus ); assertEquals( 2, imagePlus.getStack().getProcessor( imagePlus.getStackIndex( 1, 1, 2 ) ).get( 0, 0 ) ); assertEquals( 7, imagePlus.getStack().getProcessor( imagePlus.getStackIndex( 1, 2, 1 ) ).get( 0, 0 ) ); assertEquals( 3, imagePlus.getStack().getProcessor( imagePlus.getStackIndex( 2, 1, 1 ) ).get( 0, 0 ) ); @@ -130,7 +130,7 @@ public void testPersistence() // setup final PlanarImg< FloatType, FloatArray > img = PlanarImgs.floats( 1, 1 ); final ImgPlus< FloatType > imgPlus = new ImgPlus< FloatType >( img, "title", new AxisType[] { Axes.X, Axes.Y } ); - final ImagePlus imagePlus = PlanarImgToVirtualStack.wrap( imgPlus ); + final ImagePlus imagePlus = PlanarImgToImagePlus.wrap( imgPlus ); final float expected = 42.0f; // process imagePlus.getProcessor().setf( 0, 0, expected ); @@ -142,7 +142,7 @@ public void testPersistence() public void testSetPixels() { // setup final PlanarImg< FloatType, FloatArray > img = PlanarImgs.floats( 1, 1 ); - final ImagePlus imagePlus = PlanarImgToVirtualStack.wrap( new ImgPlus<>( img, "title" ) ); + final ImagePlus imagePlus = PlanarImgToImagePlus.wrap( new ImgPlus<>( img, "title" ) ); final float expected = 42.0f; // process imagePlus.getStack().setPixels( new float[] { expected }, 1 ); @@ -156,7 +156,7 @@ public void testGetProcessorForColorProcessor() { // To achieve this min and max must not be set for ColorProcessor. final PlanarImg< ARGBType, IntArray > argbs = PlanarImgs.argbs( 1, 1, 1 ); argbs.randomAccess().get().set( 0xff010203 ); - final VirtualStack stack = PlanarImgToVirtualStack.wrap( argbs ); + final VirtualStack stack = PlanarImgToImagePlus.wrap( argbs ); assertArrayEquals( new int[] { 0xff010203 }, (int[]) stack.getPixels( 1 ) ); stack.getProcessor( 1 ); assertArrayEquals( new int[] { 0xff010203 }, (int[]) stack.getPixels( 1 ) ); @@ -166,7 +166,7 @@ public void testGetProcessorForColorProcessor() { public void testConvertingBackAndForth() { ImagePlus imagePlus = IJ.createImage( "test", "8-bit ramp", 3, 3, 3 ); ImgPlus< UnsignedByteType > convertedImg = ImagePlusToImgPlus.wrapByteLazily( imagePlus ); - ImagePlus twiceConvertedImagePlus = PlanarImgToVirtualStack.wrap( convertedImg ); + ImagePlus twiceConvertedImagePlus = PlanarImgToImagePlus.wrap( convertedImg ); twiceConvertedImagePlus.getStack().getProcessor( 1 ).set( 0, 0, 5 ); assertEquals( 5, imagePlus.getStack().getProcessor( 1 ).get( 0, 0 ) ); } From 4a702c85044885eca28f088fa9b899b7e89b65ae Mon Sep 17 00:00:00 2001 From: Gabriel Selzer Date: Mon, 3 Mar 2025 10:13:29 -0600 Subject: [PATCH 05/11] Delete ImageJFunctions The only functionality remaining was for showing images - we can always add it back if/when there is demand --- .../net/imglib2/imagej/ImageJFunctions.java | 364 ------------------ 1 file changed, 364 deletions(-) delete mode 100644 src/main/java/net/imglib2/imagej/ImageJFunctions.java diff --git a/src/main/java/net/imglib2/imagej/ImageJFunctions.java b/src/main/java/net/imglib2/imagej/ImageJFunctions.java deleted file mode 100644 index 4751540..0000000 --- a/src/main/java/net/imglib2/imagej/ImageJFunctions.java +++ /dev/null @@ -1,364 +0,0 @@ -/* - * #%L - * ImgLib2: a general-purpose, multidimensional image processing library. - * %% - * Copyright (C) 2009 - 2025 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.imagej; - -import ij.ImagePlus; -import net.imglib2.RandomAccessibleInterval; -import net.imglib2.converter.Converter; -import net.imglib2.converter.Converters; -import net.imglib2.imagej.display.ImageJVirtualStack; -import net.imglib2.imagej.display.ImageJVirtualStackFloat; -import net.imglib2.img.Img; -import net.imglib2.type.numeric.ARGBType; -import net.imglib2.type.numeric.ComplexType; -import net.imglib2.type.numeric.NumericType; -import net.imglib2.type.numeric.RealType; -import net.imglib2.type.numeric.integer.UnsignedByteType; -import net.imglib2.type.numeric.integer.UnsignedShortType; -import net.imglib2.type.numeric.real.FloatType; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.atomic.AtomicInteger; - -import static net.imglib2.imagej.RAIToImagePlus.*; - -/** - * Provides static convenience methods to facilitate interacting with ImageJ - * 1.x. - *

- * When interacting between ImageJ 1.x and ImgLib2, it is desirable to adapt - * data structures instead of copying data. - *

- *

- * For example, when an {@link ImagePlus} is made available by ImageJ 1.x, you - * can pass it to ImgLib2 as an {@link Img} via - * {@code ImageJFunctions.wrap(imp)}. - *

- *

- * Likewise, when an ImgLib2 {@link RandomAccessibleInterval} needs to be passed - * to ImageJ 1.x, it can be wrapped into an {@link ImagePlus} via - * {@code ImageJFunctions.wrap(img, title)}. - * (For details on this see {@link ImageJVirtualStack}). - *

- * - * @author Tobis Pietzsch - * @author Stephan Preibisch - * @author Stephan Saalfeld - */ -public class ImageJFunctions -{ - final static AtomicInteger ai = new AtomicInteger(); - - /** - * Display and return a single channel {@link ImagePlus}, wrapping a - * {@link RandomAccessibleInterval}. The image type of the result - * (ImagePlus.GRAY8, ImagePlus.GRAY16, ImagePlus.GRAY32, ImagePlus.COLOR_256 - * or ImagePlus.COLOR_RGB) is inferred from the generic type of the input - * {@link RandomAccessibleInterval}. - */ - public static < T extends NumericType< T > > ImagePlus show( final RandomAccessibleInterval< T > img, - final ExecutorService service ) - { - return show( img, "Image " + ai.getAndIncrement(), service ); - } - - public static < T extends NumericType< T > > ImagePlus show( final RandomAccessibleInterval< T > img ) - { - return show( img, ( ExecutorService ) null ); - } - - /** - * Displays a complex type as power spectrum, phase spectrum, real values or - * imaginary values depending on the converter - */ - public static < T extends ComplexType< T > > ImagePlus show( final RandomAccessibleInterval< T > img, final Converter< T, FloatType > converter, - final ExecutorService service ) - { - return show( img, converter, "Complex image " + ai.getAndIncrement(), service ); - } - - public static < T extends ComplexType< T > > ImagePlus show( final RandomAccessibleInterval< T > img, final Converter< T, FloatType > converter ) - { - return show( img, converter, "Complex image " + ai.getAndIncrement(), null ); - } - - /** - * Displays a complex type as power spectrum, phase spectrum, real values or - * imaginary values depending on the converter - */ - public static < T extends ComplexType< T > > ImagePlus show( - final RandomAccessibleInterval< T > img, - final Converter< T, FloatType > converter, - final String title, - final ExecutorService service ) - { - final ImageJVirtualStackFloat stack = new ImageJVirtualStackFloat( img, converter, service ); - final ImagePlus imp = new ImagePlus( title, stack ); - imp.show(); - - return imp; - } - - public static < T extends ComplexType< T > > ImagePlus show( - final RandomAccessibleInterval< T > img, - final Converter< T, FloatType > converter, - final String title ) - { - return show( img, converter, title, null ); - } - - public static < T extends NumericType< T > > ImagePlus show( final RandomAccessibleInterval< T > img, final String title, - final ExecutorService service ) - { - final ImagePlus imp = wrap( img, title, service ); - if ( null == imp ) { return null; } - - imp.show(); - imp.getProcessor().resetMinAndMax(); - imp.updateAndRepaintWindow(); - - return imp; - } - - public static < T extends NumericType< T > > ImagePlus show( final RandomAccessibleInterval< T > img, final String title ) - { - return show( img, title, null ); - } - - /** - * Show a {@link RandomAccessibleInterval} as single channel 32-bit float - * {@link ImagePlus} using a custom {@link Converter}. - */ - public static < T > ImagePlus showFloat( - final RandomAccessibleInterval< T > img, - final Converter< T, FloatType > converter, - final String title, - final ExecutorService service ) - { - return showFloat( Converters.convert( img, converter, new FloatType() ), title, service ); - } - - public static < T > ImagePlus showFloat( - final RandomAccessibleInterval< T > img, - final Converter< T, FloatType > converter, - final String title ) - { - return showFloat( img, converter, title, null ); - } - - /** - * Show a {@link RandomAccessibleInterval} of {@link RealType} pixels as - * single channel 32-bit float using a default {@link Converter}. - */ - public static < T extends RealType< T > > ImagePlus showFloat( final RandomAccessibleInterval< T > img, final String title, - final ExecutorService service ) - { - final ImagePlus imp = wrapFloat( img, title, service ); - imp.show(); - imp.getProcessor().resetMinAndMax(); - imp.updateAndRepaintWindow(); - return imp; - } - - public static < T extends RealType< T > > ImagePlus showFloat( final RandomAccessibleInterval< T > img, final String title ) - { - return showFloat( img, title, null ); - } - - /** - * Show a {@link RandomAccessibleInterval} of {@link RealType} pixels as - * single channel 32-bit float using a default {@link Converter}. - */ - public static < T extends RealType< T > > ImagePlus showFloat( final RandomAccessibleInterval< T > img, - final ExecutorService service ) - { - return showFloat( img, "Image " + ai.getAndIncrement(), service ); - } - - public static < T extends RealType< T > > ImagePlus showFloat( final RandomAccessibleInterval< T > img ) - { - return showFloat( img, ( ExecutorService ) null ); - } - - /** - * Show a {@link RandomAccessibleInterval} as 24bit RGB {@link ImagePlus} - * using a custom {@link Converter}. - */ - public static < T > ImagePlus showRGB( final RandomAccessibleInterval< T > img, final Converter< T, ARGBType > converter, final String title, - final ExecutorService service ) - { - final ImagePlus imp = wrapRGB( img, converter, title, service ); - imp.show(); - imp.getProcessor().resetMinAndMax(); - imp.updateAndRepaintWindow(); - - return imp; - } - - public static < T > ImagePlus showRGB( final RandomAccessibleInterval< T > img, final Converter< T, ARGBType > converter, final String title ) - { - return showRGB( img, converter, title, null ); - } - - /** - * Show a {@link RandomAccessibleInterval} as single channel 8-bit unsigned - * integer {@link ImagePlus} using a custom {@link Converter}. - */ - public static < T > ImagePlus showUnsignedByte( - final RandomAccessibleInterval< T > img, - final Converter< T, UnsignedByteType > converter, - final String title, - final ExecutorService service ) - { - return showUnsignedByte( Converters.convert( img, converter, new UnsignedByteType() ), title, service ); - } - - public static < T > ImagePlus showUnsignedByte( - final RandomAccessibleInterval< T > img, - final Converter< T, UnsignedByteType > converter, - final String title ) - { - return showUnsignedByte( img, converter, title, null ); - } - - /** - * Show a {@link RandomAccessibleInterval} of {@link RealType} pixels as - * single channel 8-bit unsigned integer {@link ImagePlus} using a default - * {@link Converter} (clamp values to range [0, 255]). - */ - public static < T extends RealType< T > > ImagePlus showUnsignedByte( - final RandomAccessibleInterval< T > img, - final String title, - final ExecutorService service ) - { - final ImagePlus imp = wrapUnsignedByte( img, title, service ); - imp.show(); - imp.getProcessor().resetMinAndMax(); - imp.updateAndRepaintWindow(); - return imp; - } - - public static < T extends RealType< T > > ImagePlus showUnsignedByte( - final RandomAccessibleInterval< T > img, - final String title ) - { - return showUnsignedByte( img, title, null ); - } - - /** - * Show a {@link RandomAccessibleInterval} of {@link RealType} pixels as - * single channel 8-bit unsigned integer {@link ImagePlus} using a default - * {@link Converter}. - */ - public static < T extends RealType< T > > ImagePlus showUnsignedByte( final RandomAccessibleInterval< T > img, - final ExecutorService service ) - { - return showUnsignedByte( img, "Image " + ai.getAndIncrement(), service ); - } - - public static < T extends RealType< T > > ImagePlus showUnsignedByte( final RandomAccessibleInterval< T > img ) - { - return showUnsignedByte( img, ( ExecutorService ) null ); - } - - /** - * Show a {@link RandomAccessibleInterval} as single channel 16-bit unsigned - * integer {@link ImagePlus} using a custom {@link Converter}. - */ - public static < T > ImagePlus showUnsignedShort( - final RandomAccessibleInterval< T > img, - final Converter< T, UnsignedShortType > converter, - final String title, - final ExecutorService service ) - { - return showUnsignedShort( Converters.convert( img, converter, new UnsignedShortType() ), title, service ); - } - - public static < T > ImagePlus showUnsignedShort( - final RandomAccessibleInterval< T > img, - final Converter< T, UnsignedShortType > converter, - final String title ) - { - return showUnsignedShort( img, converter, title, null ); - } - - /** - * Show a {@link RandomAccessibleInterval} of {@link RealType} pixels as - * single channel 16-bit unsigned integer {@link ImagePlus} using a default - * {@link Converter}. - */ - public static < T extends RealType< T > > ImagePlus showUnsignedShort( - final RandomAccessibleInterval< T > img, - final String title, - final ExecutorService service ) - { - final ImagePlus imp = wrapUnsignedShort( img, title, service ); - imp.show(); - imp.getProcessor().resetMinAndMax(); - imp.updateAndRepaintWindow(); - return imp; - } - - public static < T extends RealType< T > > ImagePlus showUnsignedShort( - final RandomAccessibleInterval< T > img, - final String title ) - { - return showUnsignedShort( img, title, null ); - } - - /** - * Show a {@link RandomAccessibleInterval} of {@link RealType} pixels as - * single channel 16-bit unsigned integer {@link ImagePlus} using a default - * {@link Converter}. - */ - public static < T extends RealType< T > > ImagePlus showUnsignedShort( - final RandomAccessibleInterval< T > img, - final ExecutorService service ) - { - return showUnsignedShort( img, "Image " + ai.getAndIncrement(), service ); - } - - public static < T extends RealType< T > > ImagePlus showUnsignedShort( - final RandomAccessibleInterval< T > img ) - { - return showUnsignedShort( img, ( ExecutorService ) null ); - } - - /* - * public static > ImagePlus copy( final Img img, - * String title ) { } - */ - -} From b4631843e3b01b6838d6a1857e270e4819551e1a Mon Sep 17 00:00:00 2001 From: Gabriel Selzer Date: Mon, 3 Mar 2025 13:10:38 -0600 Subject: [PATCH 06/11] Partition ImagePlus->Img, ImgPlus Only one of these should live here forever so this change will make that easier. --- .../net/imglib2/imagej/ImagePlusToImg.java | 265 +++++++++++++++++ .../imglib2/imagej/ImagePlusToImgPlus.java | 271 ++---------------- .../imagej/imageplus/ImagePlusImgs.java | 49 +--- .../java/net/imglib2/imagej/io/IJLoader.java | 7 +- .../imagej/ImagePlusToImgLib2Benchmark.java | 18 +- .../ImagePlusToImgLib2PerformanceTest.java | 6 +- .../imagej/ImagePlusToImgPlusLazyTest.java | 24 +- .../imagej/ImagePlusToImgPlusTest.java | 16 +- .../display/ImageJFunctionBehavior.java | 18 +- .../display/PlanarImgToImagePlusTest.java | 2 +- .../java/net/imglib2/imagej/io/LoadTest.java | 20 +- 11 files changed, 352 insertions(+), 344 deletions(-) create mode 100644 src/main/java/net/imglib2/imagej/ImagePlusToImg.java diff --git a/src/main/java/net/imglib2/imagej/ImagePlusToImg.java b/src/main/java/net/imglib2/imagej/ImagePlusToImg.java new file mode 100644 index 0000000..ed120c0 --- /dev/null +++ b/src/main/java/net/imglib2/imagej/ImagePlusToImg.java @@ -0,0 +1,265 @@ +/* + * #%L + * ImgLib2: a general-purpose, multidimensional image processing library. + * %% + * Copyright (C) 2009 - 2025 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.imagej; + +import ij.ImagePlus; +import net.imglib2.Cursor; +import net.imglib2.cache.Cache; +import net.imglib2.cache.ref.SoftRefLoaderCache; +import net.imglib2.converter.Converter; +import net.imglib2.imagej.imageplus.*; +import net.imglib2.img.Img; +import net.imglib2.img.basictypeaccess.array.ArrayDataAccess; +import net.imglib2.img.planar.PlanarImg; +import net.imglib2.type.Type; +import net.imglib2.type.numeric.ARGBType; +import net.imglib2.type.numeric.ComplexType; +import net.imglib2.type.numeric.integer.UnsignedByteType; +import net.imglib2.type.numeric.integer.UnsignedIntType; +import net.imglib2.type.numeric.integer.UnsignedShortType; +import net.imglib2.type.numeric.real.FloatType; + +import java.util.AbstractList; +import java.util.concurrent.ExecutionException; +import java.util.function.Function; + +/** + * Provides convenience functions to wrap ImageJ 1.x data structures as ImgLib2 + * ones. + * + * + * @author Stephan Preibisch + * @author Stephan Saalfeld + * @author Matthias Arzt + */ +public class ImagePlusToImg +{ + + public static PlanarImg< ?, ? > wrap( final ImagePlus imp ) + { + switch ( imp.getType() ) + { + case ImagePlus.GRAY8: + return wrapByte( imp ); + case ImagePlus.GRAY16: + return wrapShort( imp ); + case ImagePlus.GRAY32: + return wrapFloat( imp ); + case ImagePlus.COLOR_RGB: + return wrapRGBA( imp ); + default: + throw new RuntimeException( "Only 8, 16, 32-bit and RGB supported!" ); + } + } + + public static PlanarImg< UnsignedByteType, ? > wrapByte(final ImagePlus imp ) + { + if ( imp.getType() != ImagePlus.GRAY8 ) + return null; + + final ByteImagePlus< UnsignedByteType > container = new ByteImagePlus<>( imp ); + + // create a Type that is linked to the container + final UnsignedByteType linkedType = new UnsignedByteType( container ); + + // pass it to the NativeContainer + container.setLinkedType( linkedType ); + + return container; + } + + public static PlanarImg< UnsignedShortType, ? > wrapShort(final ImagePlus imp ) + { + if ( imp.getType() != ImagePlus.GRAY16 ) + return null; + + final ShortImagePlus< UnsignedShortType > container = new ShortImagePlus<>( imp ); + + // create a Type that is linked to the container + final UnsignedShortType linkedType = new UnsignedShortType( container ); + + // pass it to the DirectAccessContainer + container.setLinkedType( linkedType ); + + return container; + } + + public static PlanarImg< UnsignedIntType, ? > wrapInt(final ImagePlus imp ) + { + if( imp.getType() != ImagePlus.COLOR_RGB ) + return null; + + final IntImagePlus< UnsignedIntType > container = new IntImagePlus<>( imp ); + + // create a Type that is linked to the container + final UnsignedIntType linkedType = new UnsignedIntType( container ); + + // pass it to the DirectAccessContainer + container.setLinkedType( linkedType ); + + return container; + } + + public static PlanarImg< ARGBType, ? > wrapRGBA( final ImagePlus imp ) + { + if ( imp.getType() != ImagePlus.COLOR_RGB ) + return null; + + final IntImagePlus< ARGBType > container = new IntImagePlus<>( imp ); + + // create a Type that is linked to the container + final ARGBType linkedType = new ARGBType( container ); + + // pass it to the DirectAccessContainer + container.setLinkedType( linkedType ); + + return container; + } + + public static PlanarImg< FloatType, ? > wrapFloat(final ImagePlus imp ) + { + if ( imp.getType() != ImagePlus.GRAY32 ) + return null; + + final FloatImagePlus< FloatType > container = new FloatImagePlus<>( imp ); + + // create a Type that is linked to the container + final FloatType linkedType = new FloatType( container ); + + // pass it to the DirectAccessContainer + container.setLinkedType( linkedType ); + + return container; + } + + public static PlanarImg< FloatType, ? > convertFloat( final ImagePlus imp ) + { + + switch ( imp.getType() ) + { + case ImagePlus.GRAY8: + return convertToFloat( wrapByte( imp ), new NumberToFloatConverter< UnsignedByteType >() ); + case ImagePlus.GRAY16: + return convertToFloat( wrapShort( imp ), new NumberToFloatConverter< UnsignedShortType >() ); + case ImagePlus.GRAY32: + return wrapFloat( imp ); + case ImagePlus.COLOR_RGB: + return convertToFloat( wrapRGBA( imp ), new ARGBtoFloatConverter() ); + default: + throw new RuntimeException( "Only 8, 16, 32-bit and RGB supported!" ); + } + } + + static private class ARGBtoFloatConverter implements Converter< ARGBType, FloatType > + { + /** Luminance times alpha. */ + @Override + public void convert( final ARGBType input, final FloatType output ) + { + final int v = input.get(); + output.setReal( ( ( v >> 24 ) & 0xff ) * ( ( ( v >> 16 ) & 0xff ) * 0.299 + ( ( v >> 8 ) & 0xff ) * 0.587 + ( v & 0xff ) * 0.144 ) ); + } + } + + static private class NumberToFloatConverter< T extends ComplexType< T > > implements Converter< T, FloatType > + { + @Override + public void convert( final T input, final FloatType output ) + { + output.setReal( input.getRealFloat() ); + } + } + + protected static < T extends Type< T > > PlanarImg< FloatType, ?> convertToFloat( + final Img< T > input, final Converter< T, FloatType > c ) + { + final ImagePlusImg< FloatType, ? > output = new ImagePlusImgFactory<>( new FloatType() ).create( input ); + + final Cursor< T > in = input.cursor(); + final Cursor< FloatType > out = output.cursor(); + + while ( in.hasNext() ) + { + in.fwd(); + out.fwd(); + + c.convert( in.get(), out.get() ); + } + + return output; + } + + private static class ImagePlusLoader< A extends ArrayDataAccess< A >> extends AbstractList< A > + { + private final ImagePlus image; + + private final Cache< Integer, A > cache; + + private final Function< Object, A > arrayFactory; + + public ImagePlusLoader( final ImagePlus image, final Function< Object, A > arrayFactory ) + { + this.arrayFactory = arrayFactory; + this.image = image; + cache = new SoftRefLoaderCache< Integer, A >().withLoader( this::load ); + } + + @Override + public A get( final int key ) + { + try + { + return cache.get( key ); + } + catch ( final ExecutionException e ) + { + throw new RuntimeException( e ); + } + } + + private A load( final Integer key ) + { + return arrayFactory.apply( image.getStack().getPixels( key + 1 ) ); + } + + @Override + public int size() + { + return image.getStackSize(); + } + } + + // +} diff --git a/src/main/java/net/imglib2/imagej/ImagePlusToImgPlus.java b/src/main/java/net/imglib2/imagej/ImagePlusToImgPlus.java index e76a338..1b924a2 100644 --- a/src/main/java/net/imglib2/imagej/ImagePlusToImgPlus.java +++ b/src/main/java/net/imglib2/imagej/ImagePlusToImgPlus.java @@ -34,30 +34,21 @@ package net.imglib2.imagej; +import ij.ImagePlus; import net.imagej.ImgPlus; -import net.imagej.axis.Axes; import net.imagej.axis.CalibratedAxis; -import net.imglib2.Cursor; import net.imglib2.cache.Cache; import net.imglib2.cache.ref.SoftRefLoaderCache; -import net.imglib2.converter.Converter; import net.imglib2.imagej.display.CalibrationUtils; -import net.imglib2.imagej.imageplus.*; -import net.imglib2.img.Img; import net.imglib2.img.basictypeaccess.array.*; import net.imglib2.img.planar.PlanarImg; import net.imglib2.type.NativeType; import net.imglib2.type.NativeTypeFactory; -import net.imglib2.type.Type; import net.imglib2.type.numeric.ARGBType; -import net.imglib2.type.numeric.ComplexType; -import net.imglib2.type.numeric.NumericType; import net.imglib2.type.numeric.integer.UnsignedByteType; import net.imglib2.type.numeric.integer.UnsignedIntType; import net.imglib2.type.numeric.integer.UnsignedShortType; import net.imglib2.type.numeric.real.FloatType; - -import ij.ImagePlus; import net.imglib2.util.Fraction; import java.util.AbstractList; @@ -66,12 +57,9 @@ import java.util.stream.LongStream; /** - * Provides convenience functions to wrap ImageJ 1.x data structures as ImgLib2 - * ones. - *

- * Some functions wrap lazily, using imglib2-caches. These functions load + * Provides convenience functions to wrap ImageJ 1.x data structures as ImageJ ones. + * Many functions wrap lazily, using imglib2-caches. These functions load * planes on-demand, which is especially useful when wrapping a virtual stack. - *

* * * @author Stephan Preibisch @@ -80,185 +68,6 @@ */ public class ImagePlusToImgPlus { - @SuppressWarnings( "unchecked" ) - public static < T extends NumericType< T > & NativeType< T > > ImagePlusImg< T, ? > wrap(final ImagePlus imp ) - { - return ( ImagePlusImg< T, ? > ) wrapLocal( imp ); - } - - @SuppressWarnings( { "rawtypes" } ) - public static ImagePlusImg wrapReal( final ImagePlus imp ) - { - return wrapLocalReal( imp ); - } - - @SuppressWarnings( { "rawtypes" } ) - public static ImagePlusImg wrapNumeric( final ImagePlus imp ) - { - return wrapLocal( imp ); - } - - public static < T extends NumericType< T > & NativeType< T > > ImgPlus< T > wrapImgPlus( final ImagePlus imp ) - { - final Img< T > img = wrap( imp ); - return new ImgPlus<>( img, imp.getTitle(), CalibrationUtils.getNonTrivialAxes( imp ) ); - } - - protected static ImagePlusImg< ?, ? > wrapLocal( final ImagePlus imp ) - { - switch ( imp.getType() ) - { - case ImagePlus.GRAY8: - return wrapByte( imp ); - case ImagePlus.GRAY16: - return wrapShort( imp ); - case ImagePlus.GRAY32: - return wrapFloat( imp ); - case ImagePlus.COLOR_RGB: - return wrapRGBA( imp ); - default: - throw new RuntimeException( "Only 8, 16, 32-bit and RGB supported!" ); - } - } - - protected static ImagePlusImg< ?, ? > wrapLocalReal( final ImagePlus imp ) - { - switch ( imp.getType() ) - { - case ImagePlus.GRAY8: - return wrapByte( imp ); - case ImagePlus.GRAY16: - return wrapShort( imp ); - case ImagePlus.GRAY32: - return wrapFloat( imp ); - default: - throw new RuntimeException( "Only 8, 16 and 32-bit supported!" ); - } - } - - protected static < T extends NumericType< T > & NativeType< T > > void setAxesFromImagePlus( final ImgPlus< T > image, final ImagePlus imp ) - { - - int currentDim = 2; - - if ( imp.getNChannels() > 1 ) - { - image.axis( currentDim ).setType( Axes.CHANNEL ); - currentDim++; - } - - if ( imp.getNSlices() > 1 ) - { - image.axis( currentDim ).setType( Axes.Z ); - currentDim++; - } - - if ( imp.getNFrames() > 1 ) - { - image.axis( currentDim ).setType( Axes.TIME ); - } - - } - - public static ByteImagePlus< UnsignedByteType > wrapByte(final ImagePlus imp ) - { - if ( imp.getType() != ImagePlus.GRAY8 ) - return null; - - final ByteImagePlus< UnsignedByteType > container = new ByteImagePlus<>( imp ); - - // create a Type that is linked to the container - final UnsignedByteType linkedType = new UnsignedByteType( container ); - - // pass it to the NativeContainer - container.setLinkedType( linkedType ); - - return container; - } - - public static ShortImagePlus< UnsignedShortType > wrapShort(final ImagePlus imp ) - { - if ( imp.getType() != ImagePlus.GRAY16 ) - return null; - - final ShortImagePlus< UnsignedShortType > container = new ShortImagePlus<>( imp ); - - // create a Type that is linked to the container - final UnsignedShortType linkedType = new UnsignedShortType( container ); - - // pass it to the DirectAccessContainer - container.setLinkedType( linkedType ); - - return container; - } - - public static IntImagePlus< UnsignedIntType > wrapInt(final ImagePlus imp ) - { - if( imp.getType() != ImagePlus.COLOR_RGB ) - return null; - - final IntImagePlus< UnsignedIntType > container = new IntImagePlus<>( imp ); - - // create a Type that is linked to the container - final UnsignedIntType linkedType = new UnsignedIntType( container ); - - // pass it to the DirectAccessContainer - container.setLinkedType( linkedType ); - - return container; - } - - public static IntImagePlus< ARGBType > wrapRGBA( final ImagePlus imp ) - { - if ( imp.getType() != ImagePlus.COLOR_RGB ) - return null; - - final IntImagePlus< ARGBType > container = new IntImagePlus<>( imp ); - - // create a Type that is linked to the container - final ARGBType linkedType = new ARGBType( container ); - - // pass it to the DirectAccessContainer - container.setLinkedType( linkedType ); - - return container; - } - - public static FloatImagePlus< FloatType > wrapFloat(final ImagePlus imp ) - { - if ( imp.getType() != ImagePlus.GRAY32 ) - return null; - - final FloatImagePlus< FloatType > container = new FloatImagePlus<>( imp ); - - // create a Type that is linked to the container - final FloatType linkedType = new FloatType( container ); - - // pass it to the DirectAccessContainer - container.setLinkedType( linkedType ); - - return container; - } - - public static Img< FloatType > convertFloat( final ImagePlus imp ) - { - - switch ( imp.getType() ) - { - case ImagePlus.GRAY8: - return convertToFloat( wrapByte( imp ), new NumberToFloatConverter< UnsignedByteType >() ); - case ImagePlus.GRAY16: - return convertToFloat( wrapShort( imp ), new NumberToFloatConverter< UnsignedShortType >() ); - case ImagePlus.GRAY32: - return wrapFloat( imp ); - case ImagePlus.COLOR_RGB: - return convertToFloat( wrapRGBA( imp ), new ARGBtoFloatConverter() ); - default: - throw new RuntimeException( "Only 8, 16, 32-bit and RGB supported!" ); - } - } - - // -- Lazy conversions -- // /** * Wraps a 8 bit {@link ImagePlus}, into an {@link ImgPlus}, that is backed @@ -266,9 +75,9 @@ public static Img< FloatType > convertFloat( final ImagePlus imp ) * needed, and caches them. The axes of the returned image are set according * to the calibration of the given image. */ - public static ImgPlus< UnsignedByteType > wrapByteLazily(final ImagePlus image ) + public static ImgPlus< UnsignedByteType > wrapByte(final ImagePlus image ) { - return internWrapLazily( image, ImagePlus.GRAY8, new UnsignedByteType(), array -> new ByteArray( ( byte[] ) array ) ); + return internWrap( image, ImagePlus.GRAY8, new UnsignedByteType(), array -> new ByteArray( ( byte[] ) array ) ); } /** @@ -277,9 +86,9 @@ public static ImgPlus< UnsignedByteType > wrapByteLazily(final ImagePlus image ) * needed, and caches them. The axes of the returned image are set according * to the calibration of the given image. */ - public static ImgPlus< UnsignedShortType > wrapShortLazily(final ImagePlus image ) + public static ImgPlus< UnsignedShortType > wrapShort(final ImagePlus image ) { - return internWrapLazily( image, ImagePlus.GRAY16, new UnsignedShortType(), array -> new ShortArray( ( short[] ) array ) ); + return internWrap( image, ImagePlus.GRAY16, new UnsignedShortType(), array -> new ShortArray( ( short[] ) array ) ); } /** @@ -288,9 +97,9 @@ public static ImgPlus< UnsignedShortType > wrapShortLazily(final ImagePlus image * needed, and caches them. The axes of the returned image are set according * to the calibration of the given image. */ - public static ImgPlus< FloatType > wrapFloatLazily(final ImagePlus image ) + public static ImgPlus< FloatType > wrapFloat(final ImagePlus image ) { - return internWrapLazily( image, ImagePlus.GRAY32, new FloatType(), array -> new FloatArray( ( float[] ) array ) ); + return internWrap( image, ImagePlus.GRAY32, new FloatType(), array -> new FloatArray( ( float[] ) array ) ); } /** @@ -299,9 +108,9 @@ public static ImgPlus< FloatType > wrapFloatLazily(final ImagePlus image ) * needed, and caches them. The axes of the returned image are set according * to the calibration of the given image. */ - public static ImgPlus< UnsignedIntType > wrapIntLazily(final ImagePlus image ) + public static ImgPlus< UnsignedIntType > wrapInt(final ImagePlus image ) { - return internWrapLazily( image, ImagePlus.COLOR_RGB, new UnsignedIntType(), array -> new IntArray( ( int[] ) array ) ); + return internWrap( image, ImagePlus.COLOR_RGB, new UnsignedIntType(), array -> new IntArray( ( int[] ) array ) ); } /** @@ -310,9 +119,9 @@ public static ImgPlus< UnsignedIntType > wrapIntLazily(final ImagePlus image ) * needed, and caches them. The axes of the returned image are set according * to the calibration of the given image. */ - public static ImgPlus< ARGBType > wrapRGBALazily(final ImagePlus image ) + public static ImgPlus< ARGBType > wrapRGBA(final ImagePlus image ) { - return internWrapLazily( image, ImagePlus.COLOR_RGB, new ARGBType(), array -> new IntArray( ( int[] ) array ) ); + return internWrap( image, ImagePlus.COLOR_RGB, new ARGBType(), array -> new IntArray( ( int[] ) array ) ); } /** @@ -322,23 +131,23 @@ public static ImgPlus< ARGBType > wrapRGBALazily(final ImagePlus image ) * of the ImagePlus. The axes of the returned image are set according to the * calibration of the given image. */ - public static ImgPlus< ? > wrapLazily(final ImagePlus image ) + public static ImgPlus< ? > wrap(final ImagePlus image ) { switch ( image.getType() ) { case ImagePlus.GRAY8: - return wrapByteLazily( image ); + return wrapByte( image ); case ImagePlus.GRAY16: - return wrapShortLazily( image ); + return wrapShort( image ); case ImagePlus.GRAY32: - return wrapFloatLazily( image ); + return wrapFloat( image ); case ImagePlus.COLOR_RGB: - return wrapRGBALazily( image ); + return wrapRGBA( image ); } throw new RuntimeException( "Only 8, 16, 32-bit and RGB supported!" ); } - private static < T extends NativeType< T >, A extends ArrayDataAccess< A > > ImgPlus< T > internWrapLazily(final ImagePlus image, final int expectedType, final T type, final Function< Object, A > createArrayAccess ) + private static < T extends NativeType< T >, A extends ArrayDataAccess< A > > ImgPlus< T > internWrap(final ImagePlus image, final int expectedType, final T type, final Function< Object, A > createArrayAccess ) { if ( image.getType() != expectedType ) throw new IllegalArgumentException(); @@ -347,8 +156,7 @@ private static < T extends NativeType< T >, A extends ArrayDataAccess< A > > Img final PlanarImg< T, A > cached = new PlanarImg<>( loader, dimensions, new Fraction() ); cached.setLinkedType( ( (NativeTypeFactory< T, A >) type.getNativeTypeFactory() ).createLinkedType( cached ) ); final CalibratedAxis[] axes = CalibrationUtils.getNonTrivialAxes( image ); - final ImgPlus< T > wrap = new ImgPlus<>( cached, image.getTitle(), axes ); - return wrap; + return new ImgPlus<>( cached, image.getTitle(), axes ); } private static long[] getNonTrivialDimensions(final ImagePlus image ) @@ -358,45 +166,6 @@ private static long[] getNonTrivialDimensions(final ImagePlus image ) return LongStream.concat( xy, czt.filter( x -> x > 1 ) ).toArray(); } - static private class ARGBtoFloatConverter implements Converter< ARGBType, FloatType > - { - /** Luminance times alpha. */ - @Override - public void convert( final ARGBType input, final FloatType output ) - { - final int v = input.get(); - output.setReal( ( ( v >> 24 ) & 0xff ) * ( ( ( v >> 16 ) & 0xff ) * 0.299 + ( ( v >> 8 ) & 0xff ) * 0.587 + ( v & 0xff ) * 0.144 ) ); - } - } - - static private class NumberToFloatConverter< T extends ComplexType< T > > implements Converter< T, FloatType > - { - @Override - public void convert( final T input, final FloatType output ) - { - output.setReal( input.getRealFloat() ); - } - } - - protected static < T extends Type< T > > Img< FloatType > convertToFloat( - final Img< T > input, final Converter< T, FloatType > c ) - { - final ImagePlusImg< FloatType, ? > output = new ImagePlusImgFactory<>( new FloatType() ).create( input ); - - final Cursor< T > in = input.cursor(); - final Cursor< FloatType > out = output.cursor(); - - while ( in.hasNext() ) - { - in.fwd(); - out.fwd(); - - c.convert( in.get(), out.get() ); - } - - return output; - } - private static class ImagePlusLoader< A extends ArrayDataAccess< A >> extends AbstractList< A > { private final ImagePlus image; diff --git a/src/main/java/net/imglib2/imagej/imageplus/ImagePlusImgs.java b/src/main/java/net/imglib2/imagej/imageplus/ImagePlusImgs.java index 5e765cf..4e1afa6 100644 --- a/src/main/java/net/imglib2/imagej/imageplus/ImagePlusImgs.java +++ b/src/main/java/net/imglib2/imagej/imageplus/ImagePlusImgs.java @@ -34,27 +34,15 @@ package net.imglib2.imagej.imageplus; -import net.imglib2.imagej.ImagePlusToImgPlus; -import net.imglib2.img.basictypeaccess.array.DoubleArray; -import net.imglib2.type.NativeType; -import net.imglib2.type.Type; -import net.imglib2.type.numeric.ARGBType; -import net.imglib2.type.numeric.NumericType; -import net.imglib2.type.numeric.complex.ComplexDoubleType; -import net.imglib2.type.numeric.complex.ComplexFloatType; -import net.imglib2.type.numeric.integer.ByteType; -import net.imglib2.type.numeric.integer.IntType; -import net.imglib2.type.numeric.integer.ShortType; -import net.imglib2.type.numeric.integer.UnsignedByteType; -import net.imglib2.type.numeric.integer.UnsignedIntType; -import net.imglib2.type.numeric.integer.UnsignedShortType; -import net.imglib2.type.numeric.real.FloatType; - -import ij.ImagePlus; import ij.process.ByteProcessor; import ij.process.ColorProcessor; import ij.process.FloatProcessor; import ij.process.ShortProcessor; +import net.imglib2.type.Type; +import net.imglib2.type.numeric.ARGBType; +import net.imglib2.type.numeric.complex.ComplexFloatType; +import net.imglib2.type.numeric.integer.*; +import net.imglib2.type.numeric.real.FloatType; /** * Convenience factory methods for creation of {@link ImagePlusImg} instances @@ -84,7 +72,7 @@ private ImagePlusImgs() *

*/ @SuppressWarnings( "unchecked" ) - final static public ByteImagePlus< UnsignedByteType > unsignedBytes( final long... dim ) + static public ByteImagePlus< UnsignedByteType > unsignedBytes(final long... dim) { return ( ByteImagePlus< UnsignedByteType > ) new ImagePlusImgFactory<>( new UnsignedByteType() ).create( dim ); } @@ -97,7 +85,7 @@ final static public ByteImagePlus< UnsignedByteType > unsignedBytes( final long. *

*/ @SuppressWarnings( "unchecked" ) - final static public ByteImagePlus< ByteType > bytes( final long... dim ) + static public ByteImagePlus< ByteType > bytes(final long... dim) { return ( ByteImagePlus< ByteType > ) new ImagePlusImgFactory<>( new ByteType() ).create( dim ); } @@ -111,7 +99,7 @@ final static public ByteImagePlus< ByteType > bytes( final long... dim ) *

*/ @SuppressWarnings( "unchecked" ) - final static public ShortImagePlus< UnsignedShortType > unsignedShorts( final long... dim ) + static public ShortImagePlus< UnsignedShortType > unsignedShorts(final long... dim) { return ( ShortImagePlus< UnsignedShortType > ) new ImagePlusImgFactory<>( new UnsignedShortType() ).create( dim ); } @@ -124,7 +112,7 @@ final static public ShortImagePlus< UnsignedShortType > unsignedShorts( final lo *

*/ @SuppressWarnings( "unchecked" ) - final static public ShortImagePlus< ShortType > shorts( final long... dim ) + static public ShortImagePlus< ShortType > shorts(final long... dim) { return ( ShortImagePlus< ShortType > ) new ImagePlusImgFactory<>( new ShortType() ).create( dim ); } @@ -139,7 +127,7 @@ final static public ShortImagePlus< ShortType > shorts( final long... dim ) *

*/ @SuppressWarnings( "unchecked" ) - final static public IntImagePlus< UnsignedIntType > unsignedInts( final long... dim ) + static public IntImagePlus< UnsignedIntType > unsignedInts(final long... dim) { return ( IntImagePlus< UnsignedIntType > ) new ImagePlusImgFactory<>( new UnsignedIntType() ).create( dim ); } @@ -154,7 +142,7 @@ final static public IntImagePlus< UnsignedIntType > unsignedInts( final long... *

*/ @SuppressWarnings( "unchecked" ) - final static public IntImagePlus< IntType > ints( final long... dim ) + static public IntImagePlus< IntType > ints(final long... dim) { return ( IntImagePlus< IntType > ) new ImagePlusImgFactory<>( new IntType() ).create( dim ); } @@ -167,7 +155,7 @@ final static public IntImagePlus< IntType > ints( final long... dim ) *

*/ @SuppressWarnings( "unchecked" ) - final static public FloatImagePlus< FloatType > floats( final long... dim ) + static public FloatImagePlus< FloatType > floats(final long... dim) { return ( FloatImagePlus< FloatType > ) new ImagePlusImgFactory<>( new FloatType() ).create( dim ); } @@ -180,7 +168,7 @@ final static public FloatImagePlus< FloatType > floats( final long... dim ) *

*/ @SuppressWarnings( "unchecked" ) - final static public IntImagePlus< ARGBType > argbs( final long... dim ) + static public IntImagePlus< ARGBType > argbs(final long... dim) { return ( IntImagePlus< ARGBType > ) new ImagePlusImgFactory<>( new ARGBType() ).create( dim ); } @@ -196,17 +184,8 @@ final static public IntImagePlus< ARGBType > argbs( final long... dim ) *

*/ @SuppressWarnings( "unchecked" ) - final static public FloatImagePlus< ComplexFloatType > complexFloats( final long... dim ) + static public FloatImagePlus< ComplexFloatType > complexFloats( final long... dim ) { return ( FloatImagePlus< ComplexFloatType > ) new ImagePlusImgFactory<>( new ComplexFloatType() ).create( dim ); } - - /** - * Create an {@link ImagePlusImg}{@code <}{@link ComplexDoubleType}, - * {@link DoubleArray}{@code >}. - */ - final static public < T extends NumericType< T > & NativeType< T > > ImagePlusImg< T, ? > from( final ImagePlus imp ) - { - return ImagePlusToImgPlus.< T >wrap( imp ); - } } diff --git a/src/main/java/net/imglib2/imagej/io/IJLoader.java b/src/main/java/net/imglib2/imagej/io/IJLoader.java index 2e3db3c..be6d546 100644 --- a/src/main/java/net/imglib2/imagej/io/IJLoader.java +++ b/src/main/java/net/imglib2/imagej/io/IJLoader.java @@ -35,7 +35,7 @@ import ij.IJ; import net.imglib2.cache.CacheLoader; -import net.imglib2.imagej.ImagePlusToImgPlus; +import net.imglib2.imagej.ImagePlusToImg; import net.imglib2.img.Img; import net.imglib2.img.planar.PlanarImg; import net.imglib2.type.NativeType; @@ -45,7 +45,7 @@ * An ImageJ-powered implementation of a disk-based {@link CacheLoader}: * the file system is the cache, and requests to load image file paths * are executed using ImageJ's {@link IJ#openImage(java.lang.String)}, - * and wrapped as {@link PlanarImg} via the {@link net.imglib2.imagej.ImagePlusToImgPlus#wrap(ij.ImagePlus)}. + * and wrapped as {@link PlanarImg} via the {@link net.imglib2.imagej.ImagePlusToImg#wrap(ij.ImagePlus)}. * * @author Albert Cardona * @@ -54,8 +54,9 @@ public class IJLoader< T extends NumericType< T > & NativeType< T > > implements CacheLoader< String, Img< T > > { @Override + @SuppressWarnings("unchecked") public Img< T > get( final String path ) { - return ImagePlusToImgPlus.wrap( IJ.openImage( path ) ); + return (Img) ImagePlusToImg.wrap( IJ.openImage( path ) ); } } diff --git a/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2Benchmark.java b/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2Benchmark.java index b9a68e6..b80eac6 100644 --- a/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2Benchmark.java +++ b/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2Benchmark.java @@ -35,7 +35,7 @@ import net.imagej.ImgPlus; import net.imglib2.RandomAccessibleInterval; -import net.imglib2.imagej.imageplus.ByteImagePlus; +import net.imglib2.img.Img; import net.imglib2.type.numeric.integer.UnsignedByteType; import net.imglib2.view.Views; @@ -62,41 +62,41 @@ public class ImagePlusToImgLib2Benchmark @Benchmark public void wrapSmall() { - net.imglib2.imagej.ImagePlusToImgPlus.wrapLazily( small ); + net.imglib2.imagej.ImagePlusToImgPlus.wrap( small ); } @Benchmark public void wrapDeep() { - net.imglib2.imagej.ImagePlusToImgPlus.wrapLazily( deep ); + net.imglib2.imagej.ImagePlusToImgPlus.wrap( deep ); } @Benchmark public void wrapWide() { - ImagePlusToImgPlus.wrapLazily( wide ); + ImagePlusToImgPlus.wrap( wide ); } @Benchmark public void wrapSmallOld() { - net.imglib2.imagej.ImagePlusToImgPlus.wrap( small ); + net.imglib2.imagej.ImagePlusToImg.wrap( small ); } @Benchmark public void wrapDeepOld() { - net.imglib2.imagej.ImagePlusToImgPlus.wrap( deep ); + net.imglib2.imagej.ImagePlusToImg.wrap( deep ); } @Benchmark public void wrapWideOld() { - net.imglib2.imagej.ImagePlusToImgPlus.wrap( wide ); + net.imglib2.imagej.ImagePlusToImg.wrap( wide ); } - private final ImgPlus< UnsignedByteType > wrapped = net.imglib2.imagej.ImagePlusToImgPlus.wrapByteLazily( imageForIteration ); - private final ByteImagePlus< UnsignedByteType > wrappedOld = net.imglib2.imagej.ImagePlusToImgPlus.wrapByte( imageForIteration ); + private final ImgPlus< UnsignedByteType > wrapped = net.imglib2.imagej.ImagePlusToImgPlus.wrapByte( imageForIteration ); + private final Img< UnsignedByteType > wrappedOld = net.imglib2.imagej.ImagePlusToImg.wrapByte( imageForIteration ); @Benchmark public void iterateWrapped() diff --git a/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2PerformanceTest.java b/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2PerformanceTest.java index d5738f2..28956a4 100644 --- a/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2PerformanceTest.java +++ b/src/test/java/net/imglib2/imagej/ImagePlusToImgLib2PerformanceTest.java @@ -57,7 +57,7 @@ public void testIterateVirtualStack() { final AtomicInteger counter = new AtomicInteger(); final ImagePlus image = countingImagePlus( counter ); - final Img< ? extends RealType< ? > > img = net.imglib2.imagej.ImagePlusToImgPlus.wrapByteLazily( image ); + final Img< ? extends RealType< ? > > img = net.imglib2.imagej.ImagePlusToImgPlus.wrapByte( image ); runFlatIteration( img ); assertTrue( counter.get() < 120 ); // don't call getProcessor too often } @@ -67,7 +67,7 @@ public void testIteratePermutedVirtualStack() { final AtomicInteger counter = new AtomicInteger(); final ImagePlus image = countingImagePlus( counter ); - final Img< ? extends RealType< ? > > img = ImagePlusToImgPlus.wrapByteLazily( image ); + final Img< ? extends RealType< ? > > img = ImagePlusToImgPlus.wrapByte( image ); runFlatIteration( Views.permute( img, 0, 2 ) ); assertTrue( counter.get() < 120 ); // don't call getProcessor too often } @@ -77,7 +77,7 @@ public void testIterateImagePlusAdapter() { final AtomicInteger counter = new AtomicInteger(); final ImagePlus image = countingImagePlus( counter ); - final Img< ? extends RealType< ? > > img = net.imglib2.imagej.ImagePlusToImgPlus.wrapByte( image ); + final Img< ? extends RealType< ? > > img = net.imglib2.imagej.ImagePlusToImg.wrapByte( image ); runFlatIteration( Views.permute( img, 0, 2 ) ); assertTrue( counter.get() < 120 ); // don't call getProcessor too often } diff --git a/src/test/java/net/imglib2/imagej/ImagePlusToImgPlusLazyTest.java b/src/test/java/net/imglib2/imagej/ImagePlusToImgPlusLazyTest.java index 82a291f..c10f391 100644 --- a/src/test/java/net/imglib2/imagej/ImagePlusToImgPlusLazyTest.java +++ b/src/test/java/net/imglib2/imagej/ImagePlusToImgPlusLazyTest.java @@ -61,8 +61,8 @@ public class ImagePlusToImgPlusLazyTest public void testUnsignedByte() { final ImagePlus image = randomImagePlus( 123, new UnsignedByteType(), DIMENSIONS ); - final Img< UnsignedByteType > actual = ImagePlusToImgPlus.wrapByteLazily( image ); - final Img< UnsignedByteType > expected = ImagePlusToImgPlus.wrapByte( image ); + final Img< UnsignedByteType > actual = ImagePlusToImgPlus.wrapByte( image ); + final Img< UnsignedByteType > expected = ImagePlusToImg.wrapByte( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -70,8 +70,8 @@ public void testUnsignedByte() public void testUnsignedShort() { final ImagePlus image = randomImagePlus( 234, new UnsignedShortType(), DIMENSIONS ); - final Img< UnsignedShortType > actual = ImagePlusToImgPlus.wrapShortLazily( image ); - final Img< UnsignedShortType > expected = ImagePlusToImgPlus.wrapShort( image ); + final Img< UnsignedShortType > actual = ImagePlusToImgPlus.wrapShort( image ); + final Img< UnsignedShortType > expected = ImagePlusToImg.wrapShort( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -79,8 +79,8 @@ public void testUnsignedShort() public void testRGB() { final ImagePlus image = randomImagePlus( 345, new ARGBType(), DIMENSIONS ); - final Img< ARGBType > actual = ImagePlusToImgPlus.wrapRGBALazily( image ); - final Img< ARGBType > expected = ImagePlusToImgPlus.wrapRGBA( image ); + final Img< ARGBType > actual = ImagePlusToImgPlus.wrapRGBA( image ); + final Img< ARGBType > expected = ImagePlusToImg.wrapRGBA( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -88,8 +88,8 @@ public void testRGB() public void testFloat() { final ImagePlus image = randomImagePlus( 456, new FloatType(), DIMENSIONS ); - final Img< FloatType > actual = ImagePlusToImgPlus.wrapFloatLazily( image ); - final Img< FloatType > expected = ImagePlusToImgPlus.wrapFloat( image ); + final Img< FloatType > actual = ImagePlusToImgPlus.wrapFloat( image ); + final Img< FloatType > expected = ImagePlusToImg.wrapFloat( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -97,8 +97,8 @@ public void testFloat() public void testLowerNumDimensions() { final ImagePlus image = randomImagePlus( 567, new UnsignedByteType(), 2, 3, 6 ); - final Img< UnsignedByteType > actual = ImagePlusToImgPlus.wrapByteLazily( image ); - final Img< UnsignedByteType > expected = ImagePlusToImgPlus.wrapByte( image ); + final Img< UnsignedByteType > actual = ImagePlusToImgPlus.wrapByte( image ); + final Img< UnsignedByteType > expected = ImagePlusToImg.wrapByte( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } @@ -106,8 +106,8 @@ public void testLowerNumDimensions() public void testSingletonDimensions() { final ImagePlus image = randomImagePlus( 678, new UnsignedByteType(), 2, 1, 1, 6 ); - final Img< UnsignedByteType > actual = ImagePlusToImgPlus.wrapByteLazily( image ); - final Img< UnsignedByteType > expected = ImagePlusToImgPlus.wrapByte( image ); + final Img< UnsignedByteType > actual = ImagePlusToImgPlus.wrapByte( image ); + final Img< UnsignedByteType > expected = ImagePlusToImg.wrapByte( image ); ImgLib2Assert.assertImageEquals( expected, actual ); } diff --git a/src/test/java/net/imglib2/imagej/ImagePlusToImgPlusTest.java b/src/test/java/net/imglib2/imagej/ImagePlusToImgPlusTest.java index 5816abe..c58f6f8 100644 --- a/src/test/java/net/imglib2/imagej/ImagePlusToImgPlusTest.java +++ b/src/test/java/net/imglib2/imagej/ImagePlusToImgPlusTest.java @@ -34,18 +34,16 @@ package net.imglib2.imagej; -import static org.junit.Assert.assertEquals; - +import ij.ImagePlus; +import ij.gui.NewImage; +import ij.measure.Calibration; import net.imagej.ImgPlus; import net.imagej.axis.Axes; import net.imglib2.type.NativeType; import net.imglib2.type.numeric.NumericType; - import org.junit.Test; -import ij.ImagePlus; -import ij.gui.NewImage; -import ij.measure.Calibration; +import static org.junit.Assert.assertEquals; public class ImagePlusToImgPlusTest< T extends NumericType< T > & NativeType< T > > { @@ -88,7 +86,7 @@ public void testDimensionality() private void testDimensionality( final int[] dim, final float[] calibration ) { final ImagePlus imp = createCalibratedImagePlus( dim, calibration ); - final ImgPlus< T > img = ImagePlusToImgPlus.wrapImgPlus( imp ); + final ImgPlus< ? > img = ImagePlusToImgPlus.wrap( imp ); // Print stuff // System.out.println( "got: " + img.getName() ); // for ( int d = 0; d < img.numDimensions(); d++ ) @@ -136,7 +134,7 @@ private int getExpectedNumDimensions( final int[] dim ) return expectedNumDimensions; } - private void checkDimensionality( final int[] dim, final ImgPlus< T > img ) + private void checkDimensionality( final int[] dim, final ImgPlus< ? > img ) { int skipDim = 0; for ( int d = 0; d < dim.length; d++ ) @@ -153,7 +151,7 @@ private void checkDimensionality( final int[] dim, final ImgPlus< T > img ) } } - private void checkCalibration( final int[] dim, final float[] calibration, final ImgPlus< T > img ) + private void checkCalibration( final int[] dim, final float[] calibration, final ImgPlus< ? > img ) { int skipDim = 0; for ( int d = 0; d < calibration.length; d++ ) diff --git a/src/test/java/net/imglib2/imagej/display/ImageJFunctionBehavior.java b/src/test/java/net/imglib2/imagej/display/ImageJFunctionBehavior.java index 4dc42e6..758023e 100644 --- a/src/test/java/net/imglib2/imagej/display/ImageJFunctionBehavior.java +++ b/src/test/java/net/imglib2/imagej/display/ImageJFunctionBehavior.java @@ -36,7 +36,7 @@ import ij.IJ; import ij.ImagePlus; -import net.imglib2.imagej.ImagePlusToImgPlus; +import net.imglib2.imagej.ImagePlusToImg; import net.imglib2.imagej.RAIToImagePlus; import net.imglib2.img.Img; import net.imglib2.type.numeric.ARGBType; @@ -69,36 +69,36 @@ static public final void main( final String[] arg ) // 1. Test ImagePlus -> Img, specific wrappers IJ.run( imp, "8-bit", "" ); - final Img< UnsignedByteType > imgb = ImagePlusToImgPlus.wrapByte( imp ); + final Img< UnsignedByteType > imgb = ImagePlusToImg.wrapByte( imp ); print( imgb ); IJ.run( imp, "16-bit", "" ); - final Img< UnsignedShortType > imgs = ImagePlusToImgPlus.wrapShort( imp ); + final Img< UnsignedShortType > imgs = ImagePlusToImg.wrapShort( imp ); print( imgs ); IJ.run( imp, "32-bit", "" ); - final Img< FloatType > imgf = ImagePlusToImgPlus.wrapFloat( imp ); + final Img< FloatType > imgf = ImagePlusToImg.wrapFloat( imp ); print( imgf ); IJ.run( imp, "RGB Color", "" ); - final Img< ARGBType > imgRGB = ImagePlusToImgPlus.wrapRGBA( imp ); + final Img< ARGBType > imgRGB = ImagePlusToImg.wrapRGBA( imp ); print( imgRGB ); // 2. Test ImagePlus -> Img, generic wrapper IJ.run( imp, "8-bit", "" ); - final Img< UnsignedByteType > g_imgb = ImagePlusToImgPlus.wrap( imp ); + final Img< UnsignedByteType > g_imgb = (Img) ImagePlusToImg.wrap( imp ); print( g_imgb ); IJ.run( imp, "16-bit", "" ); - final Img< UnsignedShortType > g_imgs = ImagePlusToImgPlus.wrap( imp ); + final Img< UnsignedShortType > g_imgs = (Img) ImagePlusToImg.wrap( imp ); print( g_imgs ); IJ.run( imp, "32-bit", "" ); - final Img< FloatType > g_imgf = ImagePlusToImgPlus.wrap( imp ); + final Img< FloatType > g_imgf = (Img) ImagePlusToImg.wrap( imp ); print( g_imgf ); IJ.run( imp, "RGB Color", "" ); - final Img< ARGBType > g_imgRGB = ImagePlusToImgPlus.wrap( imp ); + final Img< ARGBType > g_imgRGB = (Img) ImagePlusToImg.wrap( imp ); print( g_imgRGB ); // 3. Test Img -> ImagePlus, specific wrappers diff --git a/src/test/java/net/imglib2/imagej/display/PlanarImgToImagePlusTest.java b/src/test/java/net/imglib2/imagej/display/PlanarImgToImagePlusTest.java index 5dcd7f4..2acbe9c 100644 --- a/src/test/java/net/imglib2/imagej/display/PlanarImgToImagePlusTest.java +++ b/src/test/java/net/imglib2/imagej/display/PlanarImgToImagePlusTest.java @@ -165,7 +165,7 @@ public void testGetProcessorForColorProcessor() { @Test public void testConvertingBackAndForth() { ImagePlus imagePlus = IJ.createImage( "test", "8-bit ramp", 3, 3, 3 ); - ImgPlus< UnsignedByteType > convertedImg = ImagePlusToImgPlus.wrapByteLazily( imagePlus ); + ImgPlus< UnsignedByteType > convertedImg = ImagePlusToImgPlus.wrapByte( imagePlus ); ImagePlus twiceConvertedImagePlus = PlanarImgToImagePlus.wrap( convertedImg ); twiceConvertedImagePlus.getStack().getProcessor( 1 ).set( 0, 0, 5 ); assertEquals( 5, imagePlus.getStack().getProcessor( 1 ).get( 0, 0 ) ); diff --git a/src/test/java/net/imglib2/imagej/io/LoadTest.java b/src/test/java/net/imglib2/imagej/io/LoadTest.java index 691054a..0895d19 100644 --- a/src/test/java/net/imglib2/imagej/io/LoadTest.java +++ b/src/test/java/net/imglib2/imagej/io/LoadTest.java @@ -33,20 +33,13 @@ */ package net.imglib2.imagej.io; -import java.util.Arrays; -import java.util.stream.Collectors; - -import ij.CompositeImage; -import ij.IJ; -import ij.ImageJ; -import ij.ImagePlus; -import ij.VirtualStack; +import ij.*; import ij.process.ImageProcessor; import ij.process.ShortProcessor; import net.imglib2.Cursor; import net.imglib2.RandomAccessibleInterval; import net.imglib2.cache.img.CachedCellImg; -import net.imglib2.imagej.ImagePlusToImgPlus; +import net.imglib2.imagej.ImagePlusToImg; import net.imglib2.img.array.ArrayImg; import net.imglib2.img.array.ArrayImgs; import net.imglib2.img.basictypeaccess.array.ArrayDataAccess; @@ -54,6 +47,9 @@ import net.imglib2.view.IntervalView; import net.imglib2.view.Views; +import java.util.Arrays; +import java.util.stream.Collectors; + public class LoadTest { final String[] paths = new String[] @@ -123,12 +119,12 @@ public void testStack() public void testStackDefault() { - final RandomAccessibleInterval< ? > img = Views.stack( Arrays.stream( paths ) + final RandomAccessibleInterval< UnsignedShortType > img = Views.stack( Arrays.stream( paths ) .map( IJ::openImage ) - .map( ImagePlusToImgPlus::wrap ) + .map(ImagePlusToImg::wrapShort) .collect( Collectors.toList() ) ); - show( ( RandomAccessibleInterval< UnsignedShortType > )img, "stack", 1, ( int )img.dimension( 2 ), ( int )img.dimension( 3 ) ); + show(img, "stack", 1, ( int )img.dimension( 2 ), ( int )img.dimension( 3 ) ); } static public void main( final String[] args ) From eb4a60f618ff49f3da9b01bdf3ff8435cb95cdd5 Mon Sep 17 00:00:00 2001 From: Gabriel Selzer Date: Mon, 3 Mar 2025 13:36:00 -0600 Subject: [PATCH 07/11] Test cleanup --- .../net/imglib2/imagej/ImgPlusToImagePlusTest.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/test/java/net/imglib2/imagej/ImgPlusToImagePlusTest.java b/src/test/java/net/imglib2/imagej/ImgPlusToImagePlusTest.java index 965955d..f286b01 100644 --- a/src/test/java/net/imglib2/imagej/ImgPlusToImagePlusTest.java +++ b/src/test/java/net/imglib2/imagej/ImgPlusToImagePlusTest.java @@ -34,9 +34,6 @@ package net.imglib2.imagej; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; - import java.util.concurrent.atomic.AtomicInteger; import net.imagej.ImgPlus; @@ -78,6 +75,8 @@ import ij.process.ImageProcessor; import ij.process.ShortProcessor; +import static org.junit.Assert.*; + public class ImgPlusToImagePlusTest { @Test @@ -235,7 +234,7 @@ public void testDoubleType() private < T extends RealType< T > > void testTypeConversion( final Class< ? extends ImageProcessor > processorClass, final float expected, final T input ) { - final RandomAccessibleInterval< T > rai = ConstantUtils.constantRandomAccessibleInterval( input, 2, new FinalInterval( 1, 1 ) ); + final RandomAccessibleInterval< T > rai = ConstantUtils.constantRandomAccessibleInterval( input, new FinalInterval( 1, 1 ) ); final Img< T > image = ImgView.wrap( rai, null ); final ImgPlus< T > imgPlus = new ImgPlus< T >( image, "title", new AxisType[] { Axes.X, Axes.Y } ); // process @@ -246,7 +245,7 @@ private < T extends RealType< T > > void testTypeConversion( final Class< ? exte Assert.assertEquals( expected, processor.getPixelValue( 0, 0 ), 0f ); } - private void fill( final RandomAccessibleInterval< ? extends IntegerType > img ) + private void fill( final RandomAccessibleInterval< ? extends IntegerType > img ) { final AtomicInteger i = new AtomicInteger(); Views.flatIterable( img ).forEach( pixel -> pixel.setInteger( i.incrementAndGet() ) ); @@ -299,6 +298,6 @@ public void testPersistenceBits() // data // changed // test - assertEquals( true, img.cursor().next().get() ); + assertTrue(img.cursor().next().get()); } } From a764ca72ddeda61060b1712676ef5bccb4cbb35a Mon Sep 17 00:00:00 2001 From: Gabriel Selzer Date: Mon, 3 Mar 2025 13:37:13 -0600 Subject: [PATCH 08/11] Remove io package Can add back later if needed --- .../java/net/imglib2/imagej/io/IJLoader.java | 62 ---- src/main/java/net/imglib2/imagej/io/Load.java | 273 ------------------ .../io/proxyaccess/AbstractAccessProxy.java | 56 ---- .../io/proxyaccess/ByteAccessProxy.java | 89 ------ .../io/proxyaccess/FloatAccessProxy.java | 89 ------ .../imagej/io/proxyaccess/IntAccessProxy.java | 88 ------ .../io/proxyaccess/LongAccessProxy.java | 88 ------ .../io/proxyaccess/ShortAccessProxy.java | 88 ------ .../java/net/imglib2/imagej/io/LoadTest.java | 138 --------- 9 files changed, 971 deletions(-) delete mode 100644 src/main/java/net/imglib2/imagej/io/IJLoader.java delete mode 100644 src/main/java/net/imglib2/imagej/io/Load.java delete mode 100644 src/main/java/net/imglib2/imagej/io/proxyaccess/AbstractAccessProxy.java delete mode 100644 src/main/java/net/imglib2/imagej/io/proxyaccess/ByteAccessProxy.java delete mode 100644 src/main/java/net/imglib2/imagej/io/proxyaccess/FloatAccessProxy.java delete mode 100644 src/main/java/net/imglib2/imagej/io/proxyaccess/IntAccessProxy.java delete mode 100644 src/main/java/net/imglib2/imagej/io/proxyaccess/LongAccessProxy.java delete mode 100644 src/main/java/net/imglib2/imagej/io/proxyaccess/ShortAccessProxy.java delete mode 100644 src/test/java/net/imglib2/imagej/io/LoadTest.java diff --git a/src/main/java/net/imglib2/imagej/io/IJLoader.java b/src/main/java/net/imglib2/imagej/io/IJLoader.java deleted file mode 100644 index be6d546..0000000 --- a/src/main/java/net/imglib2/imagej/io/IJLoader.java +++ /dev/null @@ -1,62 +0,0 @@ -/*- - * #%L - * ImgLib2: a general-purpose, multidimensional image processing library. - * %% - * Copyright (C) 2009 - 2025 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.imagej.io; - -import ij.IJ; -import net.imglib2.cache.CacheLoader; -import net.imglib2.imagej.ImagePlusToImg; -import net.imglib2.img.Img; -import net.imglib2.img.planar.PlanarImg; -import net.imglib2.type.NativeType; -import net.imglib2.type.numeric.NumericType; - -/** - * An ImageJ-powered implementation of a disk-based {@link CacheLoader}: - * the file system is the cache, and requests to load image file paths - * are executed using ImageJ's {@link IJ#openImage(java.lang.String)}, - * and wrapped as {@link PlanarImg} via the {@link net.imglib2.imagej.ImagePlusToImg#wrap(ij.ImagePlus)}. - * - * @author Albert Cardona - * - * @param - */ -public class IJLoader< T extends NumericType< T > & NativeType< T > > implements CacheLoader< String, Img< T > > -{ - @Override - @SuppressWarnings("unchecked") - public Img< T > get( final String path ) - { - return (Img) ImagePlusToImg.wrap( IJ.openImage( path ) ); - } -} diff --git a/src/main/java/net/imglib2/imagej/io/Load.java b/src/main/java/net/imglib2/imagej/io/Load.java deleted file mode 100644 index ec8656c..0000000 --- a/src/main/java/net/imglib2/imagej/io/Load.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * #%L - * ImgLib2: a general-purpose, multidimensional image processing library. - * %% - * Copyright (C) 2009 - 2025 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.imagej.io; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -import net.imagej.ImgPlus; -import net.imglib2.RandomAccessibleInterval; -import net.imglib2.cache.CacheLoader; -import net.imglib2.cache.UncheckedCache; -import net.imglib2.cache.img.CachedCellImg; -import net.imglib2.cache.img.ReadOnlyCachedCellImgFactory; -import net.imglib2.cache.img.ReadOnlyCachedCellImgOptions; -import net.imglib2.cache.ref.SoftRefLoaderCache; -import net.imglib2.img.Img; -import net.imglib2.img.array.ArrayImg; -import net.imglib2.img.basictypeaccess.array.ArrayDataAccess; -import net.imglib2.img.basictypeaccess.volatiles.VolatileArrayDataAccess; -import net.imglib2.img.basictypeaccess.volatiles.array.VolatileByteArray; -import net.imglib2.img.basictypeaccess.volatiles.array.VolatileDoubleArray; -import net.imglib2.img.basictypeaccess.volatiles.array.VolatileFloatArray; -import net.imglib2.img.basictypeaccess.volatiles.array.VolatileIntArray; -import net.imglib2.img.basictypeaccess.volatiles.array.VolatileLongArray; -import net.imglib2.img.basictypeaccess.volatiles.array.VolatileShortArray; -import net.imglib2.img.cell.Cell; -import net.imglib2.img.cell.LazyCellImg; -import net.imglib2.imagej.io.proxyaccess.ByteAccessProxy; -import net.imglib2.imagej.io.proxyaccess.FloatAccessProxy; -import net.imglib2.imagej.io.proxyaccess.IntAccessProxy; -import net.imglib2.imagej.io.proxyaccess.LongAccessProxy; -import net.imglib2.imagej.io.proxyaccess.ShortAccessProxy; -import net.imglib2.img.planar.PlanarImg; -import net.imglib2.type.NativeType; -import net.imglib2.type.numeric.NumericType; -import net.imglib2.type.numeric.RealType; -import net.imglib2.type.numeric.integer.GenericByteType; -import net.imglib2.type.numeric.integer.GenericIntType; -import net.imglib2.type.numeric.integer.GenericLongType; -import net.imglib2.type.numeric.integer.GenericShortType; -import net.imglib2.view.Views; - -public class Load -{ - /** Return a {@link CachedCellImg} representation of the ordered list of file paths, - * with each file path pointing to an image that can be loaded with the {@link CacheLoader}. - * All images are expected to be of the same dimensions and of {@link NativeType}. - * Each image is loaded as a {@link Cell} of the {@link LazyCellImg}, or, - * in the case of {@link PlanarImg}, each stack plane is loaded as a {@link Cell}. - * - * For example, load a 4D volume by providing a list of file paths to the 3D volume of each time point. - * Can equally load a 3D volume by providing a list of file paths to the 2D images. - * - * The first image will be loaded to find out the dimensions, but it is cached. - * - * @param paths The ordered list of file paths, one per image to load. - * @param loader The reader that turns a file path into an {@link Img}. - */ - static public final < T extends NumericType< T > & NativeType< T >, A extends ArrayDataAccess< A > > - CachedCellImg< T, A > lazyStack( - final List< String > paths, - final CacheLoader< String, Img< T > > loader - ) - { - final UncheckedCache< Integer, Img< T > > loading_cache = new SoftRefLoaderCache< Integer, Img< T > >() - .withLoader( i -> loader.get( paths.get( i ) ) ) - .unchecked(); - - final Img< T > first = loading_cache.get( 0 ); - - final long[] dimensions_all = new long[ first.numDimensions() + 1 ]; - first.dimensions( dimensions_all ); - dimensions_all[ dimensions_all.length - 1 ] = paths.size(); - - final CacheLoader< Long, Cell< A > > cache_loader; - final int[] dimensions_cell = new int[ first.numDimensions() + 1 ]; - - if ( first instanceof PlanarImg ) - { - @SuppressWarnings("unchecked") - final int numSlices = ( ( PlanarImg< T, ? > )first ).numSlices(); - - dimensions_cell[ 0 ] = ( int )first.dimension( 0 ); - dimensions_cell[ 1 ] = ( int )first.dimension( 1 ); - dimensions_cell[ 2 ] = 1; // single unit in Z - dimensions_cell[ 3 ] = 1; // single unit in T - - cache_loader = new CacheLoader< Long, Cell< A > >() - { - @Override - final public Cell< A > get( final Long index ) throws Exception { - final int i = index.intValue(); - final int t = ( ( int )i ) / numSlices; - final int z = ( ( int )i ) % numSlices; - // Origin of coordinates for the Cell: 0,0,z,t - final long[] min = new long[ first.numDimensions() + 1 ]; - min[ 2 ] = z; - min[ 3 ] = t; - @SuppressWarnings("unchecked") - final PlanarImg< T, A > stack = ( PlanarImg< T, A > )loading_cache.get( t ); - return new Cell< A >( dimensions_cell, min, stack.getPlane( z ) ); - } - }; - } - else - { - for ( int d = 0; d < dimensions_cell.length -1; ++ d ) - dimensions_cell[ d ] = ( int )first.dimension( d ); - - dimensions_cell[ dimensions_cell.length - 1 ] = 1; - - cache_loader = new CacheLoader< Long, Cell< A > >() - { - @Override - final public Cell< A > get( final Long index ) throws Exception { - final long[] min = new long[ first.numDimensions() + 1 ]; - min[ min.length - 1 ] = index; - return new Cell< A >( dimensions_cell, min, extractDataAccess( loading_cache.get( index.intValue() ) ) ); - } - }; - } - - final CachedCellImg< T, A > ccimg = new ReadOnlyCachedCellImgFactory().createWithCacheLoader( - dimensions_all, - first.firstElement().createVariable(), - cache_loader, - ReadOnlyCachedCellImgOptions.options().volatileAccesses( true ).cellDimensions( dimensions_cell ) ); - - - return ccimg; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - static private final < T extends NumericType< T > & NativeType< T >, A extends ArrayDataAccess< ? > > A extractDataAccess( final Img< T > img ) - { - if ( ImgPlus.class.isAssignableFrom( img.getClass() ) ) - return extractDataAccess( ( ( ImgPlus< T > )img ).getImg() ); - - if ( ArrayImg.class.isAssignableFrom( img.getClass() ) ) - return (A) wrapAsVolatile( ( ( ArrayImg< T, ArrayDataAccess< ? > > )img ).update( null ) ); - - // If images are not of type ArrayImg, provide read/write proxy random access - final T type = img.firstElement(); - - if ( type instanceof GenericByteType ) - return (A) new ByteAccessProxy( img ); - - if ( type instanceof GenericShortType ) - return (A) new ShortAccessProxy( img ); - - if ( type instanceof GenericIntType ) - return (A) new IntAccessProxy( img ); - - if ( type instanceof GenericLongType ) - return (A) new LongAccessProxy( img ); - - if ( type instanceof RealType ) - return (A) new FloatAccessProxy( img ); - - return null; - } - - static private final VolatileArrayDataAccess< ? > wrapAsVolatile( final ArrayDataAccess< ? > access ) - { - final Object array = access.getCurrentStorageArray(); - - if ( array instanceof byte[] ) - return new VolatileByteArray( ( byte[] )array, true ); - else if ( array instanceof short[] ) - return new VolatileShortArray( ( short[] )array, true ); - else if ( array instanceof int[] ) - return new VolatileIntArray( ( int[] )array, true ); - else if ( array instanceof long[] ) - return new VolatileLongArray( ( long[] )array, true ); - else if ( array instanceof float[] ) - return new VolatileFloatArray( ( float[] )array, true ); - else if (array instanceof double[] ) - return new VolatileDoubleArray( ( double[] )array, true ); - - return null; - } - - /** - * Convenient method that invokes {@link Load#lazyStack(List, CacheLoader)} - * with a cache-enabled {@link IJLoader}. - * - * @see Load#lazyStack(List, CacheLoader) - * - * @param paths The ordered list of file paths, one per image to load. - * @return a {@link LazyCellImg} that lazily loads each time point, one per file path. - */ - static public final < T extends NumericType< T > & NativeType< T >, A extends ArrayDataAccess< A > > LazyCellImg< T, A > lazyStack( final String[] paths ) - { - return Load.lazyStack( Arrays.asList( paths ), new IJLoader< T >() ); - } - - /** - * Convenient method that invokes {@link Load#lazyStack(List, CacheLoader)} - * with a cache-enabled {@link IJLoader}. - * - * @see Load#lazyStack(List, CacheLoader) - * - * @param paths The ordered list of file paths, one per image to load. - * @return a {@link LazyCellImg} that lazily loads each time point, one per file path. - */ - static public final < T extends NumericType< T > & NativeType< T >, A extends ArrayDataAccess< A > > LazyCellImg< T, A > lazyStack( final List< String > paths ) - { - return Load.lazyStack( paths, new IJLoader< T >() ); - } - - /** - * Return an {@link Img} representation of the ordered list of file paths, - * with each file path pointing to an image that can be loaded with the {@link CacheLoader}. - * All images are expected to be of the same dimensions and of {@link NativeType}. - * Eager: loads all images right away. - * - * @param paths The ordered list of file paths, one per image to load. - * @param loader The reader that turns a file path into an {@link Img}. - * @return - */ - static public final < T extends NumericType< T > & NativeType< T > > RandomAccessibleInterval< T > stack( final List< String > paths, final CacheLoader< String, Img< T > > loader ) - { - return Views.stack( paths.stream().map( path -> { - try { - return loader.get( path ); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } ).collect( Collectors.toList() ) ); - } - - /** - * @see Load#stack(List, CacheLoader) - */ - static public final < T extends NumericType< T > & NativeType< T > > RandomAccessibleInterval< T > stack( final String[] paths, final CacheLoader< String, Img< T > > loader ) - { - return stack( Arrays.asList( paths ), loader ); - } -} diff --git a/src/main/java/net/imglib2/imagej/io/proxyaccess/AbstractAccessProxy.java b/src/main/java/net/imglib2/imagej/io/proxyaccess/AbstractAccessProxy.java deleted file mode 100644 index 0ef8a97..0000000 --- a/src/main/java/net/imglib2/imagej/io/proxyaccess/AbstractAccessProxy.java +++ /dev/null @@ -1,56 +0,0 @@ -/*- - * #%L - * ImgLib2: a general-purpose, multidimensional image processing library. - * %% - * Copyright (C) 2009 - 2025 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.imagej.io.proxyaccess; - -import java.util.Arrays; - -import net.imglib2.RandomAccess; -import net.imglib2.RandomAccessibleInterval; - -abstract public class AbstractAccessProxy< T > -{ - protected final RandomAccess< T > ra; - protected final long[] dimensions, - position; - protected final int size; - - public AbstractAccessProxy( final RandomAccessibleInterval< T > rai ) - { - this.ra = rai.randomAccess(); - this.dimensions = new long[ rai.numDimensions() ]; - rai.dimensions( this.dimensions ); - this.size = ( int )Arrays.stream( this.dimensions ).reduce( (a, b) -> a * b ).getAsLong(); - this.position = new long[ rai.numDimensions() ]; - } -} diff --git a/src/main/java/net/imglib2/imagej/io/proxyaccess/ByteAccessProxy.java b/src/main/java/net/imglib2/imagej/io/proxyaccess/ByteAccessProxy.java deleted file mode 100644 index ac3f6f2..0000000 --- a/src/main/java/net/imglib2/imagej/io/proxyaccess/ByteAccessProxy.java +++ /dev/null @@ -1,89 +0,0 @@ -/*- - * #%L - * ImgLib2: a general-purpose, multidimensional image processing library. - * %% - * Copyright (C) 2009 - 2025 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.imagej.io.proxyaccess; - -import net.imglib2.RandomAccessibleInterval; -import net.imglib2.img.basictypeaccess.ByteAccess; -import net.imglib2.img.basictypeaccess.array.ArrayDataAccess; -import net.imglib2.type.numeric.integer.GenericByteType; -import net.imglib2.util.IntervalIndexer; - -/** - * Proxy access over any {@link GenericByteType} container. - * - * @author Albert Cardona - */ -public class ByteAccessProxy< T extends GenericByteType< T > > extends AbstractAccessProxy< T > implements ByteAccess, ArrayDataAccess< byte[] > -{ - private static final long serialVersionUID = 1L; - - public ByteAccessProxy( final RandomAccessibleInterval< T > rai ) - { - super( rai ); - } - - @Override - synchronized public byte getValue( final int index ) - { - IntervalIndexer.indexToPosition( index, this.dimensions, this.position ); - this.ra.setPosition( this.position ); - return this.ra.get().getByte(); - } - - @Override - synchronized public void setValue( final int index, final byte value ) - { - IntervalIndexer.indexToPosition( index, this.dimensions, this.position ); - this.ra.setPosition( this.position ); - this.ra.get().setByte( value ); - } - - @Override - public byte[] createArray( final int numEntities ) - { - return new byte[ numEntities ]; - } - - @Override - public Object getCurrentStorageArray() - { - return null; - } - - @Override - public int getArrayLength() - { - return this.size; - } -} diff --git a/src/main/java/net/imglib2/imagej/io/proxyaccess/FloatAccessProxy.java b/src/main/java/net/imglib2/imagej/io/proxyaccess/FloatAccessProxy.java deleted file mode 100644 index f14924d..0000000 --- a/src/main/java/net/imglib2/imagej/io/proxyaccess/FloatAccessProxy.java +++ /dev/null @@ -1,89 +0,0 @@ -/*- - * #%L - * ImgLib2: a general-purpose, multidimensional image processing library. - * %% - * Copyright (C) 2009 - 2025 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.imagej.io.proxyaccess; - -import net.imglib2.RandomAccessibleInterval; -import net.imglib2.img.basictypeaccess.FloatAccess; -import net.imglib2.img.basictypeaccess.array.ArrayDataAccess; -import net.imglib2.type.numeric.RealType; -import net.imglib2.util.IntervalIndexer; - -/** - * Proxy access over any {@link RealType} container. - * - * @author Albert Cardona - */ -public class FloatAccessProxy< T extends RealType< T > > extends AbstractAccessProxy< T > implements FloatAccess, ArrayDataAccess< float[] > -{ - private static final long serialVersionUID = 1L; - - public FloatAccessProxy( final RandomAccessibleInterval< T > rai ) - { - super( rai ); - } - - @Override - synchronized public float getValue( final int index ) - { - IntervalIndexer.indexToPosition( index, this.dimensions, this.position ); - this.ra.setPosition( this.position ); - return this.ra.get().getRealFloat(); - } - - @Override - synchronized public void setValue( final int index, final float value ) - { - IntervalIndexer.indexToPosition( index, this.dimensions, this.position ); - this.ra.setPosition( this.position ); - this.ra.get().setReal( value ); - } - - @Override - public float[] createArray( final int numEntities ) - { - return new float[ numEntities ]; - } - - @Override - public Object getCurrentStorageArray() - { - return null; - } - - @Override - public int getArrayLength() - { - return this.size; - } -} diff --git a/src/main/java/net/imglib2/imagej/io/proxyaccess/IntAccessProxy.java b/src/main/java/net/imglib2/imagej/io/proxyaccess/IntAccessProxy.java deleted file mode 100644 index 7716031..0000000 --- a/src/main/java/net/imglib2/imagej/io/proxyaccess/IntAccessProxy.java +++ /dev/null @@ -1,88 +0,0 @@ -/*- - * #%L - * ImgLib2: a general-purpose, multidimensional image processing library. - * %% - * Copyright (C) 2009 - 2025 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.imagej.io.proxyaccess; - -import net.imglib2.RandomAccessibleInterval; -import net.imglib2.img.basictypeaccess.IntAccess; -import net.imglib2.img.basictypeaccess.array.ArrayDataAccess; -import net.imglib2.type.numeric.integer.GenericIntType; -import net.imglib2.util.IntervalIndexer; - -/** - * Proxy access over any {@link GenericIntType} container. - * - * @author Albert Cardona - */ -public class IntAccessProxy< T extends GenericIntType< T > > extends AbstractAccessProxy< T > implements IntAccess, ArrayDataAccess< int[] > -{ - private static final long serialVersionUID = 1L; - - public IntAccessProxy( final RandomAccessibleInterval< T > rai ) - { - super( rai ); - } - - @Override - synchronized public int getValue( final int index ) - { - IntervalIndexer.indexToPosition( index, this.dimensions, this.position ); - this.ra.setPosition( this.position ); - return this.ra.get().getInteger(); - } - - @Override - synchronized public void setValue( final int index, final int value ) - { - IntervalIndexer.indexToPosition( index, this.dimensions, this.position ); - this.ra.setPosition( this.position ); - this.ra.get().setInteger( value ); - } - - @Override - public int[] createArray( final int numEntities ) { - return new int[ numEntities ]; - } - - @Override - public Object getCurrentStorageArray() - { - return null; - } - - @Override - public int getArrayLength() - { - return this.size; - } -} diff --git a/src/main/java/net/imglib2/imagej/io/proxyaccess/LongAccessProxy.java b/src/main/java/net/imglib2/imagej/io/proxyaccess/LongAccessProxy.java deleted file mode 100644 index 913b22f..0000000 --- a/src/main/java/net/imglib2/imagej/io/proxyaccess/LongAccessProxy.java +++ /dev/null @@ -1,88 +0,0 @@ -/*- - * #%L - * ImgLib2: a general-purpose, multidimensional image processing library. - * %% - * Copyright (C) 2009 - 2025 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.imagej.io.proxyaccess; - -import net.imglib2.RandomAccessibleInterval; -import net.imglib2.img.basictypeaccess.LongAccess; -import net.imglib2.img.basictypeaccess.array.ArrayDataAccess; -import net.imglib2.type.numeric.integer.GenericLongType; -import net.imglib2.util.IntervalIndexer; - -/** - * Proxy access over any {@link GenericLongType} container. - * - * @author Albert Cardona - */ -public class LongAccessProxy< T extends GenericLongType< T > > extends AbstractAccessProxy< T > implements LongAccess, ArrayDataAccess< long[] > -{ - private static final long serialVersionUID = 1L; - - public LongAccessProxy( final RandomAccessibleInterval< T > rai ) - { - super( rai ); - } - - @Override - synchronized public long getValue( final int index ) - { - IntervalIndexer.indexToPosition( index, this.dimensions, this.position ); - this.ra.setPosition( this.position ); - return this.ra.get().getIntegerLong(); - } - - @Override - synchronized public void setValue( final int index, final long value ) - { - IntervalIndexer.indexToPosition( index, this.dimensions, this.position ); - this.ra.setPosition( this.position ); - this.ra.get().setInteger( value ); - } - - @Override - public long[] createArray( final int numEntities ) { - return new long[ numEntities ]; - } - - @Override - public Object getCurrentStorageArray() - { - return null; - } - - @Override - public int getArrayLength() - { - return this.size; - } -} diff --git a/src/main/java/net/imglib2/imagej/io/proxyaccess/ShortAccessProxy.java b/src/main/java/net/imglib2/imagej/io/proxyaccess/ShortAccessProxy.java deleted file mode 100644 index 4289d7b..0000000 --- a/src/main/java/net/imglib2/imagej/io/proxyaccess/ShortAccessProxy.java +++ /dev/null @@ -1,88 +0,0 @@ -/*- - * #%L - * ImgLib2: a general-purpose, multidimensional image processing library. - * %% - * Copyright (C) 2009 - 2025 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.imagej.io.proxyaccess; - -import net.imglib2.RandomAccessibleInterval; -import net.imglib2.img.basictypeaccess.ShortAccess; -import net.imglib2.img.basictypeaccess.array.ArrayDataAccess; -import net.imglib2.type.numeric.integer.GenericShortType; -import net.imglib2.util.IntervalIndexer; - -/** - * Proxy access over any {@link GenericShortType} container. - * - * @author Albert Cardona - */ -public class ShortAccessProxy< T extends GenericShortType< T > > extends AbstractAccessProxy< T > implements ShortAccess, ArrayDataAccess< short[] > -{ - private static final long serialVersionUID = 1L; - - public ShortAccessProxy( final RandomAccessibleInterval< T > rai ) - { - super( rai ); - } - - @Override - synchronized public short getValue( final int index ) - { - IntervalIndexer.indexToPosition( index, this.dimensions, this.position ); - this.ra.setPosition( this.position ); - return this.ra.get().getShort(); - } - - @Override - synchronized public void setValue( final int index, final short value ) - { - IntervalIndexer.indexToPosition( index, this.dimensions, this.position ); - this.ra.setPosition( this.position ); - this.ra.get().setShort( value ); - } - - @Override - public short[] createArray( final int numEntities ) { - return new short[ numEntities ]; - } - - @Override - public Object getCurrentStorageArray() - { - return null; - } - - @Override - public int getArrayLength() - { - return this.size; - } -} diff --git a/src/test/java/net/imglib2/imagej/io/LoadTest.java b/src/test/java/net/imglib2/imagej/io/LoadTest.java deleted file mode 100644 index 0895d19..0000000 --- a/src/test/java/net/imglib2/imagej/io/LoadTest.java +++ /dev/null @@ -1,138 +0,0 @@ -/*- - * #%L - * ImgLib2: a general-purpose, multidimensional image processing library. - * %% - * Copyright (C) 2009 - 2025 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.imagej.io; - -import ij.*; -import ij.process.ImageProcessor; -import ij.process.ShortProcessor; -import net.imglib2.Cursor; -import net.imglib2.RandomAccessibleInterval; -import net.imglib2.cache.img.CachedCellImg; -import net.imglib2.imagej.ImagePlusToImg; -import net.imglib2.img.array.ArrayImg; -import net.imglib2.img.array.ArrayImgs; -import net.imglib2.img.basictypeaccess.array.ArrayDataAccess; -import net.imglib2.type.numeric.integer.UnsignedShortType; -import net.imglib2.view.IntervalView; -import net.imglib2.view.Views; - -import java.util.Arrays; -import java.util.stream.Collectors; - -public class LoadTest -{ - final String[] paths = new String[] - { - "/home/albert/lab/scripts/data/4D-series-zip/SPM00_TM000000_CM00_CHN00.zip", - "/home/albert/lab/scripts/data/4D-series-zip/SPM00_TM000001_CM00_CHN00.zip", - "/home/albert/lab/scripts/data/4D-series-zip/SPM00_TM000002_CM00_CHN00.zip", - }; - - private class ImgVirtualStack extends VirtualStack - { - private final RandomAccessibleInterval< UnsignedShortType > img; - - ImgVirtualStack( final RandomAccessibleInterval< UnsignedShortType > img ) - { - super( ( int )img.dimension( 0 ), ( int )img.dimension( 1 ), ( int )img.dimension( 2 ) * ( int ) img.dimension( 3 ) ); - this.img = img; - } - - @Override - public Object getPixels( final int n ) - { - final ArrayImg< UnsignedShortType, ? > aimg = ArrayImgs.unsignedShorts( new long[]{ this.img.dimension( 0 ), this.img.dimension( 1 ) } ); - final long nZ = this.img.dimension( 2 ); - final IntervalView< UnsignedShortType > volume = Views.hyperSlice( this.img, 3, (n - 1) / nZ ); // fixed T - final IntervalView< UnsignedShortType > plane = Views.hyperSlice( volume, 2, (n - 1) % nZ ); // fixed Z - - final Cursor< UnsignedShortType > c1 = plane.cursor(), - c2 = aimg.cursor(); - - while ( c1.hasNext() ) - c2.next().set( c1.next() ); - - return ( ( ArrayDataAccess< ? > )aimg.update( null ) ).getCurrentStorageArray(); - } - - @Override - public ImageProcessor getProcessor( final int n ) - { - return new ShortProcessor( ( int )this.img.dimension( 0 ), ( int )this.img.dimension( 1 ), ( short[] )this.getPixels( n ), null ); - } - } - - public void testLazyStackCached() - { - final CachedCellImg< UnsignedShortType, ? > ccimg = Load.lazyStack( Arrays.asList( paths ), new IJLoader< UnsignedShortType >() ); - - show( ccimg, "lazy stack", 1, ( int )ccimg.dimension( 2 ), ( int )ccimg.dimension( 3 ) ); - } - - public void show( final RandomAccessibleInterval< UnsignedShortType > img, final String title, final int nChannels, final int nSlices, final int nFrames ) - { - final ImgVirtualStack vs = new ImgVirtualStack( img ); - final ImagePlus imp = new ImagePlus( title, vs ); - imp.setDimensions( nChannels, nSlices, nFrames ); - final CompositeImage com = new CompositeImage( imp, CompositeImage.GRAYSCALE ); - com.show(); - } - - //@Test - public void testStack() - { - final RandomAccessibleInterval< UnsignedShortType > img = Load.stack( paths, new IJLoader< UnsignedShortType >() ); - - show( img, "stack", 1, ( int )img.dimension( 2 ), ( int )img.dimension( 3 ) ); - } - - public void testStackDefault() - { - final RandomAccessibleInterval< UnsignedShortType > img = Views.stack( Arrays.stream( paths ) - .map( IJ::openImage ) - .map(ImagePlusToImg::wrapShort) - .collect( Collectors.toList() ) ); - - show(img, "stack", 1, ( int )img.dimension( 2 ), ( int )img.dimension( 3 ) ); - } - - static public void main( final String[] args ) - { - new ImageJ(); - //new LoadTest().testLazyStack(); - //new LoadTest().testStack(); - //new LoadTest().testStackDefault(); - new LoadTest().testLazyStackCached(); - } -} From 5d0e2e30b414a7461114143132c4fab2ccd93216 Mon Sep 17 00:00:00 2001 From: Gabriel Selzer Date: Mon, 3 Mar 2025 15:07:01 -0600 Subject: [PATCH 09/11] Refactor packages Packages should imply something more about the classes contained within. To be fair, I think these package names are only marginally less confusing that their predecessors, but I couldn't think of anything better :) --- src/main/java/net/imglib2/imagej/ImagePlusToImgPlus.java | 2 +- src/main/java/net/imglib2/imagej/ImgPlusToImagePlus.java | 2 +- src/main/java/net/imglib2/imagej/RAIToImagePlus.java | 2 +- src/main/java/net/imglib2/imagej/imageplus/package-info.java | 5 +++++ .../imagej/{display => img}/AbstractVirtualStack.java | 2 +- .../imglib2/imagej/{display => img}/ArrayImgToImagePlus.java | 2 +- .../imglib2/imagej/{display => img}/CalibrationUtils.java | 2 +- .../imglib2/imagej/{display => img}/CellImgToImagePlus.java | 2 +- .../imglib2/imagej/{display => img}/ImageJVirtualStack.java | 2 +- .../imagej/{display => img}/ImageJVirtualStackARGB.java | 2 +- .../imagej/{display => img}/ImageJVirtualStackFloat.java | 2 +- .../{display => img}/ImageJVirtualStackUnsignedByte.java | 2 +- .../{display => img}/ImageJVirtualStackUnsignedShort.java | 2 +- .../imglib2/imagej/{display => img}/ImageProcessorUtils.java | 2 +- .../net/imglib2/imagej/{display => img}/ImageStackUtils.java | 2 +- .../MultithreadedIterableIntervalProjector2D.java | 2 +- .../imagej/{display => img}/PlanarImgToImagePlus.java | 2 +- src/main/java/net/imglib2/imagej/img/package-info.java | 5 +++++ .../AbstractVirtualStackGetSetVoxelsTest.java | 2 +- .../imagej/{display => img}/AbstractVirtualStackTest.java | 2 +- .../imagej/{display => img}/ArrayImgToImagePlusTest.java | 2 +- .../imagej/{display => img}/CellImgToImagePlusTest.java | 2 +- .../imagej/{display => img}/ImageJFunctionBehavior.java | 2 +- .../ImageJFunctionDatasetTransformation.java | 2 +- .../ImageJVirtualStackGetProcessorBenchmark.java | 2 +- .../imagej/{display => img}/ImageJVirtualStackTest.java | 2 +- .../{display => img}/ImgLib2ToVirtualStackBenchmark.java | 2 +- .../imagej/{display => img}/PlanarImgToImagePlusTest.java | 2 +- 28 files changed, 36 insertions(+), 26 deletions(-) create mode 100644 src/main/java/net/imglib2/imagej/imageplus/package-info.java rename src/main/java/net/imglib2/imagej/{display => img}/AbstractVirtualStack.java (99%) rename src/main/java/net/imglib2/imagej/{display => img}/ArrayImgToImagePlus.java (99%) rename src/main/java/net/imglib2/imagej/{display => img}/CalibrationUtils.java (99%) rename src/main/java/net/imglib2/imagej/{display => img}/CellImgToImagePlus.java (99%) rename src/main/java/net/imglib2/imagej/{display => img}/ImageJVirtualStack.java (99%) rename src/main/java/net/imglib2/imagej/{display => img}/ImageJVirtualStackARGB.java (98%) rename src/main/java/net/imglib2/imagej/{display => img}/ImageJVirtualStackFloat.java (99%) rename src/main/java/net/imglib2/imagej/{display => img}/ImageJVirtualStackUnsignedByte.java (99%) rename src/main/java/net/imglib2/imagej/{display => img}/ImageJVirtualStackUnsignedShort.java (99%) rename src/main/java/net/imglib2/imagej/{display => img}/ImageProcessorUtils.java (99%) rename src/main/java/net/imglib2/imagej/{display => img}/ImageStackUtils.java (98%) rename src/main/java/net/imglib2/imagej/{display => img}/MultithreadedIterableIntervalProjector2D.java (99%) rename src/main/java/net/imglib2/imagej/{display => img}/PlanarImgToImagePlus.java (99%) create mode 100644 src/main/java/net/imglib2/imagej/img/package-info.java rename src/test/java/net/imglib2/imagej/{display => img}/AbstractVirtualStackGetSetVoxelsTest.java (99%) rename src/test/java/net/imglib2/imagej/{display => img}/AbstractVirtualStackTest.java (99%) rename src/test/java/net/imglib2/imagej/{display => img}/ArrayImgToImagePlusTest.java (99%) rename src/test/java/net/imglib2/imagej/{display => img}/CellImgToImagePlusTest.java (99%) rename src/test/java/net/imglib2/imagej/{display => img}/ImageJFunctionBehavior.java (99%) rename src/test/java/net/imglib2/imagej/{display => img}/ImageJFunctionDatasetTransformation.java (98%) rename src/test/java/net/imglib2/imagej/{display => img}/ImageJVirtualStackGetProcessorBenchmark.java (99%) rename src/test/java/net/imglib2/imagej/{display => img}/ImageJVirtualStackTest.java (99%) rename src/test/java/net/imglib2/imagej/{display => img}/ImgLib2ToVirtualStackBenchmark.java (99%) rename src/test/java/net/imglib2/imagej/{display => img}/PlanarImgToImagePlusTest.java (99%) diff --git a/src/main/java/net/imglib2/imagej/ImagePlusToImgPlus.java b/src/main/java/net/imglib2/imagej/ImagePlusToImgPlus.java index 1b924a2..4d473fe 100644 --- a/src/main/java/net/imglib2/imagej/ImagePlusToImgPlus.java +++ b/src/main/java/net/imglib2/imagej/ImagePlusToImgPlus.java @@ -39,7 +39,7 @@ import net.imagej.axis.CalibratedAxis; import net.imglib2.cache.Cache; import net.imglib2.cache.ref.SoftRefLoaderCache; -import net.imglib2.imagej.display.CalibrationUtils; +import net.imglib2.imagej.img.CalibrationUtils; import net.imglib2.img.basictypeaccess.array.*; import net.imglib2.img.planar.PlanarImg; import net.imglib2.type.NativeType; diff --git a/src/main/java/net/imglib2/imagej/ImgPlusToImagePlus.java b/src/main/java/net/imglib2/imagej/ImgPlusToImagePlus.java index 0b05abf..99941ec 100644 --- a/src/main/java/net/imglib2/imagej/ImgPlusToImagePlus.java +++ b/src/main/java/net/imglib2/imagej/ImgPlusToImagePlus.java @@ -44,7 +44,7 @@ import net.imagej.axis.Axes; import net.imagej.axis.AxisType; import net.imglib2.RandomAccessibleInterval; -import net.imglib2.imagej.display.*; +import net.imglib2.imagej.img.*; import net.imglib2.transform.integer.MixedTransform; import net.imglib2.type.logic.BitType; import net.imglib2.type.numeric.ARGBType; diff --git a/src/main/java/net/imglib2/imagej/RAIToImagePlus.java b/src/main/java/net/imglib2/imagej/RAIToImagePlus.java index 22b0c07..0ce5fa3 100644 --- a/src/main/java/net/imglib2/imagej/RAIToImagePlus.java +++ b/src/main/java/net/imglib2/imagej/RAIToImagePlus.java @@ -9,7 +9,7 @@ import net.imglib2.converter.Converter; import net.imglib2.converter.Converters; import net.imglib2.converter.RealUnsignedByteConverter; -import net.imglib2.imagej.display.*; +import net.imglib2.imagej.img.*; import net.imglib2.type.logic.BitType; import net.imglib2.type.numeric.*; import net.imglib2.type.numeric.integer.UnsignedByteType; diff --git a/src/main/java/net/imglib2/imagej/imageplus/package-info.java b/src/main/java/net/imglib2/imagej/imageplus/package-info.java new file mode 100644 index 0000000..86ae23d --- /dev/null +++ b/src/main/java/net/imglib2/imagej/imageplus/package-info.java @@ -0,0 +1,5 @@ +package net.imglib2.imagej.imageplus; + +/** + * This package contains utilities for converting from {@link ij.ImagePlus} to {@link net.imglib2.RandomAccessibleInterval} and its various subtypes. + */ \ No newline at end of file diff --git a/src/main/java/net/imglib2/imagej/display/AbstractVirtualStack.java b/src/main/java/net/imglib2/imagej/img/AbstractVirtualStack.java similarity index 99% rename from src/main/java/net/imglib2/imagej/display/AbstractVirtualStack.java rename to src/main/java/net/imglib2/imagej/img/AbstractVirtualStack.java index e1078bb..0ef9a9e 100644 --- a/src/main/java/net/imglib2/imagej/display/AbstractVirtualStack.java +++ b/src/main/java/net/imglib2/imagej/img/AbstractVirtualStack.java @@ -32,7 +32,7 @@ * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import java.awt.Rectangle; import java.awt.image.ColorModel; diff --git a/src/main/java/net/imglib2/imagej/display/ArrayImgToImagePlus.java b/src/main/java/net/imglib2/imagej/img/ArrayImgToImagePlus.java similarity index 99% rename from src/main/java/net/imglib2/imagej/display/ArrayImgToImagePlus.java rename to src/main/java/net/imglib2/imagej/img/ArrayImgToImagePlus.java index 3c0d06b..fa18f1c 100644 --- a/src/main/java/net/imglib2/imagej/display/ArrayImgToImagePlus.java +++ b/src/main/java/net/imglib2/imagej/img/ArrayImgToImagePlus.java @@ -32,7 +32,7 @@ * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import java.util.List; import java.util.stream.Collectors; diff --git a/src/main/java/net/imglib2/imagej/display/CalibrationUtils.java b/src/main/java/net/imglib2/imagej/img/CalibrationUtils.java similarity index 99% rename from src/main/java/net/imglib2/imagej/display/CalibrationUtils.java rename to src/main/java/net/imglib2/imagej/img/CalibrationUtils.java index e7f0ab3..bc222c0 100644 --- a/src/main/java/net/imglib2/imagej/display/CalibrationUtils.java +++ b/src/main/java/net/imglib2/imagej/img/CalibrationUtils.java @@ -31,7 +31,7 @@ * POSSIBILITY OF SUCH DAMAGE. * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/net/imglib2/imagej/display/CellImgToImagePlus.java b/src/main/java/net/imglib2/imagej/img/CellImgToImagePlus.java similarity index 99% rename from src/main/java/net/imglib2/imagej/display/CellImgToImagePlus.java rename to src/main/java/net/imglib2/imagej/img/CellImgToImagePlus.java index 365edf1..de7e473 100644 --- a/src/main/java/net/imglib2/imagej/display/CellImgToImagePlus.java +++ b/src/main/java/net/imglib2/imagej/img/CellImgToImagePlus.java @@ -32,7 +32,7 @@ * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import ij.ImagePlus; import net.imagej.ImgPlus; diff --git a/src/main/java/net/imglib2/imagej/display/ImageJVirtualStack.java b/src/main/java/net/imglib2/imagej/img/ImageJVirtualStack.java similarity index 99% rename from src/main/java/net/imglib2/imagej/display/ImageJVirtualStack.java rename to src/main/java/net/imglib2/imagej/img/ImageJVirtualStack.java index e956cdf..f80c00e 100644 --- a/src/main/java/net/imglib2/imagej/display/ImageJVirtualStack.java +++ b/src/main/java/net/imglib2/imagej/img/ImageJVirtualStack.java @@ -32,7 +32,7 @@ * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import ij.ImageStack; import ij.VirtualStack; diff --git a/src/main/java/net/imglib2/imagej/display/ImageJVirtualStackARGB.java b/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackARGB.java similarity index 98% rename from src/main/java/net/imglib2/imagej/display/ImageJVirtualStackARGB.java rename to src/main/java/net/imglib2/imagej/img/ImageJVirtualStackARGB.java index 0bca0c7..87f2cd5 100644 --- a/src/main/java/net/imglib2/imagej/display/ImageJVirtualStackARGB.java +++ b/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackARGB.java @@ -32,7 +32,7 @@ * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import java.util.concurrent.ExecutorService; diff --git a/src/main/java/net/imglib2/imagej/display/ImageJVirtualStackFloat.java b/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackFloat.java similarity index 99% rename from src/main/java/net/imglib2/imagej/display/ImageJVirtualStackFloat.java rename to src/main/java/net/imglib2/imagej/img/ImageJVirtualStackFloat.java index 75bffdb..b25e86a 100644 --- a/src/main/java/net/imglib2/imagej/display/ImageJVirtualStackFloat.java +++ b/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackFloat.java @@ -32,7 +32,7 @@ * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/net/imglib2/imagej/display/ImageJVirtualStackUnsignedByte.java b/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackUnsignedByte.java similarity index 99% rename from src/main/java/net/imglib2/imagej/display/ImageJVirtualStackUnsignedByte.java rename to src/main/java/net/imglib2/imagej/img/ImageJVirtualStackUnsignedByte.java index 93c92f4..6adf0e6 100644 --- a/src/main/java/net/imglib2/imagej/display/ImageJVirtualStackUnsignedByte.java +++ b/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackUnsignedByte.java @@ -32,7 +32,7 @@ * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import net.imglib2.RandomAccessibleInterval; import net.imglib2.Sampler; diff --git a/src/main/java/net/imglib2/imagej/display/ImageJVirtualStackUnsignedShort.java b/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackUnsignedShort.java similarity index 99% rename from src/main/java/net/imglib2/imagej/display/ImageJVirtualStackUnsignedShort.java rename to src/main/java/net/imglib2/imagej/img/ImageJVirtualStackUnsignedShort.java index b8bc154..38256e7 100644 --- a/src/main/java/net/imglib2/imagej/display/ImageJVirtualStackUnsignedShort.java +++ b/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackUnsignedShort.java @@ -32,7 +32,7 @@ * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import java.util.concurrent.ExecutorService; diff --git a/src/main/java/net/imglib2/imagej/display/ImageProcessorUtils.java b/src/main/java/net/imglib2/imagej/img/ImageProcessorUtils.java similarity index 99% rename from src/main/java/net/imglib2/imagej/display/ImageProcessorUtils.java rename to src/main/java/net/imglib2/imagej/img/ImageProcessorUtils.java index 3c73f75..b7514a0 100644 --- a/src/main/java/net/imglib2/imagej/display/ImageProcessorUtils.java +++ b/src/main/java/net/imglib2/imagej/img/ImageProcessorUtils.java @@ -32,7 +32,7 @@ * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import ij.process.ByteProcessor; import ij.process.ColorProcessor; diff --git a/src/main/java/net/imglib2/imagej/display/ImageStackUtils.java b/src/main/java/net/imglib2/imagej/img/ImageStackUtils.java similarity index 98% rename from src/main/java/net/imglib2/imagej/display/ImageStackUtils.java rename to src/main/java/net/imglib2/imagej/img/ImageStackUtils.java index 5dc350e..bfe6665 100644 --- a/src/main/java/net/imglib2/imagej/display/ImageStackUtils.java +++ b/src/main/java/net/imglib2/imagej/img/ImageStackUtils.java @@ -31,7 +31,7 @@ * POSSIBILITY OF SUCH DAMAGE. * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import ij.ImageStack; import ij.process.ImageProcessor; diff --git a/src/main/java/net/imglib2/imagej/display/MultithreadedIterableIntervalProjector2D.java b/src/main/java/net/imglib2/imagej/img/MultithreadedIterableIntervalProjector2D.java similarity index 99% rename from src/main/java/net/imglib2/imagej/display/MultithreadedIterableIntervalProjector2D.java rename to src/main/java/net/imglib2/imagej/img/MultithreadedIterableIntervalProjector2D.java index 1e4b970..b07f1ed 100644 --- a/src/main/java/net/imglib2/imagej/display/MultithreadedIterableIntervalProjector2D.java +++ b/src/main/java/net/imglib2/imagej/img/MultithreadedIterableIntervalProjector2D.java @@ -31,7 +31,7 @@ * POSSIBILITY OF SUCH DAMAGE. * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/net/imglib2/imagej/display/PlanarImgToImagePlus.java b/src/main/java/net/imglib2/imagej/img/PlanarImgToImagePlus.java similarity index 99% rename from src/main/java/net/imglib2/imagej/display/PlanarImgToImagePlus.java rename to src/main/java/net/imglib2/imagej/img/PlanarImgToImagePlus.java index e6f5b3b..640676e 100644 --- a/src/main/java/net/imglib2/imagej/display/PlanarImgToImagePlus.java +++ b/src/main/java/net/imglib2/imagej/img/PlanarImgToImagePlus.java @@ -32,7 +32,7 @@ * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import java.util.Arrays; import java.util.HashSet; diff --git a/src/main/java/net/imglib2/imagej/img/package-info.java b/src/main/java/net/imglib2/imagej/img/package-info.java new file mode 100644 index 0000000..33fc558 --- /dev/null +++ b/src/main/java/net/imglib2/imagej/img/package-info.java @@ -0,0 +1,5 @@ +package net.imglib2.imagej.img; + +/** + * This package contains utilities for converting from {@link net.imglib2.RandomAccessibleInterval} and its various subtypes to {@link ij.ImagePlus}. + */ diff --git a/src/test/java/net/imglib2/imagej/display/AbstractVirtualStackGetSetVoxelsTest.java b/src/test/java/net/imglib2/imagej/img/AbstractVirtualStackGetSetVoxelsTest.java similarity index 99% rename from src/test/java/net/imglib2/imagej/display/AbstractVirtualStackGetSetVoxelsTest.java rename to src/test/java/net/imglib2/imagej/img/AbstractVirtualStackGetSetVoxelsTest.java index 0d9644f..1a74d5a 100644 --- a/src/test/java/net/imglib2/imagej/display/AbstractVirtualStackGetSetVoxelsTest.java +++ b/src/test/java/net/imglib2/imagej/img/AbstractVirtualStackGetSetVoxelsTest.java @@ -31,7 +31,7 @@ * POSSIBILITY OF SUCH DAMAGE. * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import ij.ImageStack; import org.junit.Test; diff --git a/src/test/java/net/imglib2/imagej/display/AbstractVirtualStackTest.java b/src/test/java/net/imglib2/imagej/img/AbstractVirtualStackTest.java similarity index 99% rename from src/test/java/net/imglib2/imagej/display/AbstractVirtualStackTest.java rename to src/test/java/net/imglib2/imagej/img/AbstractVirtualStackTest.java index d350521..9c3de73 100644 --- a/src/test/java/net/imglib2/imagej/display/AbstractVirtualStackTest.java +++ b/src/test/java/net/imglib2/imagej/img/AbstractVirtualStackTest.java @@ -31,7 +31,7 @@ * POSSIBILITY OF SUCH DAMAGE. * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import ij.IJ; import ij.ImagePlus; diff --git a/src/test/java/net/imglib2/imagej/display/ArrayImgToImagePlusTest.java b/src/test/java/net/imglib2/imagej/img/ArrayImgToImagePlusTest.java similarity index 99% rename from src/test/java/net/imglib2/imagej/display/ArrayImgToImagePlusTest.java rename to src/test/java/net/imglib2/imagej/img/ArrayImgToImagePlusTest.java index 843c510..5c0f1fe 100644 --- a/src/test/java/net/imglib2/imagej/display/ArrayImgToImagePlusTest.java +++ b/src/test/java/net/imglib2/imagej/img/ArrayImgToImagePlusTest.java @@ -32,7 +32,7 @@ * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; diff --git a/src/test/java/net/imglib2/imagej/display/CellImgToImagePlusTest.java b/src/test/java/net/imglib2/imagej/img/CellImgToImagePlusTest.java similarity index 99% rename from src/test/java/net/imglib2/imagej/display/CellImgToImagePlusTest.java rename to src/test/java/net/imglib2/imagej/img/CellImgToImagePlusTest.java index 842282d..b3ba35a 100644 --- a/src/test/java/net/imglib2/imagej/display/CellImgToImagePlusTest.java +++ b/src/test/java/net/imglib2/imagej/img/CellImgToImagePlusTest.java @@ -32,7 +32,7 @@ * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import ij.ImagePlus; import ij.ImageStack; diff --git a/src/test/java/net/imglib2/imagej/display/ImageJFunctionBehavior.java b/src/test/java/net/imglib2/imagej/img/ImageJFunctionBehavior.java similarity index 99% rename from src/test/java/net/imglib2/imagej/display/ImageJFunctionBehavior.java rename to src/test/java/net/imglib2/imagej/img/ImageJFunctionBehavior.java index 758023e..3c2c0d7 100644 --- a/src/test/java/net/imglib2/imagej/display/ImageJFunctionBehavior.java +++ b/src/test/java/net/imglib2/imagej/img/ImageJFunctionBehavior.java @@ -32,7 +32,7 @@ * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import ij.IJ; import ij.ImagePlus; diff --git a/src/test/java/net/imglib2/imagej/display/ImageJFunctionDatasetTransformation.java b/src/test/java/net/imglib2/imagej/img/ImageJFunctionDatasetTransformation.java similarity index 98% rename from src/test/java/net/imglib2/imagej/display/ImageJFunctionDatasetTransformation.java rename to src/test/java/net/imglib2/imagej/img/ImageJFunctionDatasetTransformation.java index 66a8420..547f5ca 100644 --- a/src/test/java/net/imglib2/imagej/display/ImageJFunctionDatasetTransformation.java +++ b/src/test/java/net/imglib2/imagej/img/ImageJFunctionDatasetTransformation.java @@ -36,7 +36,7 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import ij.ImagePlus; import net.imglib2.Cursor; diff --git a/src/test/java/net/imglib2/imagej/display/ImageJVirtualStackGetProcessorBenchmark.java b/src/test/java/net/imglib2/imagej/img/ImageJVirtualStackGetProcessorBenchmark.java similarity index 99% rename from src/test/java/net/imglib2/imagej/display/ImageJVirtualStackGetProcessorBenchmark.java rename to src/test/java/net/imglib2/imagej/img/ImageJVirtualStackGetProcessorBenchmark.java index e186609..085a6df 100644 --- a/src/test/java/net/imglib2/imagej/display/ImageJVirtualStackGetProcessorBenchmark.java +++ b/src/test/java/net/imglib2/imagej/img/ImageJVirtualStackGetProcessorBenchmark.java @@ -31,7 +31,7 @@ * POSSIBILITY OF SUCH DAMAGE. * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import ij.ImageStack; import net.imagej.ImgPlus; diff --git a/src/test/java/net/imglib2/imagej/display/ImageJVirtualStackTest.java b/src/test/java/net/imglib2/imagej/img/ImageJVirtualStackTest.java similarity index 99% rename from src/test/java/net/imglib2/imagej/display/ImageJVirtualStackTest.java rename to src/test/java/net/imglib2/imagej/img/ImageJVirtualStackTest.java index d20eb4f..ed765c9 100644 --- a/src/test/java/net/imglib2/imagej/display/ImageJVirtualStackTest.java +++ b/src/test/java/net/imglib2/imagej/img/ImageJVirtualStackTest.java @@ -32,7 +32,7 @@ * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import ij.ImagePlus; import ij.ImageStack; diff --git a/src/test/java/net/imglib2/imagej/display/ImgLib2ToVirtualStackBenchmark.java b/src/test/java/net/imglib2/imagej/img/ImgLib2ToVirtualStackBenchmark.java similarity index 99% rename from src/test/java/net/imglib2/imagej/display/ImgLib2ToVirtualStackBenchmark.java rename to src/test/java/net/imglib2/imagej/img/ImgLib2ToVirtualStackBenchmark.java index d441086..dfd6c5a 100644 --- a/src/test/java/net/imglib2/imagej/display/ImgLib2ToVirtualStackBenchmark.java +++ b/src/test/java/net/imglib2/imagej/img/ImgLib2ToVirtualStackBenchmark.java @@ -31,7 +31,7 @@ * POSSIBILITY OF SUCH DAMAGE. * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import net.imagej.ImgPlus; import net.imagej.axis.Axes; diff --git a/src/test/java/net/imglib2/imagej/display/PlanarImgToImagePlusTest.java b/src/test/java/net/imglib2/imagej/img/PlanarImgToImagePlusTest.java similarity index 99% rename from src/test/java/net/imglib2/imagej/display/PlanarImgToImagePlusTest.java rename to src/test/java/net/imglib2/imagej/img/PlanarImgToImagePlusTest.java index 2acbe9c..0d47996 100644 --- a/src/test/java/net/imglib2/imagej/display/PlanarImgToImagePlusTest.java +++ b/src/test/java/net/imglib2/imagej/img/PlanarImgToImagePlusTest.java @@ -32,7 +32,7 @@ * #L% */ -package net.imglib2.imagej.display; +package net.imglib2.imagej.img; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; From 6dec1f233daf727a7e4c8493d4ebe4e2b6b2e518 Mon Sep 17 00:00:00 2001 From: Gabriel Selzer Date: Mon, 3 Mar 2025 15:52:09 -0600 Subject: [PATCH 10/11] Minor cleaning --- .../imagej/imageplus/ImagePlusImgFactory.java | 2 +- .../imagej/img/AbstractVirtualStack.java | 4 +- .../imagej/img/ImageJVirtualStack.java | 6 +- .../imagej/img/ImageJVirtualStackFloat.java | 4 +- .../img/ImageJVirtualStackUnsignedByte.java | 4 +- .../img/ImageJVirtualStackUnsignedShort.java | 12 +- ...tithreadedIterableIntervalProjector2D.java | 168 +++++++++--------- 7 files changed, 97 insertions(+), 103 deletions(-) diff --git a/src/main/java/net/imglib2/imagej/imageplus/ImagePlusImgFactory.java b/src/main/java/net/imglib2/imagej/imageplus/ImagePlusImgFactory.java index ea86e0c..87b6c6e 100644 --- a/src/main/java/net/imglib2/imagej/imageplus/ImagePlusImgFactory.java +++ b/src/main/java/net/imglib2/imagej/imageplus/ImagePlusImgFactory.java @@ -116,7 +116,7 @@ public ImagePlusImgFactory( final T type ) @Override public < S > ImgFactory< S > imgFactory( final S type ) throws IncompatibleTypeException { - if ( NativeType.class.isInstance( type ) ) + if (type instanceof NativeType) return new ImagePlusImgFactory( ( NativeType ) type ); throw new IncompatibleTypeException( this, type.getClass().getCanonicalName() + " does not implement NativeType." ); } diff --git a/src/main/java/net/imglib2/imagej/img/AbstractVirtualStack.java b/src/main/java/net/imglib2/imagej/img/AbstractVirtualStack.java index 0ef9a9e..09124fc 100644 --- a/src/main/java/net/imglib2/imagej/img/AbstractVirtualStack.java +++ b/src/main/java/net/imglib2/imagej/img/AbstractVirtualStack.java @@ -460,8 +460,8 @@ private BiConsumer voxelAccessAction( Integer channel, boolean isS if ( bitDepth == 24 ) return arbgVoxelAccessAction( channel, isSetVoxels ); return isSetVoxels ? - (BiConsumer< RealType, FloatType >) ( a, b ) -> a.setReal( b.getRealFloat() ) : - (BiConsumer< RealType, FloatType >) ( a, b ) -> b.setReal( a.getRealFloat() ); + (BiConsumer< RealType, FloatType >) ( a, b ) -> a.setReal( b.getRealFloat() ) : + (BiConsumer< RealType, FloatType >) ( a, b ) -> b.setReal( a.getRealFloat() ); } private static BiConsumer arbgVoxelAccessAction( Integer channel, boolean isSetVoxel ) diff --git a/src/main/java/net/imglib2/imagej/img/ImageJVirtualStack.java b/src/main/java/net/imglib2/imagej/img/ImageJVirtualStack.java index f80c00e..7e14274 100644 --- a/src/main/java/net/imglib2/imagej/img/ImageJVirtualStack.java +++ b/src/main/java/net/imglib2/imagej/img/ImageJVirtualStack.java @@ -49,12 +49,12 @@ import net.imglib2.img.array.ArrayImgFactory; import net.imglib2.img.basictypeaccess.array.ArrayDataAccess; import net.imglib2.type.NativeType; +import net.imglib2.type.Type; import net.imglib2.type.numeric.ARGBType; import net.imglib2.type.numeric.integer.UnsignedByteType; import net.imglib2.type.numeric.integer.UnsignedShortType; import net.imglib2.type.numeric.real.FloatType; import net.imglib2.util.IntervalIndexer; -import net.imglib2.util.Util; import net.imglib2.view.Views; import java.util.concurrent.ExecutorService; @@ -113,7 +113,7 @@ protected ImageJVirtualStack( final RandomAccessibleInterval< T > source, final // if we were given an ExecutorService, use a multithreaded projector assert source.numDimensions() > 1; this.source = zeroMin( source ); - this.type = Util.getTypeFromInterval( source ); + this.type = source.getType(); this.higherSourceDimensions = initHigherDimensions( source ); } @@ -204,7 +204,7 @@ protected void setPixelsZeroBasedIndex( final int index, final Object pixels ) Img< T > img = ( Img< T > ) ImageProcessorUtils.createImg( pixels, getWidth(), getHeight() ); // NB: The use of Converter and Projector2D is a bit surprising. // As the converter intentionally uses the first parameter a output. - project( index, img, (o, i) -> o.set( i ) ); + project( index, img, Type::set); } @Override diff --git a/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackFloat.java b/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackFloat.java index b25e86a..7f57638 100644 --- a/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackFloat.java +++ b/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackFloat.java @@ -67,9 +67,9 @@ public class ImageJVirtualStackFloat extends ImageJVirtualStack< FloatType > private static < T extends RealType< ? > > RandomAccessibleInterval toFloat( RandomAccessibleInterval source ) { - if( Util.getTypeFromInterval(source) instanceof FloatType ) + if( source.getType() instanceof FloatType ) return ( RandomAccessibleInterval< FloatType > ) source; - return Converters.convert( source, new ToFloatSamplerConverter( Util.getTypeFromInterval( source ))); + return Converters.convert( source, new ToFloatSamplerConverter( source.getType())); } public < S > ImageJVirtualStackFloat( final RandomAccessibleInterval< S > source, diff --git a/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackUnsignedByte.java b/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackUnsignedByte.java index 6adf0e6..9923010 100644 --- a/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackUnsignedByte.java +++ b/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackUnsignedByte.java @@ -61,9 +61,9 @@ public class ImageJVirtualStackUnsignedByte extends ImageJVirtualStack< Unsigned private static < T extends RealType< ? > > RandomAccessibleInterval< UnsignedByteType > toUnsignedByteType( RandomAccessibleInterval< T > source ) { - if( Util.getTypeFromInterval( source ) instanceof UnsignedByteType ) + if( source.getType() instanceof UnsignedByteType ) return ( RandomAccessibleInterval< UnsignedByteType > ) source; - return Converters.convert(source, new ToUnsignedByteSamplerConverter( Util.getTypeFromInterval( source ) ) ); + return Converters.convert(source, new ToUnsignedByteSamplerConverter( source.getType() ) ); } public static ImageJVirtualStackUnsignedByte wrapAndScaleBitType( final RandomAccessibleInterval< BitType > source ) diff --git a/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackUnsignedShort.java b/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackUnsignedShort.java index 38256e7..ef5c950 100644 --- a/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackUnsignedShort.java +++ b/src/main/java/net/imglib2/imagej/img/ImageJVirtualStackUnsignedShort.java @@ -57,15 +57,15 @@ public class ImageJVirtualStackUnsignedShort extends ImageJVirtualStack< Unsigne public static < T extends RealType< ? > > ImageJVirtualStackUnsignedShort wrap( final RandomAccessibleInterval< T > source ) { final ImageJVirtualStackUnsignedShort result = new ImageJVirtualStackUnsignedShort( toUnsignedShort( source ) ); - result.initMinMax( Util.getTypeFromInterval( source ) ); + result.initMinMax( source.getType() ); return result; } private static < T extends RealType< ? > > RandomAccessibleInterval< UnsignedShortType > toUnsignedShort( RandomAccessibleInterval< T > source ) { - if( Util.getTypeFromInterval( source ) instanceof UnsignedShortType ) + if( source.getType() instanceof UnsignedShortType ) return ( RandomAccessibleInterval< UnsignedShortType > ) source; - return Converters.convert( source, new ShortConverter( Util.getTypeFromInterval( source ) ) ); + return Converters.convert( source, new ShortConverter( source.getType() ) ); } public < S > ImageJVirtualStackUnsignedShort( final RandomAccessibleInterval< S > source, final Converter< ? super S, UnsignedShortType > converter ) @@ -76,7 +76,7 @@ public < S > ImageJVirtualStackUnsignedShort( final RandomAccessibleInterval< S public < S > ImageJVirtualStackUnsignedShort( final RandomAccessibleInterval< S > source, final Converter< ? super S, UnsignedShortType > converter, final ExecutorService service ) { super( source, converter, new UnsignedShortType(), 16, service ); - initMinMax( Util.getTypeFromInterval( source ) ); + initMinMax( source.getType() ); } private ImageJVirtualStackUnsignedShort( final RandomAccessibleInterval< UnsignedShortType > source ) @@ -88,9 +88,9 @@ private void initMinMax( Object s ) { int maxDisplay = ( 1 << 16 ) - 1; - if ( BitType.class.isInstance( s ) ) + if (s instanceof BitType) maxDisplay = 1; - else if ( Unsigned12BitType.class.isInstance( s ) ) + else if (s instanceof Unsigned12BitType) maxDisplay = 4095; setMinAndMax( 0, maxDisplay ); diff --git a/src/main/java/net/imglib2/imagej/img/MultithreadedIterableIntervalProjector2D.java b/src/main/java/net/imglib2/imagej/img/MultithreadedIterableIntervalProjector2D.java index b07f1ed..19db3fa 100644 --- a/src/main/java/net/imglib2/imagej/img/MultithreadedIterableIntervalProjector2D.java +++ b/src/main/java/net/imglib2/imagej/img/MultithreadedIterableIntervalProjector2D.java @@ -110,7 +110,7 @@ public void map() max[dimX] = target.max( 0 ); max[dimY] = target.max( 1 ); - final IterableInterval< A > ii = Views.iterable( Views.interval( source, new FinalInterval( min, max ) ) ); + final IterableInterval< A > ii = Views.interval( source, new FinalInterval( min, max ) ); final long portionSize = target.size() / nTasks; @@ -119,92 +119,86 @@ public void map() for ( int t = 0; t < nTasks; ++t ) { - tasks.add( new Callable< Void >() - { - - @Override - public Void call() throws Exception - { - int i = ai.getAndIncrement(); - - final Cursor< B > targetCursor = target.localizingCursor(); - - // we might need either a cursor or a RandomAccess - final RandomAccess< A > sourceRandomAccess = source.randomAccess(); - sourceRandomAccess.setPosition( position ); - - final Cursor< A > sourceCursor = ii.cursor(); - - // jump to correct starting point - targetCursor.jumpFwd( i * portionSize ); - sourceCursor.jumpFwd( i * portionSize ); - long stepsTaken = 0; - - if ( target.iterationOrder().equals( ii.iterationOrder() ) - && !( sourceCursor instanceof RandomAccessibleIntervalCursor ) ) - { - // either map a portion or (for the last portion) go - // until the end - while ( ( i != nTasks - 1 && stepsTaken < portionSize ) - || ( i == nTasks - 1 && targetCursor.hasNext() ) ) - { - stepsTaken++; - converter.convert( sourceCursor.next(), targetCursor.next() ); - } - } - - else if ( target.iterationOrder() instanceof FlatIterationOrder ) - { - - final long cr = -target.dimension( 0 ); - final long width = target.dimension( 0 ); - final long height = target.dimension( 1 ); - - final long initX = ( i * portionSize ) % width; - final long initY = ( i * portionSize ) / width; - // either map a portion or (for the last portion) go - // until the end - final long endX = ( i == nTasks - 1 ) ? width : ( initX + ( i + 1 ) * portionSize ) % width; - final long endY = ( i == nTasks - 1 ) ? height - 1 - : ( initX + ( i + 1 ) * portionSize ) / width; - - sourceRandomAccess.setPosition( initX, dimX ); - sourceRandomAccess.setPosition( initY, dimY ); - - for ( long y = initY; y <= endY; ++y ) - { - for ( long x = ( y == initY ? initX : 0 ); x < ( y == endY ? endX : width ); ++x ) - { - targetCursor.fwd(); - converter.convert( sourceRandomAccess.get(), targetCursor.get() ); - sourceRandomAccess.fwd( dimX ); - - } - sourceRandomAccess.move( cr, dimX ); - sourceRandomAccess.fwd( dimY ); - } - } - - else - { - // either map a portion or (for the last portion) go - // until the end - while ( ( i != nTasks - 1 && stepsTaken < portionSize ) - || ( i == nTasks - 1 && targetCursor.hasNext() ) ) - { - stepsTaken++; - - final B b = targetCursor.next(); - sourceRandomAccess.setPosition( targetCursor.getLongPosition( 0 ), dimX ); - sourceRandomAccess.setPosition( targetCursor.getLongPosition( 1 ), dimY ); - - converter.convert( sourceRandomAccess.get(), b ); - } - } - - return null; - } - } ); + tasks.add(() -> { + int i = ai.getAndIncrement(); + + final Cursor< B > targetCursor = target.localizingCursor(); + + // we might need either a cursor or a RandomAccess + final RandomAccess< A > sourceRandomAccess = source.randomAccess(); + sourceRandomAccess.setPosition( position ); + + final Cursor< A > sourceCursor = ii.cursor(); + + // jump to correct starting point + targetCursor.jumpFwd( i * portionSize ); + sourceCursor.jumpFwd( i * portionSize ); + long stepsTaken = 0; + + if ( target.iterationOrder().equals( ii.iterationOrder() ) + && !( sourceCursor instanceof RandomAccessibleIntervalCursor ) ) + { + // either map a portion or (for the last portion) go + // until the end + while ( ( i != nTasks - 1 && stepsTaken < portionSize ) + || ( i == nTasks - 1 && targetCursor.hasNext() ) ) + { + stepsTaken++; + converter.convert( sourceCursor.next(), targetCursor.next() ); + } + } + + else if ( target.iterationOrder() instanceof FlatIterationOrder ) + { + + final long cr = -target.dimension( 0 ); + final long width = target.dimension( 0 ); + final long height = target.dimension( 1 ); + + final long initX = ( i * portionSize ) % width; + final long initY = ( i * portionSize ) / width; + // either map a portion or (for the last portion) go + // until the end + final long endX = ( i == nTasks - 1 ) ? width : ( initX + ( i + 1 ) * portionSize ) % width; + final long endY = ( i == nTasks - 1 ) ? height - 1 + : ( initX + ( i + 1 ) * portionSize ) / width; + + sourceRandomAccess.setPosition( initX, dimX ); + sourceRandomAccess.setPosition( initY, dimY ); + + for ( long y = initY; y <= endY; ++y ) + { + for ( long x = ( y == initY ? initX : 0 ); x < ( y == endY ? endX : width ); ++x ) + { + targetCursor.fwd(); + converter.convert( sourceRandomAccess.get(), targetCursor.get() ); + sourceRandomAccess.fwd( dimX ); + + } + sourceRandomAccess.move( cr, dimX ); + sourceRandomAccess.fwd( dimY ); + } + } + + else + { + // either map a portion or (for the last portion) go + // until the end + while ( ( i != nTasks - 1 && stepsTaken < portionSize ) + || ( i == nTasks - 1 && targetCursor.hasNext() ) ) + { + stepsTaken++; + + final B b = targetCursor.next(); + sourceRandomAccess.setPosition( targetCursor.getLongPosition( 0 ), dimX ); + sourceRandomAccess.setPosition( targetCursor.getLongPosition( 1 ), dimY ); + + converter.convert( sourceRandomAccess.get(), b ); + } + } + + return null; + }); } try From 5fe3b0c265ee73a8cf30d85edf9bdf221c9ada10 Mon Sep 17 00:00:00 2001 From: Gabriel Selzer Date: Tue, 4 Mar 2025 10:48:06 -0600 Subject: [PATCH 11/11] Add migration guide --- MIGRATION.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 MIGRATION.md diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 0000000..1b3fa39 --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,22 @@ +# Migrating from [imglib/imglib2-ij](https://github.com/imglib/imglib2-ij) + +Unfortunately, `imglib/imglib2-ij` cannot be used with Java 11+, because of the package conflicts with `imglib/imglib2`. If you try, you'll see build errors like: +``` +[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project scijava-legacy: Compilation failure: Compilation failure: +[ERROR] error: the unnamed module reads package net.imglib2.img from both net.imglib2 and net.imglib2.img +[ERROR] error: the unnamed module reads package net.imglib2.display.projector from both net.imglib2 and net.imglib2.img +[ERROR] error: module net.imglib2 reads package net.imglib2.img from both net.imglib2 and net.imglib2.img +[ERROR] error: module net.imglib2 reads package net.imglib2.display.projector from both net.imglib2 and net.imglib2.img +[ERROR] error: module org.slf4j reads package net.imglib2.img from both net.imglib2 and net.imglib2.img +[ERROR] error: module org.slf4j reads package net.imglib2.display.projector from both net.imglib2 and net.imglib2.img +``` + +To resolve these errors (and for organization) this library changed many names. Below you'll find commonly-used functions from `imglib/imglib2-ij`, as well as their drop-in replacements from `imglib/imglib2-imagej`: + +**`net.imglib2.img.display.imagej.ImgToVirtualStack.wrap*` have been renamed to `net.imglib2.imagej.ImgPlusToImagePlus.wrap*`**. +**`net.imglib2.img.VirtualStackAdapter.wrap*` have been renamed to `net.imglib2.imagej.ImagePlusToImgPlus.wrap*`**. +**`net.imglib2.img.ImagePlusAdapter.wrap*` have been renamed to `net.imglib2.imagej.ImagePlusToImg.wrap*`**. +**`net.imglib2.img.ImageJFunctions.wrap*(ImagePlus)` have been renamed to `net.imglib2.imagej.ImagePlusToImg.wrap*`**. +**`net.imglib2.img.display.imagej.ImageJFunctions.wrap*(RandomAccessibleInterval, ...)` have been renamed to `net.imglib2.imagej.RAIToImagePlus.wrap*`**. + +If you require additional functionality that is not yet in this library, please file an issue!