diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 46fcfdc..e643bf8 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -19,7 +19,7 @@ jobs:
- name: Set up Java
uses: actions/setup-java@v3
with:
- java-version: '8'
+ java-version: '11'
distribution: 'zulu'
cache: 'maven'
- name: Set up CI environment
diff --git a/pom.xml b/pom.xml
index 7f41cb7..8fdfbeb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -159,6 +159,21 @@ Jean-Yves Tinevez and Michael Zinsmaier.
sign,deploy-to-scijava
+
+
+ [11.0.17,)
+ 11
@@ -192,12 +207,6 @@ Jean-Yves Tinevez and Michael Zinsmaier.
junit
test
-
- net.imglib2
- imglib2
- tests
- test
-
org.openjdk.jmh
jmh-core
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
new file mode 100644
index 0000000..4a6b149
--- /dev/null
+++ b/src/main/java/module-info.java
@@ -0,0 +1,7 @@
+module net.imglib2.imagej {
+ requires net.imglib2;
+ requires ij;
+ requires net.imglib2.cache;
+ requires java.desktop;
+ exports net.imglib2.imagej;
+}
\ No newline at end of file
diff --git a/src/test/java/net/imglib2/imagej/imageplus/ImagePlusImgTest.java b/src/test/java/net/imglib2/imagej/imageplus/ImagePlusImgTest.java
index b90cfab..86f3d66 100644
--- a/src/test/java/net/imglib2/imagej/imageplus/ImagePlusImgTest.java
+++ b/src/test/java/net/imglib2/imagej/imageplus/ImagePlusImgTest.java
@@ -38,7 +38,6 @@
import net.imglib2.img.array.ArrayImgFactory;
import net.imglib2.type.numeric.real.FloatType;
-import net.imglib2.util.ImgTestHelper;
import net.imglib2.util.Util;
import org.junit.Test;
diff --git a/src/test/java/net/imglib2/imagej/imageplus/ImgTestHelper.java b/src/test/java/net/imglib2/imagej/imageplus/ImgTestHelper.java
new file mode 100644
index 0000000..bf26b28
--- /dev/null
+++ b/src/test/java/net/imglib2/imagej/imageplus/ImgTestHelper.java
@@ -0,0 +1,283 @@
+/*
+ * #%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.Random;
+import java.util.function.Function;
+
+import net.imglib2.exception.InvalidDimensionsException;
+import net.imglib2.util.Util;
+import org.junit.Assert;
+import net.imglib2.Cursor;
+import net.imglib2.RandomAccess;
+import net.imglib2.img.Img;
+import net.imglib2.img.ImgFactory;
+import net.imglib2.outofbounds.OutOfBoundsPeriodicFactory;
+import net.imglib2.type.numeric.real.FloatType;
+import net.imglib2.view.ExtendedRandomAccessibleInterval;
+
+/**
+ * Helper class for {@link Img} subclass unit tests.
+ *
+ * @author Stephan Preibisch
+ * @author Stephan Saalfeld
+ * @author Curtis Rueden
+ * @author Philipp Hanslovsky
+ */
+public class ImgTestHelper
+{
+ // which dimensions to test
+ private static final long[][] DIM =
+ new long[][] {
+ { 127 },
+ { 288 },
+ { 135, 111 },
+ { 172, 131 },
+ { 15, 13, 33 },
+ { 110, 38, 30 },
+ { 109, 34, 111 },
+ { 12, 43, 92, 10 },
+ { 21, 34, 29, 13 },
+ { 5, 12, 30, 4, 21 },
+ { 14, 21, 13, 9, 12 }
+ };
+
+ public static long[][] dims()
+ {
+ return DIM.clone();
+ }
+
+ private static final long[][] INVALID_DIM = {
+ { -127 },
+ { 0 },
+ { -1, 0 },
+ { -1, 1 },
+ { -3, -2 },
+ { 0, 0, 0 },
+ { -1, 2, 3 },
+ { 4, -2, 100 },
+ { 3151, -235, 8341 },
+ { 34, 5135, 35163, 0 },
+ { 35135, 3531, -2, 1 },
+ };
+
+ public static void assertInvalidDims( final ImgFactory< ? > factory )
+ {
+ assertInvalidDims( factory::create );
+ }
+
+ public static void assertInvalidDims( final Function< long[], Img< ? > > factory )
+ {
+ for ( final long[] dims : INVALID_DIM )
+ assertInvalidDims( dims, factory );
+ }
+
+ private static void assertInvalidDims( final long[] dims, final Function< long[], Img< ? > > factory )
+ {
+ try
+ {
+ factory.apply( dims );
+ }
+ catch ( final InvalidDimensionsException exception )
+ {
+ Assert.assertArrayEquals( dims, exception.getDimenionsCopy() );
+ return;
+ }
+ catch ( final Throwable exception )
+ {
+
+ Assert.fail( String.format(
+ "Expected exception of type %s but %s was thrown.",
+ InvalidDimensionsException.class.getName(),
+ exception.getClass().getName() ) );
+ }
+
+ Assert.fail( String.format(
+ "Expected exception of type %s but no exception was thrown.",
+ InvalidDimensionsException.class.getName() ) );
+ }
+
+ public static boolean testImg( final long[] size, final ImgFactory< FloatType > factory1, final ImgFactory< FloatType > factory2 )
+ {
+ // create the image
+ final Img< FloatType > img1 = factory1.create( size );
+ final Img< FloatType > img2 = factory2.create( size );
+
+ final int numDimensions = img1.numDimensions();
+
+ // get a reference to compare to
+ final float[] reference = createReference( img1 );
+
+ // copy into a second image using simple cursors
+ final Cursor< FloatType > cursor1 = img1.cursor();
+ final Cursor< FloatType > cursor2 = img2.cursor();
+
+ while ( cursor1.hasNext() )
+ {
+ cursor1.fwd();
+ cursor2.fwd();
+
+ cursor2.get().set( cursor1.get() );
+ }
+
+ cursor1.reset();
+ cursor2.reset();
+
+ // and copy right back
+ while ( cursor2.hasNext() )
+ {
+ cursor1.fwd();
+ cursor2.fwd();
+
+ cursor1.get().set( cursor2.get() );
+ }
+
+ // copy back into a second image using localizable and positionable
+ // cursors
+ final Cursor< FloatType > localizableCursor1 = img1.localizingCursor();
+ final RandomAccess< FloatType > positionable2 = img2.randomAccess();
+
+ int i = 0;
+
+ while ( localizableCursor1.hasNext() )
+ {
+ localizableCursor1.fwd();
+ ++i;
+
+ if ( i % 2 == 0 )
+ positionable2.setPosition( localizableCursor1 );
+ else
+ positionable2.setPosition( localizableCursor1 );
+
+ final FloatType t2 = positionable2.get();
+ final FloatType t1 = localizableCursor1.get();
+// float f1 = t1.getRealFloat();
+// float f2 = t2.getRealFloat();
+ t2.set( t1 );
+// positionable2.get().set( localizableCursor1.get() );
+ }
+
+ // copy again to the first image using a LocalizableByDimOutsideCursor
+ // and a LocalizableByDimCursor
+ final ExtendedRandomAccessibleInterval< FloatType, Img< FloatType > > extendedImg2 = new ExtendedRandomAccessibleInterval< FloatType, Img< FloatType > >( img2, new OutOfBoundsPeriodicFactory< FloatType, Img< FloatType > >() );
+ final RandomAccess< FloatType > outsideCursor2 = extendedImg2.randomAccess();
+ localizableCursor1.reset();
+
+ final int[] pos = new int[ numDimensions ];
+ i = 0;
+ int direction = 1;
+
+ try
+ {
+ while ( localizableCursor1.hasNext() )
+ {
+ localizableCursor1.fwd();
+ localizableCursor1.localize( pos );
+ ++i;
+
+ // how many times far away from the original image do we grab
+ // the pixel
+ final int distance = i % 5;
+ direction *= -1;
+
+ pos[ i % numDimensions ] += img1.dimension( i % numDimensions ) * distance * direction;
+
+ if ( i % 7 == 0 )
+ outsideCursor2.setPosition( pos );
+ else
+ outsideCursor2.setPosition( pos );
+
+ final FloatType t1 = localizableCursor1.get();
+ final FloatType t2 = outsideCursor2.get();
+
+// final float f1 = t1.getRealFloat();
+// final float f2 = t2.getRealFloat();
+
+ t1.set( t2 );
+
+ }
+ }
+ catch ( final ArrayIndexOutOfBoundsException e )
+ {
+ System.err.println( ( i % 7 == 0 ? "setPosition() " : "moveTo() " ) + Util.printCoordinates( pos ) );
+ e.printStackTrace();
+ System.exit( 1 );
+ }
+
+ final boolean success = test( img1, reference );
+
+ return success;
+ }
+
+ private static float[] createReference( final Img< FloatType > img )
+ {
+ // use a random number generator
+ final Random rnd = new Random( 1241234 );
+
+ // create reference array
+ final float[] reference = new float[ ( int ) img.size() ];
+
+ // iterate over image and reference array and fill with data
+ final Cursor< FloatType > cursor = img.cursor();
+ int i = 0;
+
+ while ( cursor.hasNext() )
+ {
+ cursor.fwd();
+
+ final float value = rnd.nextFloat();
+ reference[ i++ ] = value;
+ cursor.get().set( value );
+ }
+
+ return reference;
+ }
+
+ private static boolean test( final Img< FloatType > img, final float[] reference )
+ {
+ boolean allEqual = true;
+
+ final Cursor< FloatType > cursor = img.cursor();
+ int i = 0;
+
+ while ( cursor.hasNext() )
+ {
+ cursor.fwd();
+ allEqual &= cursor.get().get() == reference[ i++ ];
+ }
+
+ return allEqual;
+ }
+}