diff --git a/src/main/java/bdv/ij/OpenImagePlusPlugIn.java b/src/main/java/bdv/ij/OpenImagePlusPlugIn.java
index 8d8bdfa39cb00a2e076745f85a3d227a95622e52..6e29dbaf521b9948bab78ecb0e017a307443fe81 100644
--- a/src/main/java/bdv/ij/OpenImagePlusPlugIn.java
+++ b/src/main/java/bdv/ij/OpenImagePlusPlugIn.java
@@ -56,21 +56,8 @@ public class OpenImagePlusPlugIn implements Command
 	{
 		System.setProperty( "apple.laf.useScreenMenuBar", "true" );
 		new ImageJ();
-
-
-//		IJ.run("Confocal Series (2.2MB)");
-//		IJ.run("Confocal Series (2.2MB)");
-//		IJ.run("Fly Brain (1MB)");
-		
-//		ImagePlus ip1 = IJ.openImage("/groups/saalfeld/home/bogovicj/tmp/mri-stack.tif");
-//		ImagePlus ip2 = IJ.openImage("/groups/saalfeld/home/bogovicj/tmp/flybrain.tif");
-		
-		ImagePlus ip1 = IJ.openImage("/groups/saalfeld/home/bogovicj/tmp/confocal-series.tif");
-		ImagePlus ip2 = IJ.openImage("/groups/saalfeld/home/bogovicj/tmp/confocal_grad.tif");
-
-		ip1.show();
-		ip2.show();
-
+		IJ.run( "Confocal Series (2.2MB)" );
+//		IJ.run( "Fly Brain (1MB)" );
 		new OpenImagePlusPlugIn().run();
 	}
 
@@ -109,17 +96,19 @@ public class OpenImagePlusPlugIn implements Command
 		AbstractSpimData< ? > spimData;
 		CacheControl cache = null;
 		int setup_id_offset = 0;
+		ArrayList<ImagePlus> imgList = new ArrayList<ImagePlus>();
 		for( int i = 0; i < nImages; i++ )
 		{
 			if( !gd.getNextBoolean() )
 				continue;
 
 			ImagePlus imp = WindowManager.getImage( idList[ i ]);
+			imgList.add( imp );
 			spimData = load( imp, converterSetups, sources, setup_id_offset );
 			if( spimData != null )
 				cache = ( ( ViewerImgLoader ) spimData.getSequenceDescription().getImgLoader() ).getCacheControl();
 			
-			setup_id_offset += imp.getChannel();
+			setup_id_offset += imp.getNChannels();
 		}
 
 		int nTimepoints = 1;
@@ -131,17 +120,15 @@ public class OpenImagePlusPlugIn implements Command
 		final VisibilityAndGrouping vg = bdv.getViewer().getVisibilityAndGrouping();
 		vg.setFusedEnabled( true );
 
-		int channel_offset = 0;
-		for( int i = 0; i < nImages; i++ )
+		int channelOffset = 0;
+		for( ImagePlus imp : imgList )
 		{
-			ImagePlus imp = WindowManager.getImage( idList[ i ]);
 			if ( imp.isComposite() )
-			{
-				transferChannelSettings( channel_offset, ( CompositeImage ) imp, sa, vg );
-				channel_offset += imp.getNChannels();
-			}
+				transferChannelSettings( channelOffset, ( CompositeImage ) imp, sa, vg );
 			else
-				transferImpSettings( imp, sa );
+				transferImpSettings( channelOffset, imp, sa );
+
+			channelOffset += imp.getNChannels();
 		}
 	}
 
@@ -184,9 +171,6 @@ public class OpenImagePlusPlugIn implements Command
 		// propose reasonable mipmap settings
 //		final ExportMipmapInfo autoMipmapSettings = ProposeMipmaps.proposeMipmaps( new BasicViewSetup( 0, "", size, voxelSize ) );
 
-//		imp.getDisplayRangeMin();
-//		imp.getDisplayRangeMax();
-
 		// create ImgLoader wrapping the image
 		final BasicImgLoader imgLoader;
 		if ( imp.getStack().isVirtual() )
@@ -194,17 +178,17 @@ public class OpenImagePlusPlugIn implements Command
 			switch ( imp.getType() )
 			{
 			case ImagePlus.GRAY8:
-				imgLoader = VirtualStackImageLoader.createUnsignedByteInstance( imp );
+				imgLoader = VirtualStackImageLoader.createUnsignedByteInstance( imp, setup_id_offset );
 				break;
 			case ImagePlus.GRAY16:
-				imgLoader = VirtualStackImageLoader.createUnsignedShortInstance( imp );
+				imgLoader = VirtualStackImageLoader.createUnsignedShortInstance( imp, setup_id_offset );
 				break;
 			case ImagePlus.GRAY32:
-				imgLoader = VirtualStackImageLoader.createFloatInstance( imp );
+				imgLoader = VirtualStackImageLoader.createFloatInstance( imp, setup_id_offset );
 				break;
 			case ImagePlus.COLOR_RGB:
 			default:
-				imgLoader = VirtualStackImageLoader.createARGBInstance( imp );
+				imgLoader = VirtualStackImageLoader.createARGBInstance( imp, setup_id_offset );
 				break;
 			}
 		}
@@ -213,17 +197,17 @@ public class OpenImagePlusPlugIn implements Command
 			switch ( imp.getType() )
 			{
 			case ImagePlus.GRAY8:
-				imgLoader = ImageStackImageLoader.createUnsignedByteInstance( imp );
+				imgLoader = ImageStackImageLoader.createUnsignedByteInstance( imp, setup_id_offset );
 				break;
 			case ImagePlus.GRAY16:
-				imgLoader = ImageStackImageLoader.createUnsignedShortInstance( imp );
+				imgLoader = ImageStackImageLoader.createUnsignedShortInstance( imp, setup_id_offset );
 				break;
 			case ImagePlus.GRAY32:
-				imgLoader = ImageStackImageLoader.createFloatInstance( imp );
+				imgLoader = ImageStackImageLoader.createFloatInstance( imp, setup_id_offset );
 				break;
 			case ImagePlus.COLOR_RGB:
 			default:
-				imgLoader = ImageStackImageLoader.createARGBInstance( imp );
+				imgLoader = ImageStackImageLoader.createARGBInstance( imp, setup_id_offset );
 				break;
 			}
 		}
@@ -235,9 +219,9 @@ public class OpenImagePlusPlugIn implements Command
 		final HashMap< Integer, BasicViewSetup > setups = new HashMap<>( numSetups );
 		for ( int s = 0; s < numSetups; ++s )
 		{
-			final BasicViewSetup setup = new BasicViewSetup( s, String.format( imp.getTitle() + " channel %d", s + 1 ), size, voxelSize );
-			setup.setAttribute( new Channel( setup_id_offset + s + 1 ) );
-			setups.put( s, setup );
+			final BasicViewSetup setup = new BasicViewSetup( setup_id_offset + s, String.format( imp.getTitle() + " channel %d", s + 1 ), size, voxelSize );
+			setup.setAttribute( new Channel( s + 1 ) );
+			setups.put( setup_id_offset + s, setup );
 		}
 
 		// create timepoints
@@ -252,7 +236,7 @@ public class OpenImagePlusPlugIn implements Command
 		final ArrayList< ViewRegistration > registrations = new ArrayList<>();
 		for ( int t = 0; t < numTimepoints; ++t )
 			for ( int s = 0; s < numSetups; ++s )
-				registrations.add( new ViewRegistration( t, s, sourceTransform ) );
+				registrations.add( new ViewRegistration( t, setup_id_offset + s, sourceTransform ) );
 
 		final File basePath = new File(".");
 		final AbstractSpimData< ? > spimData = new SpimDataMinimal( basePath, seq, new ViewRegistrations( registrations ) );
@@ -262,7 +246,7 @@ public class OpenImagePlusPlugIn implements Command
 		return spimData;
 	}
 
-	protected void transferChannelSettings( int channel_offset, final CompositeImage ci, final SetupAssignments setupAssignments, final VisibilityAndGrouping visibility )
+	protected void transferChannelSettings( int channelOffset, final CompositeImage ci, final SetupAssignments setupAssignments, final VisibilityAndGrouping visibility )
 	{
 		final int nChannels = ci.getNChannels();
 		final int mode = ci.getCompositeMode();
@@ -270,7 +254,7 @@ public class OpenImagePlusPlugIn implements Command
 		for ( int c = 0; c < nChannels; ++c )
 		{
 			final LUT lut = ci.getChannelLut( c + 1 );
-			final ConverterSetup setup = setupAssignments.getConverterSetups().get( channel_offset + c );
+			final ConverterSetup setup = setupAssignments.getConverterSetups().get( channelOffset + c );
 			if ( transferColor )
 				setup.setColor( new ARGBType( lut.getRGB( 255 ) ) );
 			setup.setDisplayRange( lut.min, lut.max );
@@ -286,9 +270,9 @@ public class OpenImagePlusPlugIn implements Command
 		visibility.setCurrentSource( ci.getChannel() - 1 );
 	}
 
-	protected void transferImpSettings( final ImagePlus imp, final SetupAssignments setupAssignments )
+	protected void transferImpSettings( int setupIndex, final ImagePlus imp, final SetupAssignments setupAssignments )
 	{
-		final ConverterSetup setup = setupAssignments.getConverterSetups().get( 0 );
+		final ConverterSetup setup = setupAssignments.getConverterSetups().get( setupIndex );
 		setup.setDisplayRange( imp.getDisplayRangeMin(), imp.getDisplayRangeMax() );
 	}
 }
diff --git a/src/main/java/bdv/img/imagestack/ImageStackImageLoader.java b/src/main/java/bdv/img/imagestack/ImageStackImageLoader.java
index d3f3eeda0ac51fa5fb73ef05003d98d9c1f39e4f..f5f6528073839557d562b824a89880113c8d3edb 100644
--- a/src/main/java/bdv/img/imagestack/ImageStackImageLoader.java
+++ b/src/main/java/bdv/img/imagestack/ImageStackImageLoader.java
@@ -1,6 +1,7 @@
 package bdv.img.imagestack;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.function.Function;
 
 import net.imglib2.RandomAccessibleInterval;
@@ -28,22 +29,42 @@ public class ImageStackImageLoader< T extends NumericType< T > & NativeType< T >
 {
 	public static ImageStackImageLoader< UnsignedByteType, ByteArray > createUnsignedByteInstance( final ImagePlus imp )
 	{
-		return new ImageStackImageLoader<>( new UnsignedByteType(), imp, array -> new ByteArray( ( byte[] ) array ) );
+		return createUnsignedByteInstance( imp, 0 );
+	}
+
+	public static ImageStackImageLoader< UnsignedByteType, ByteArray > createUnsignedByteInstance( final ImagePlus imp, int offset )
+	{
+		return new ImageStackImageLoader<>( new UnsignedByteType(), imp, array -> new ByteArray( ( byte[] ) array ), offset );
 	}
 
 	public static ImageStackImageLoader< UnsignedShortType, ShortArray > createUnsignedShortInstance( final ImagePlus imp )
 	{
-		return new ImageStackImageLoader<>( new UnsignedShortType(), imp, array -> new ShortArray( ( short[] ) array ) );
+		return createUnsignedShortInstance( imp, 0 );
+	}
+
+	public static ImageStackImageLoader< UnsignedShortType, ShortArray > createUnsignedShortInstance( final ImagePlus imp, int offset )
+	{
+		return new ImageStackImageLoader<>( new UnsignedShortType(), imp, array -> new ShortArray( ( short[] ) array ), offset );
 	}
 
 	public static ImageStackImageLoader< FloatType, FloatArray > createFloatInstance( final ImagePlus imp )
 	{
-		return new ImageStackImageLoader<>( new FloatType(), imp, array -> new FloatArray( ( float[] ) array ) );
+		return createFloatInstance( imp, 0 );
+	}
+
+	public static ImageStackImageLoader< FloatType, FloatArray > createFloatInstance( final ImagePlus imp, int offset )
+	{
+		return new ImageStackImageLoader<>( new FloatType(), imp, array -> new FloatArray( ( float[] ) array ), offset );
 	}
 
 	public static ImageStackImageLoader< ARGBType, IntArray > createARGBInstance( final ImagePlus imp )
 	{
-		return new ImageStackImageLoader<>( new ARGBType(), imp, array -> new IntArray( ( int[] ) array ) );
+		return createARGBInstance( imp, 0 );
+	}
+
+	public static ImageStackImageLoader< ARGBType, IntArray > createARGBInstance( final ImagePlus imp, int offset )
+	{
+		return new ImageStackImageLoader<>( new ARGBType(), imp, array -> new IntArray( ( int[] ) array ), offset );
 	}
 
 	private final T type;
@@ -52,35 +73,39 @@ public class ImageStackImageLoader< T extends NumericType< T > & NativeType< T >
 
 	private final long[] dim;
 
-	private final ArrayList< SetupImgLoader > setupImgLoaders;
+	private final HashMap< Integer, SetupImgLoader > setupImgLoaders;
 
 	private final Function< Object, A > wrapPixels;
 
-	public ImageStackImageLoader( final T type, final ImagePlus imp, final Function< Object, A > wrapPixels )
+	public ImageStackImageLoader( final T type, final ImagePlus imp, final Function< Object, A > wrapPixels, int setup_id_offset )
 	{
 		this.type = type;
 		this.imp = imp;
 		this.wrapPixels = wrapPixels;
 		this.dim = new long[] { imp.getWidth(), imp.getHeight(), imp.getNSlices() };
 		final int numSetups = imp.getNChannels();
-		setupImgLoaders = new ArrayList<>();
-		for ( int setupId = 0; setupId < numSetups; ++setupId )
-			setupImgLoaders.add( new SetupImgLoader( setupId ) );
+		setupImgLoaders = new HashMap<>();
+		for ( int c = 0; c < numSetups; ++c )
+			setupImgLoaders.put( (setup_id_offset  + c), new SetupImgLoader( c ) );
+	}
+
+	public ImageStackImageLoader( final T type, final ImagePlus imp, final Function< Object, A > wrapPixels )
+	{
+		this( type, imp, wrapPixels, 0 );
 	}
 
 	public class SetupImgLoader implements BasicSetupImgLoader< T >
 	{
-		private final int setupId;
+		private final int channel;
 
-		public SetupImgLoader( final int setupId )
+		public SetupImgLoader( final int channel )
 		{
-			this.setupId = setupId;
+			this.channel = channel + 1;
 		}
 
 		@Override
 		public RandomAccessibleInterval< T > getImage( final int timepointId, final ImgLoaderHint... hints )
 		{
-			final int channel = setupId + 1;
 			final int frame = timepointId + 1;
 			final ArrayList< A > slices = new ArrayList<>();
 			for ( int slice = 1; slice <= dim[ 2 ]; ++slice )
diff --git a/src/main/java/bdv/img/virtualstack/VirtualStackImageLoader.java b/src/main/java/bdv/img/virtualstack/VirtualStackImageLoader.java
index 30e06c216326e6ca9e3010fad389ed9fa371499f..cf73f1ecbea142c2f7cfca007ed26e4121ab1cad 100644
--- a/src/main/java/bdv/img/virtualstack/VirtualStackImageLoader.java
+++ b/src/main/java/bdv/img/virtualstack/VirtualStackImageLoader.java
@@ -1,6 +1,7 @@
 package bdv.img.virtualstack;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 
 import bdv.AbstractViewerSetupImgLoader;
 import bdv.ViewerImgLoader;
@@ -62,9 +63,14 @@ public abstract class VirtualStackImageLoader< T extends NativeType< T >, V exte
 		implements ViewerImgLoader, TypedBasicImgLoader< T >
 {
 	public static VirtualStackImageLoader< FloatType, VolatileFloatType, VolatileFloatArray > createFloatInstance( final ImagePlus imp )
+	{
+		return createFloatInstance( imp, 0 );
+	}
+
+	public static VirtualStackImageLoader< FloatType, VolatileFloatType, VolatileFloatArray > createFloatInstance( final ImagePlus imp, final int offset )
 	{
 		return new VirtualStackImageLoader< FloatType, VolatileFloatType, VolatileFloatArray >(
-				imp, new VirtualStackVolatileFloatArrayLoader( imp ), new FloatType(), new VolatileFloatType() )
+				imp, new VirtualStackVolatileFloatArrayLoader( imp ), new FloatType(), new VolatileFloatType(), offset )
 		{
 			@Override
 			protected void linkType( final CachedCellImg< FloatType, VolatileFloatArray > img )
@@ -81,9 +87,14 @@ public abstract class VirtualStackImageLoader< T extends NativeType< T >, V exte
 	}
 
 	public static VirtualStackImageLoader< UnsignedShortType, VolatileUnsignedShortType, VolatileShortArray > createUnsignedShortInstance( final ImagePlus imp )
+	{
+		return createUnsignedShortInstance( imp, 0 );
+	}
+
+	public static VirtualStackImageLoader< UnsignedShortType, VolatileUnsignedShortType, VolatileShortArray > createUnsignedShortInstance( final ImagePlus imp, final int offset )
 	{
 		return new VirtualStackImageLoader< UnsignedShortType, VolatileUnsignedShortType, VolatileShortArray >(
-				imp, new VirtualStackVolatileShortArrayLoader( imp ), new UnsignedShortType(), new VolatileUnsignedShortType() )
+				imp, new VirtualStackVolatileShortArrayLoader( imp ), new UnsignedShortType(), new VolatileUnsignedShortType(), offset )
 		{
 			@Override
 			protected void linkType( final CachedCellImg< UnsignedShortType, VolatileShortArray > img )
@@ -100,9 +111,14 @@ public abstract class VirtualStackImageLoader< T extends NativeType< T >, V exte
 	}
 
 	public static VirtualStackImageLoader< UnsignedByteType, VolatileUnsignedByteType, VolatileByteArray > createUnsignedByteInstance( final ImagePlus imp )
+	{
+		return createUnsignedByteInstance( imp, 0 );
+	}
+
+	public static VirtualStackImageLoader< UnsignedByteType, VolatileUnsignedByteType, VolatileByteArray > createUnsignedByteInstance( final ImagePlus imp, final int offset )
 	{
 		return new VirtualStackImageLoader< UnsignedByteType, VolatileUnsignedByteType, VolatileByteArray >(
-				imp, new VirtualStackVolatileByteArrayLoader( imp ), new UnsignedByteType(), new VolatileUnsignedByteType() )
+				imp, new VirtualStackVolatileByteArrayLoader( imp ), new UnsignedByteType(), new VolatileUnsignedByteType(), offset )
 		{
 			@Override
 			protected void linkType( final CachedCellImg< UnsignedByteType, VolatileByteArray > img )
@@ -119,9 +135,14 @@ public abstract class VirtualStackImageLoader< T extends NativeType< T >, V exte
 	}
 
 	public static VirtualStackImageLoader< ARGBType, VolatileARGBType, VolatileIntArray > createARGBInstance( final ImagePlus imp )
+	{
+		return createARGBInstance( imp, 0 );
+	}
+
+	public static VirtualStackImageLoader< ARGBType, VolatileARGBType, VolatileIntArray > createARGBInstance( final ImagePlus imp, final int offset )
 	{
 		return new VirtualStackImageLoader< ARGBType, VolatileARGBType, VolatileIntArray >(
-				imp, new VirtualStackVolatileARGBArrayLoader( imp ), new ARGBType(), new VolatileARGBType() )
+				imp, new VirtualStackVolatileARGBArrayLoader( imp ), new ARGBType(), new VolatileARGBType(), offset )
 		{
 			@Override
 			protected void linkType( final CachedCellImg< ARGBType, VolatileIntArray > img )
@@ -149,18 +170,23 @@ public abstract class VirtualStackImageLoader< T extends NativeType< T >, V exte
 
 	private final int[] cellDimensions;
 
-	private final ArrayList< SetupImgLoader > setupImgLoaders;
+	private final HashMap< Integer, SetupImgLoader > setupImgLoaders;
 
-	protected VirtualStackImageLoader( final ImagePlus imp, final CacheArrayLoader< A > loader, final T type, final V volatileType )
+	protected VirtualStackImageLoader( final ImagePlus imp, final CacheArrayLoader< A > loader, final T type, final V volatileType, int setupOffset )
 	{
 		this.loader = loader;
 		dimensions = new long[] { imp.getWidth(), imp.getHeight(), imp.getNSlices() };
 		cellDimensions = new int[] { imp.getWidth(), imp.getHeight(), 1 };
 		final int numSetups = imp.getNChannels();
 		cache = new VolatileGlobalCellCache( 1, 1 );
-		setupImgLoaders = new ArrayList<>();
+		setupImgLoaders = new HashMap<>();
 		for ( int setupId = 0; setupId < numSetups; ++setupId )
-			setupImgLoaders.add( new SetupImgLoader( setupId, type, volatileType ) );
+			setupImgLoaders.put( setupOffset + setupId, new SetupImgLoader( setupId, type, volatileType ) );
+	}
+
+	protected VirtualStackImageLoader( final ImagePlus imp, final CacheArrayLoader< A > loader, final T type, final V volatileType )
+	{
+		this( imp, loader, type, volatileType, 0 );
 	}
 
 	protected abstract void linkType( CachedCellImg< T, A > img );