diff --git a/pom.xml b/pom.xml
index 901f3059e655d8d6c77caaa2d7b59a99d2ca46b4..4c1486b7b4858d159f4efc78c66e307d88bc6c56 100644
--- a/pom.xml
+++ b/pom.xml
@@ -92,6 +92,9 @@
 		<package-name>bdv.ij</package-name>
 		<license.licenseName>gpl_v3</license.licenseName>
 		<license.copyrightOwners>BigDataViewer developers.</license.copyrightOwners>
+
+		<imglib2.version>4.2.1</imglib2.version>
+		<bigdataviewer-core.version>4.1.0</bigdataviewer-core.version>
 	</properties>
 
 	<repositories>
@@ -122,6 +125,11 @@
 			<groupId>io.scif</groupId>
 			<artifactId>scifio</artifactId>
 		</dependency>
+		<dependency>
+			<groupId>net.imglib2</groupId>
+			<artifactId>imglib2-ui</artifactId>
+			<version>2.0.0-beta-32</version>
+		</dependency>
 		<dependency>
 			<groupId>sc.fiji</groupId>
 			<artifactId>SPIM_Registration</artifactId>
diff --git a/src/main/java/bdv/img/virtualstack/VirtualStackImageLoader.java b/src/main/java/bdv/img/virtualstack/VirtualStackImageLoader.java
index c4cdfc17da00efe0cb392d2669068ca83480fe0a..10f6229c1bc43fb1ddd06a186eecbd2042bc24ec 100644
--- a/src/main/java/bdv/img/virtualstack/VirtualStackImageLoader.java
+++ b/src/main/java/bdv/img/virtualstack/VirtualStackImageLoader.java
@@ -4,26 +4,25 @@ import java.util.ArrayList;
 
 import bdv.AbstractViewerSetupImgLoader;
 import bdv.ViewerImgLoader;
-import bdv.cache.CacheHints;
-import bdv.cache.LoadingStrategy;
 import bdv.img.cache.CacheArrayLoader;
-import bdv.img.cache.CachedCellImg;
 import bdv.img.cache.VolatileGlobalCellCache;
-import bdv.img.cache.VolatileImgCells;
-import bdv.img.cache.VolatileImgCells.CellCache;
 import ij.ImagePlus;
 import mpicbg.spim.data.generic.sequence.BasicSetupImgLoader;
 import mpicbg.spim.data.generic.sequence.ImgLoaderHint;
 import mpicbg.spim.data.generic.sequence.TypedBasicImgLoader;
-import mpicbg.spim.data.sequence.ViewId;
 import net.imglib2.RandomAccessibleInterval;
 import net.imglib2.Volatile;
+import net.imglib2.cache.img.CachedCellImg;
+import net.imglib2.cache.volatiles.CacheHints;
+import net.imglib2.cache.volatiles.LoadingStrategy;
 import net.imglib2.img.NativeImg;
 import net.imglib2.img.basictypeaccess.volatiles.VolatileAccess;
 import net.imglib2.img.basictypeaccess.volatiles.array.VolatileByteArray;
 import net.imglib2.img.basictypeaccess.volatiles.array.VolatileFloatArray;
 import net.imglib2.img.basictypeaccess.volatiles.array.VolatileIntArray;
 import net.imglib2.img.basictypeaccess.volatiles.array.VolatileShortArray;
+import net.imglib2.img.cell.AbstractCellImg;
+import net.imglib2.img.cell.CellGrid;
 import net.imglib2.realtransform.AffineTransform3D;
 import net.imglib2.type.NativeType;
 import net.imglib2.type.numeric.ARGBType;
@@ -34,7 +33,6 @@ import net.imglib2.type.volatiles.VolatileARGBType;
 import net.imglib2.type.volatiles.VolatileFloatType;
 import net.imglib2.type.volatiles.VolatileUnsignedByteType;
 import net.imglib2.type.volatiles.VolatileUnsignedShortType;
-import net.imglib2.util.Fraction;
 
 /**
  * ImageLoader backed by a ImagePlus. The ImagePlus may be virtual and in
@@ -194,19 +192,13 @@ public abstract class VirtualStackImageLoader< T extends NativeType< T >, V exte
 		@Override
 		public RandomAccessibleInterval< V > getVolatileImage( final int timepointId, final int level, final ImgLoaderHint... hints )
 		{
-			final ViewId view = new ViewId( timepointId, setupId );
-			final CachedCellImg< V, A > img = prepareCachedImage( view, level, LoadingStrategy.BUDGETED );
-			linkVolatileType( img );
-			return img;
+			return prepareCachedImage( timepointId, level, LoadingStrategy.BUDGETED, volatileType );
 		}
 
 		@Override
 		public RandomAccessibleInterval< T > getImage( final int timepointId, final int level, final ImgLoaderHint... hints )
 		{
-			final ViewId view = new ViewId( timepointId, setupId );
-			final CachedCellImg< T, A > img = prepareCachedImage( view, level, LoadingStrategy.BLOCKING );
-			linkType( img );
-			return img;
+			return prepareCachedImage( timepointId, level, LoadingStrategy.BUDGETED, type );
 		}
 
 		/**
@@ -215,14 +207,12 @@ public abstract class VirtualStackImageLoader< T extends NativeType< T >, V exte
 		 * linked type} before it can be used. The type should be either
 		 * {@link ARGBType} and {@link VolatileARGBType}.
 		 */
-		protected < T extends NativeType< T > > CachedCellImg< T, A > prepareCachedImage( final ViewId view, final int level, final LoadingStrategy loadingStrategy )
+		protected < T extends NativeType< T > > AbstractCellImg< T, A, ?, ? > prepareCachedImage( final int timepointId, final int level, final LoadingStrategy loadingStrategy, final T type )
 		{
 			final int priority = 0;
 			final CacheHints cacheHints = new CacheHints( loadingStrategy, priority, false );
-			final CellCache< A > c = cache.new VolatileCellCache<>( view.getTimePointId(), view.getViewSetupId(), level, cacheHints, loader );
-			final VolatileImgCells< A > cells = new VolatileImgCells<>( c, new Fraction(), dimensions, cellDimensions );
-			final CachedCellImg< T, A > img = new CachedCellImg<>( cells );
-			return img;
+			final CellGrid grid = new CellGrid( dimensions, cellDimensions );
+			return cache.createImg( grid, timepointId, setupId, level, cacheHints, loader, type );
 		}
 
 		@Override
diff --git a/src/main/java/bdv/img/virtualstack/VirtualStackVolatileARGBArrayLoader.java b/src/main/java/bdv/img/virtualstack/VirtualStackVolatileARGBArrayLoader.java
index d586bdc76e81c30301de30b1054d8a2c28b58074..893a17e7857b920692af736cf51ae4b207789987 100644
--- a/src/main/java/bdv/img/virtualstack/VirtualStackVolatileARGBArrayLoader.java
+++ b/src/main/java/bdv/img/virtualstack/VirtualStackVolatileARGBArrayLoader.java
@@ -1,18 +1,15 @@
 package bdv.img.virtualstack;
 
+import bdv.img.cache.CacheArrayLoader;
 import ij.ImagePlus;
 import net.imglib2.img.basictypeaccess.volatiles.array.VolatileIntArray;
-import bdv.img.cache.CacheArrayLoader;
 
 public class VirtualStackVolatileARGBArrayLoader implements CacheArrayLoader< VolatileIntArray >
 {
-	private final VolatileIntArray theEmptyArray;
-
 	private final ImagePlus imp;
 
 	public VirtualStackVolatileARGBArrayLoader( final ImagePlus imp )
 	{
-		theEmptyArray = new VolatileIntArray( imp.getWidth() * imp.getHeight(), false );
 		this.imp = imp;
 	}
 
@@ -26,12 +23,6 @@ public class VirtualStackVolatileARGBArrayLoader implements CacheArrayLoader< Vo
 		return new VolatileIntArray( data, true );
 	}
 
-	@Override
-	public VolatileIntArray emptyArray( final int[] dimensions )
-	{
-		return theEmptyArray;
-	}
-
 	@Override
 	public int getBytesPerElement()
 	{
diff --git a/src/main/java/bdv/img/virtualstack/VirtualStackVolatileByteArrayLoader.java b/src/main/java/bdv/img/virtualstack/VirtualStackVolatileByteArrayLoader.java
index 1347cafa72e9215c4fc3e4475a79f732707e1010..70a55e3b283b80106595fefec5b06c8555c8db9e 100644
--- a/src/main/java/bdv/img/virtualstack/VirtualStackVolatileByteArrayLoader.java
+++ b/src/main/java/bdv/img/virtualstack/VirtualStackVolatileByteArrayLoader.java
@@ -1,18 +1,15 @@
 package bdv.img.virtualstack;
 
+import bdv.img.cache.CacheArrayLoader;
 import ij.ImagePlus;
 import net.imglib2.img.basictypeaccess.volatiles.array.VolatileByteArray;
-import bdv.img.cache.CacheArrayLoader;
 
 public class VirtualStackVolatileByteArrayLoader implements CacheArrayLoader< VolatileByteArray >
 {
-	private final VolatileByteArray theEmptyArray;
-
 	private final ImagePlus imp;
 
 	public VirtualStackVolatileByteArrayLoader( final ImagePlus imp )
 	{
-		theEmptyArray = new VolatileByteArray( imp.getWidth() * imp.getHeight(), false );
 		this.imp = imp;
 	}
 
@@ -26,12 +23,6 @@ public class VirtualStackVolatileByteArrayLoader implements CacheArrayLoader< Vo
 		return new VolatileByteArray( data, true );
 	}
 
-	@Override
-	public VolatileByteArray emptyArray( final int[] dimensions )
-	{
-		return theEmptyArray;
-	}
-
 	@Override
 	public int getBytesPerElement()
 	{
diff --git a/src/main/java/bdv/img/virtualstack/VirtualStackVolatileFloatArrayLoader.java b/src/main/java/bdv/img/virtualstack/VirtualStackVolatileFloatArrayLoader.java
index 6b7127383481443c05c48d740d0e69b00169170c..dbd3da0f432b78bfc40fbe8f5568ed52622ad727 100644
--- a/src/main/java/bdv/img/virtualstack/VirtualStackVolatileFloatArrayLoader.java
+++ b/src/main/java/bdv/img/virtualstack/VirtualStackVolatileFloatArrayLoader.java
@@ -1,18 +1,15 @@
 package bdv.img.virtualstack;
 
+import bdv.img.cache.CacheArrayLoader;
 import ij.ImagePlus;
 import net.imglib2.img.basictypeaccess.volatiles.array.VolatileFloatArray;
-import bdv.img.cache.CacheArrayLoader;
 
 public class VirtualStackVolatileFloatArrayLoader implements CacheArrayLoader< VolatileFloatArray >
 {
-	private final VolatileFloatArray theEmptyArray;
-
 	private final ImagePlus imp;
 
 	public VirtualStackVolatileFloatArrayLoader( final ImagePlus imp )
 	{
-		theEmptyArray = new VolatileFloatArray( imp.getWidth() * imp.getHeight(), false );
 		this.imp = imp;
 	}
 
@@ -26,12 +23,6 @@ public class VirtualStackVolatileFloatArrayLoader implements CacheArrayLoader< V
 		return new VolatileFloatArray( data, true );
 	}
 
-	@Override
-	public VolatileFloatArray emptyArray( final int[] dimensions )
-	{
-		return theEmptyArray;
-	}
-
 	@Override
 	public int getBytesPerElement()
 	{
diff --git a/src/main/java/bdv/img/virtualstack/VirtualStackVolatileShortArrayLoader.java b/src/main/java/bdv/img/virtualstack/VirtualStackVolatileShortArrayLoader.java
index d95c8724069a61cc53491ec8694f288d7f704ac3..c819b3a3f7ff68c19a39bb03cbc14346d344a433 100644
--- a/src/main/java/bdv/img/virtualstack/VirtualStackVolatileShortArrayLoader.java
+++ b/src/main/java/bdv/img/virtualstack/VirtualStackVolatileShortArrayLoader.java
@@ -1,18 +1,15 @@
 package bdv.img.virtualstack;
 
+import bdv.img.cache.CacheArrayLoader;
 import ij.ImagePlus;
 import net.imglib2.img.basictypeaccess.volatiles.array.VolatileShortArray;
-import bdv.img.cache.CacheArrayLoader;
 
 public class VirtualStackVolatileShortArrayLoader implements CacheArrayLoader< VolatileShortArray >
 {
-	private final VolatileShortArray theEmptyArray;
-
 	private final ImagePlus imp;
 
 	public VirtualStackVolatileShortArrayLoader( final ImagePlus imp )
 	{
-		theEmptyArray = new VolatileShortArray( imp.getWidth() * imp.getHeight(), false );
 		this.imp = imp;
 	}
 
@@ -26,12 +23,6 @@ public class VirtualStackVolatileShortArrayLoader implements CacheArrayLoader< V
 		return new VolatileShortArray( data, true );
 	}
 
-	@Override
-	public VolatileShortArray emptyArray( final int[] dimensions )
-	{
-		return theEmptyArray;
-	}
-
 	@Override
 	public int getBytesPerElement()
 	{