Skip to content

Commit baa19e4

Browse files
authored
Merge pull request #7 from imglib/purge-ij2
Purge imagej-common
2 parents 9ed81b1 + 719977c commit baa19e4

29 files changed

+868
-1865
lines changed

MIGRATION.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ Unfortunately, `imglib/imglib2-ij` cannot be used with Java 11+, because of the
1313

1414
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`:
1515

16-
**`net.imglib2.img.display.imagej.ImgToVirtualStack.wrap*` have been renamed to `net.imglib2.imagej.ImgPlusToImagePlus.wrap*`**.
17-
**`net.imglib2.img.VirtualStackAdapter.wrap*` have been renamed to `net.imglib2.imagej.ImagePlusToImgPlus.wrap*`**.
18-
**`net.imglib2.img.ImagePlusAdapter.wrap*` have been renamed to `net.imglib2.imagej.ImagePlusToImg.wrap*`**.
16+
**`net.imglib2.img.display.imagej.ImgToVirtualStack.wrap*` have been renamed to `net.imglib2.imagej.RAIToImagePlus.wrapVirtualStack*`**.
17+
**`net.imglib2.img.VirtualStackAdapter.wrap*` have been renamed to `net.imglib2.imagej.ImagePlusToImg.wrapCached*`**.
18+
**`net.imglib2.img.ImagePlusAdapter.wrap*` have been renamed to `net.imglib2.imagej.ImagePlusToImg.wrapDirect*`**.
1919
**`net.imglib2.img.ImageJFunctions.wrap*(ImagePlus)` have been renamed to `net.imglib2.imagej.ImagePlusToImg.wrap*`**.
2020
**`net.imglib2.img.display.imagej.ImageJFunctions.wrap*(RandomAccessibleInterval, ...)` have been renamed to `net.imglib2.imagej.RAIToImagePlus.wrap*`**.
2121

pom.xml

-4
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,6 @@ Jean-Yves Tinevez and Michael Zinsmaier.</license.copyrightOwners>
185185
<groupId>net.imagej</groupId>
186186
<artifactId>ij</artifactId>
187187
</dependency>
188-
<dependency>
189-
<groupId>net.imagej</groupId>
190-
<artifactId>imagej-common</artifactId>
191-
</dependency>
192188

193189
<!-- Test scope dependencies -->
194190
<dependency>

src/main/java/net/imglib2/imagej/ImagePlusToImg.java

+158-80
Original file line numberDiff line numberDiff line change
@@ -35,25 +35,27 @@
3535
package net.imglib2.imagej;
3636

3737
import ij.ImagePlus;
38-
import net.imglib2.Cursor;
3938
import net.imglib2.cache.Cache;
4039
import net.imglib2.cache.ref.SoftRefLoaderCache;
41-
import net.imglib2.converter.Converter;
42-
import net.imglib2.imagej.imageplus.*;
43-
import net.imglib2.img.Img;
44-
import net.imglib2.img.basictypeaccess.array.ArrayDataAccess;
40+
import net.imglib2.imagej.imageplus.ByteImagePlus;
41+
import net.imglib2.imagej.imageplus.FloatImagePlus;
42+
import net.imglib2.imagej.imageplus.IntImagePlus;
43+
import net.imglib2.imagej.imageplus.ShortImagePlus;
44+
import net.imglib2.img.basictypeaccess.array.*;
4545
import net.imglib2.img.planar.PlanarImg;
46-
import net.imglib2.type.Type;
46+
import net.imglib2.type.NativeType;
47+
import net.imglib2.type.NativeTypeFactory;
4748
import net.imglib2.type.numeric.ARGBType;
48-
import net.imglib2.type.numeric.ComplexType;
4949
import net.imglib2.type.numeric.integer.UnsignedByteType;
50-
import net.imglib2.type.numeric.integer.UnsignedIntType;
5150
import net.imglib2.type.numeric.integer.UnsignedShortType;
5251
import net.imglib2.type.numeric.real.FloatType;
52+
import net.imglib2.util.Fraction;
5353

5454
import java.util.AbstractList;
55+
import java.util.List;
5556
import java.util.concurrent.ExecutionException;
5657
import java.util.function.Function;
58+
import java.util.stream.LongStream;
5759

5860
/**
5961
* Provides convenience functions to wrap ImageJ 1.x data structures as ImgLib2
@@ -63,31 +65,54 @@
6365
* @author Stephan Preibisch
6466
* @author Stephan Saalfeld
6567
* @author Matthias Arzt
68+
* @author Gabriel Selzer
6669
*/
6770
public class ImagePlusToImg
6871
{
6972

70-
public static PlanarImg< ?, ? > wrap( final ImagePlus imp )
73+
/**
74+
* Wraps an {@link ImagePlus} into a {@link PlanarImg}.
75+
* <p>
76+
* Under the hood, each {@link ij.process.ImageProcessor}'s backing array is
77+
* wrapped into an {@link ArrayDataAccess}. The resulting {@link List} of
78+
* {@link ArrayDataAccess}es is used to form a {@link PlanarImg}.
79+
* </p>
80+
*
81+
* @param imp the {@link ImagePlus} to wrap
82+
* @return a {@link PlanarImg} directly wrapping {@code imp}
83+
*/
84+
public static PlanarImg< ?, ? > wrapDirect(final ImagePlus imp )
7185
{
7286
switch ( imp.getType() )
7387
{
7488
case ImagePlus.GRAY8:
75-
return wrapByte( imp );
89+
return wrapByteDirect( imp );
7690
case ImagePlus.GRAY16:
77-
return wrapShort( imp );
91+
return wrapShortDirect( imp );
7892
case ImagePlus.GRAY32:
79-
return wrapFloat( imp );
93+
return wrapFloatDirect( imp );
8094
case ImagePlus.COLOR_RGB:
81-
return wrapRGBA( imp );
95+
return wrapRGBADirect( imp );
8296
default:
8397
throw new RuntimeException( "Only 8, 16, 32-bit and RGB supported!" );
8498
}
8599
}
86100

87-
public static PlanarImg< UnsignedByteType, ? > wrapByte(final ImagePlus imp )
101+
/**
102+
* Wraps an {@link ImagePlus} into a {@link PlanarImg} of unsigned bytes.
103+
* <p>
104+
* Under the hood, each {@link ij.process.ImageProcessor}'s backing array is
105+
* wrapped into an {@link ByteArray}. The resulting {@link List} of
106+
* {@link ArrayDataAccess}es is used to form a {@link PlanarImg}.
107+
* </p>
108+
*
109+
* @param imp the {@link ImagePlus} to wrap
110+
* @return a {@link PlanarImg} of unsigned bytes directly wrapping {@code imp}
111+
*/
112+
public static PlanarImg< UnsignedByteType, ? > wrapByteDirect(final ImagePlus imp )
88113
{
89114
if ( imp.getType() != ImagePlus.GRAY8 )
90-
return null;
115+
throw new IllegalArgumentException(imp + " does not contain unsigned bytes!");
91116

92117
final ByteImagePlus< UnsignedByteType > container = new ByteImagePlus<>( imp );
93118

@@ -100,10 +125,21 @@ public class ImagePlusToImg
100125
return container;
101126
}
102127

103-
public static PlanarImg< UnsignedShortType, ? > wrapShort(final ImagePlus imp )
128+
/**
129+
* Wraps an {@link ImagePlus} into a {@link PlanarImg} of unsigned shorts.
130+
* <p>
131+
* Under the hood, each {@link ij.process.ImageProcessor}'s backing array is
132+
* wrapped into an {@link ShortArray}. The resulting {@link List} of
133+
* {@link ArrayDataAccess}es is used to form a {@link PlanarImg}.
134+
* </p>
135+
*
136+
* @param imp the {@link ImagePlus} to wrap
137+
* @return a {@link PlanarImg} of unsigned shorts directly wrapping {@code imp}
138+
*/
139+
public static PlanarImg< UnsignedShortType, ? > wrapShortDirect(final ImagePlus imp )
104140
{
105141
if ( imp.getType() != ImagePlus.GRAY16 )
106-
return null;
142+
throw new IllegalArgumentException(imp + " does not contain unsigned shorts!");
107143

108144
final ShortImagePlus< UnsignedShortType > container = new ShortImagePlus<>( imp );
109145

@@ -116,26 +152,21 @@ public class ImagePlusToImg
116152
return container;
117153
}
118154

119-
public static PlanarImg< UnsignedIntType, ? > wrapInt(final ImagePlus imp )
120-
{
121-
if( imp.getType() != ImagePlus.COLOR_RGB )
122-
return null;
123-
124-
final IntImagePlus< UnsignedIntType > container = new IntImagePlus<>( imp );
125-
126-
// create a Type that is linked to the container
127-
final UnsignedIntType linkedType = new UnsignedIntType( container );
128-
129-
// pass it to the DirectAccessContainer
130-
container.setLinkedType( linkedType );
131-
132-
return container;
133-
}
134-
135-
public static PlanarImg< ARGBType, ? > wrapRGBA( final ImagePlus imp )
155+
/**
156+
* Wraps an {@link ImagePlus} into a {@link PlanarImg} of RGBA tuples.
157+
* <p>
158+
* Under the hood, each {@link ij.process.ImageProcessor}'s backing array is
159+
* wrapped into an {@link IntArray}. The resulting {@link List} of
160+
* {@link ArrayDataAccess}es is used to form a {@link PlanarImg}.
161+
* </p>
162+
*
163+
* @param imp the {@link ImagePlus} to wrap
164+
* @return a {@link PlanarImg} of ARGB tuples directly wrapping {@code imp}
165+
*/
166+
public static PlanarImg< ARGBType, ? > wrapRGBADirect(final ImagePlus imp )
136167
{
137168
if ( imp.getType() != ImagePlus.COLOR_RGB )
138-
return null;
169+
throw new IllegalArgumentException(imp + " does not contain RGB tuples!");
139170

140171
final IntImagePlus< ARGBType > container = new IntImagePlus<>( imp );
141172

@@ -148,10 +179,21 @@ public class ImagePlusToImg
148179
return container;
149180
}
150181

151-
public static PlanarImg< FloatType, ? > wrapFloat(final ImagePlus imp )
182+
/**
183+
* Wraps an {@link ImagePlus} into a {@link PlanarImg} of floats.
184+
* <p>
185+
* Under the hood, each {@link ij.process.ImageProcessor}'s backing array is
186+
* wrapped into an {@link FloatArray}. The resulting {@link List} of
187+
* {@link ArrayDataAccess}es is used to form a {@link PlanarImg}.
188+
* </p>
189+
*
190+
* @param imp the {@link ImagePlus} to wrap
191+
* @return a {@link PlanarImg} of floats directly wrapping {@code imp}
192+
*/
193+
public static PlanarImg< FloatType, ? > wrapFloatDirect(final ImagePlus imp )
152194
{
153195
if ( imp.getType() != ImagePlus.GRAY32 )
154-
return null;
196+
throw new IllegalArgumentException(imp + " does not contain floats!");
155197

156198
final FloatImagePlus< FloatType > container = new FloatImagePlus<>( imp );
157199

@@ -164,61 +206,99 @@ public class ImagePlusToImg
164206
return container;
165207
}
166208

167-
public static PlanarImg< FloatType, ? > convertFloat( final ImagePlus imp )
209+
/**
210+
* Wraps an 8 bit {@link ImagePlus}, into an {@link PlanarImg}, that is backed
211+
* by a {@link PlanarImg}. The {@link PlanarImg} loads the planes only if
212+
* needed, and caches them.
213+
* @param image the {@link ImagePlus} to wrap. Must contain unsigned bytes.
214+
* @return a {@link PlanarImg} wrapping {@code image}.
215+
*/
216+
public static PlanarImg< UnsignedByteType, ByteArray > wrapByteCached(final ImagePlus image )
168217
{
169-
170-
switch ( imp.getType() )
171-
{
172-
case ImagePlus.GRAY8:
173-
return convertToFloat( wrapByte( imp ), new NumberToFloatConverter< UnsignedByteType >() );
174-
case ImagePlus.GRAY16:
175-
return convertToFloat( wrapShort( imp ), new NumberToFloatConverter< UnsignedShortType >() );
176-
case ImagePlus.GRAY32:
177-
return wrapFloat( imp );
178-
case ImagePlus.COLOR_RGB:
179-
return convertToFloat( wrapRGBA( imp ), new ARGBtoFloatConverter() );
180-
default:
181-
throw new RuntimeException( "Only 8, 16, 32-bit and RGB supported!" );
182-
}
218+
return internWrap( image, ImagePlus.GRAY8, new UnsignedByteType(), array -> new ByteArray( ( byte[] ) array ) );
183219
}
184220

185-
static private class ARGBtoFloatConverter implements Converter< ARGBType, FloatType >
221+
/**
222+
* Wraps a 16 bit {@link ImagePlus}, into an {@link PlanarImg}, that is backed
223+
* by a {@link PlanarImg}. The {@link PlanarImg} loads the planes only if
224+
* needed, and caches them.
225+
* @param image the {@link ImagePlus} to wrap. Must contain unsigned shorts.
226+
* @return a {@link PlanarImg} wrapping {@code image}.
227+
*/
228+
public static PlanarImg< UnsignedShortType, ShortArray > wrapShortCached(final ImagePlus image )
186229
{
187-
/** Luminance times alpha. */
188-
@Override
189-
public void convert( final ARGBType input, final FloatType output )
190-
{
191-
final int v = input.get();
192-
output.setReal( ( ( v >> 24 ) & 0xff ) * ( ( ( v >> 16 ) & 0xff ) * 0.299 + ( ( v >> 8 ) & 0xff ) * 0.587 + ( v & 0xff ) * 0.144 ) );
193-
}
230+
return internWrap( image, ImagePlus.GRAY16, new UnsignedShortType(), array -> new ShortArray( ( short[] ) array ) );
194231
}
195232

196-
static private class NumberToFloatConverter< T extends ComplexType< T > > implements Converter< T, FloatType >
233+
/**
234+
* Wraps a 32 bit {@link ImagePlus}, into an {@link PlanarImg}, that is backed
235+
* by a {@link PlanarImg}. The {@link PlanarImg} loads the planes only if
236+
* needed, and caches them.
237+
* @param image the {@link ImagePlus} to wrap. Must contain floats.
238+
* @return a {@link PlanarImg} wrapping {@code image}.
239+
*/
240+
public static PlanarImg< FloatType, FloatArray > wrapFloatCached(final ImagePlus image )
197241
{
198-
@Override
199-
public void convert( final T input, final FloatType output )
200-
{
201-
output.setReal( input.getRealFloat() );
202-
}
242+
return internWrap( image, ImagePlus.GRAY32, new FloatType(), array -> new FloatArray( ( float[] ) array ) );
203243
}
204244

205-
protected static < T extends Type< T > > PlanarImg< FloatType, ?> convertToFloat(
206-
final Img< T > input, final Converter< T, FloatType > c )
245+
/**
246+
* Wraps a 24 bit {@link ImagePlus}, into an {@link PlanarImg}, that is backed
247+
* by a {@link PlanarImg}. The {@link PlanarImg} loads the planes only if
248+
* needed, and caches them.
249+
* @param image the {@link ImagePlus} to wrap. Must contain RGB tuples.
250+
* @return a {@link PlanarImg} wrapping {@code image}.
251+
*/
252+
public static PlanarImg< ARGBType, IntArray > wrapRGBACached(final ImagePlus image )
207253
{
208-
final ImagePlusImg< FloatType, ? > output = new ImagePlusImgFactory<>( new FloatType() ).create( input );
209-
210-
final Cursor< T > in = input.cursor();
211-
final Cursor< FloatType > out = output.cursor();
254+
return internWrap( image, ImagePlus.COLOR_RGB, new ARGBType(), array -> new IntArray( ( int[] ) array ) );
255+
}
212256

213-
while ( in.hasNext() )
257+
/**
258+
* Wraps an {@link ImagePlus}, into an {@link PlanarImg}, that is backed by a
259+
* {@link PlanarImg}. The {@link PlanarImg} loads the planes only if needed,
260+
* and caches them. The pixel type of the returned image depends on the type
261+
* of the ImagePlus.
262+
* @param image the {@link ImagePlus} to wrap
263+
* @return a {@link PlanarImg} wrapping {@code image}.
264+
*/
265+
public static PlanarImg< ?, ? > wrapCached(final ImagePlus image )
266+
{
267+
switch ( image.getType() )
214268
{
215-
in.fwd();
216-
out.fwd();
217-
218-
c.convert( in.get(), out.get() );
269+
case ImagePlus.GRAY8:
270+
return wrapByteCached( image );
271+
case ImagePlus.GRAY16:
272+
return wrapShortCached( image );
273+
case ImagePlus.GRAY32:
274+
return wrapFloatCached( image );
275+
case ImagePlus.COLOR_RGB:
276+
return wrapRGBACached( image );
219277
}
278+
throw new RuntimeException( "Only 8, 16, 32-bit and RGB supported!" );
279+
}
220280

221-
return output;
281+
private static < T extends NativeType< T >, A extends ArrayDataAccess< A > > PlanarImg< T, A > internWrap(
282+
final ImagePlus image,
283+
final int expectedType,
284+
final T type,
285+
final Function< Object, A > createArrayAccess
286+
) {
287+
if ( image.getType() != expectedType )
288+
throw new IllegalArgumentException();
289+
final ImagePlusLoader< A > loader = new ImagePlusLoader<>( image, createArrayAccess );
290+
final long[] dimensions = getNonTrivialDimensions( image );
291+
final PlanarImg< T, A > cached = new PlanarImg<>( loader, dimensions, new Fraction() );
292+
cached.setLinkedType( ( (NativeTypeFactory< T, A >) type.getNativeTypeFactory() ).createLinkedType( cached ) );
293+
// TODO: Preserve metadata
294+
return cached;
295+
}
296+
297+
private static long[] getNonTrivialDimensions(final ImagePlus image )
298+
{
299+
final LongStream xy = LongStream.of( image.getWidth(), image.getHeight() );
300+
final LongStream czt = LongStream.of( image.getNChannels(), image.getNSlices(), image.getNFrames() );
301+
return LongStream.concat( xy, czt.filter( x -> x > 1 ) ).toArray();
222302
}
223303

224304
private static class ImagePlusLoader< A extends ArrayDataAccess< A >> extends AbstractList< A >
@@ -260,6 +340,4 @@ public int size()
260340
return image.getStackSize();
261341
}
262342
}
263-
264-
//
265343
}

0 commit comments

Comments
 (0)