diff --git a/src/main/java/bdv/BigDataViewer.java b/src/main/java/bdv/BigDataViewer.java
index 48b0c8f75ffd483f49036c3323af0e3af85dcb35..c83bd20ff02dcd6936121c10a33139ae9ead2f83 100644
--- a/src/main/java/bdv/BigDataViewer.java
+++ b/src/main/java/bdv/BigDataViewer.java
@@ -380,7 +380,8 @@ public class BigDataViewer
 
 	public static void main( final String[] args )
 	{
-		final String fn = "/Users/pietzsch/desktop/data/catmaid-confocal.xml";
+//		final String fn = "/Users/pietzsch/desktop/data/catmaid-confocal.xml";
+		final String fn = "/home/saalfeld/catmaid-confocal.xml";
 //		final String fn = "/Users/pietzsch/desktop/data/BDV130418A325/BDV130418A325_NoTempReg.xml";
 //		final String fn = "/Users/pietzsch/Desktop/data/valia2/valia.xml";
 //		final String fn = "/Users/pietzsch/workspace/data/fast fly/111010_weber/combined.xml";
diff --git a/src/main/java/bdv/img/catmaid/CatmaidImageLoader.java b/src/main/java/bdv/img/catmaid/CatmaidImageLoader.java
index b64a15b354766d34cca1c90dda9460cf856c2056..17cfa587c268f5f0b65f66a27ca0175b45a76a60 100644
--- a/src/main/java/bdv/img/catmaid/CatmaidImageLoader.java
+++ b/src/main/java/bdv/img/catmaid/CatmaidImageLoader.java
@@ -34,7 +34,7 @@ public class CatmaidImageLoader implements ViewerImgLoader< ARGBType, VolatileAR
 
 	private double resZ;
 
-	private String baseUrl;
+	private String urlFormat;
 
 	private int tileWidth;
 
@@ -60,7 +60,7 @@ public class CatmaidImageLoader implements ViewerImgLoader< ARGBType, VolatileAR
 		resXY = Double.parseDouble( elem.getChildText( "resXY" ) );
 		resZ = Double.parseDouble( elem.getChildText( "resZ" ) );
 
-		baseUrl = elem.getChildText( "baseUrl" );
+		urlFormat = elem.getChildText( "urlFormat" );
 
 		tileWidth = Integer.parseInt( elem.getChildText( "tileWidth" ) );
 		tileHeight = Integer.parseInt( elem.getChildText( "tileHeight" ) );
@@ -76,7 +76,6 @@ public class CatmaidImageLoader implements ViewerImgLoader< ARGBType, VolatileAR
 		blockDimensions = new int[ numScales ][];
 		for ( int l = 0; l < numScales; ++l )
 		{
-
 			mipmapResolutions[ l ] = new double[] { 1 << l, 1 << l, 1 };
 			imageDimensions[ l ] = new long[] { width >> l, height >> l, depth };
 			blockDimensions[ l ] = new int[] { tileWidth, tileHeight, 1 };
@@ -84,7 +83,7 @@ public class CatmaidImageLoader implements ViewerImgLoader< ARGBType, VolatileAR
 
 		final int[] maxLevels = new int[] { numScales - 1 };
 		cache = new VolatileGlobalCellCache< VolatileIntArray >(
-				new CatmaidVolatileIntArrayLoader( baseUrl, tileWidth, tileHeight ), 1, 1, numScales, maxLevels, 10 );
+				new CatmaidVolatileIntArrayLoader( urlFormat, tileWidth, tileHeight ), 1, 1, numScales, maxLevels, 10 );
 	}
 
 	final static public int getNumScales( long width, long height, final long tileWidth, final long tileHeight )
diff --git a/src/main/java/bdv/img/catmaid/CatmaidVolatileIntArrayLoader.java b/src/main/java/bdv/img/catmaid/CatmaidVolatileIntArrayLoader.java
index ebfe9e00359becc2cfc3e4c62f12a19b384dc398..762693a9db71ccad96e39508fdb3d3c29ac4608d 100644
--- a/src/main/java/bdv/img/catmaid/CatmaidVolatileIntArrayLoader.java
+++ b/src/main/java/bdv/img/catmaid/CatmaidVolatileIntArrayLoader.java
@@ -14,45 +14,70 @@ public class CatmaidVolatileIntArrayLoader implements CacheArrayLoader< Volatile
 {
 	private VolatileIntArray theEmptyArray;
 
-	private final String baseUrl;
-
+	private final String urlFormat;
+	
 	private final int tileWidth;
 
 	private final int tileHeight;
 
-	public CatmaidVolatileIntArrayLoader( final String baseUrl, final int tileWidth, final int tileHeight )
+	/**
+	 * <p>Create a {@link CacheArrayLoader} for a CATMAID source.  Tiles are
+	 * addressed, in this order, by their</p>
+	 * <ul>
+	 * <li>scale level,</li>
+	 * <li>scale,</li>
+	 * <li>x,</li>
+	 * <li>y,</li>
+	 * <li>z,</li>
+	 * <li>tile width,</li>
+	 * <li>tile height,</li>
+	 * <li>tile row, and</li>
+	 * <li>tile column.</li>
+	 * </ul>
+	 * <p><code>urlFormat</code> specifies how these parameters are used
+	 * to generate a URL referencing the tile.  Examples:</p>
+	 *
+	 * <dl>
+	 * <dt>"http://catmaid.org/my-data/xy/%5$d/%8$d_%9$d_%1$d.jpg"</dt>
+	 * <dd>CATMAID DefaultTileSource (type 1)</dd>
+	 * <dt>"http://catmaid.org/my-data/xy/?x=%3$d&y=%4$d&width=%6d&height=%7$d&row=%8$d&col=%9$d&scale=%2$f&z=%4$d"</dt>
+     * <dd>CATMAID RequestTileSource (type 2)</dd>
+	 * <dt>"http://catmaid.org/my-data/xy/%1$d/%5$d/%8$d/%9$d.jpg"</dt>
+	 * <dd>CATMAID LargeDataTileSource (type 5)</dd>
+	 * </dl>
+	 * 
+	 * @param urlFormat
+	 * @param tileWidth
+	 * @param tileHeight
+	 */
+	public CatmaidVolatileIntArrayLoader( final String urlFormat, final int tileWidth, final int tileHeight )
 	{
-		theEmptyArray = new VolatileIntArray( 256 * 256, false );
-		this.baseUrl = baseUrl;
+		theEmptyArray = new VolatileIntArray( tileWidth * tileHeight, false );
+		this.urlFormat = urlFormat;
 		this.tileWidth = tileWidth;
 		this.tileHeight = tileHeight;
 	}
-
+	
 	@Override
 	public int getBytesPerElement()
 	{
-		return 1;
+		return 4;
 	}
 
 	@Override
-	public VolatileIntArray loadArray( final int timepoint, final int setup, final int level, final int[] dimensions, final long[] min ) throws InterruptedException
+	public VolatileIntArray loadArray(
+			final int timepoint,
+			final int setup,
+			final int level,
+			final int[] dimensions,
+			final long[] min ) throws InterruptedException
 	{
 		final int c = ( int ) min[ 0 ] / tileWidth;
 		final int r = ( int ) min[ 1 ] / tileHeight;
-		final int z = ( int ) min[ 2 ];
-		final int s = level;
-		final String urlString =
-				new
-					StringBuffer( baseUrl ).
-					append( z ).
-					append( "/" ).
-					append( r ).
-					append( "_" ).
-					append( c ).
-					append( "_" ).
-					append( s ).
-					append( ".jpg" ).
-					toString();
+		final double scale = 1.0 / Math.pow(2.0, level);
+		
+		final String urlString = String.format( urlFormat, level, scale, min[ 0 ], min[ 1 ], min[ 2 ], tileWidth, tileHeight, r, c );
+		
 		final int w = dimensions[ 0 ];
 		final int h = dimensions[ 1 ];
 		final int[] data = new int[ w * h ];
diff --git a/src/main/java/bdv/img/catmaid/CatmaidVolatileShortArrayLoader.java b/src/main/java/bdv/img/catmaid/CatmaidVolatileShortArrayLoader.java
index 483f45b925053128ef76f7525a6799e61c356ebf..e6d1d6141093b18830c5cb79c5fc64760227c768 100644
--- a/src/main/java/bdv/img/catmaid/CatmaidVolatileShortArrayLoader.java
+++ b/src/main/java/bdv/img/catmaid/CatmaidVolatileShortArrayLoader.java
@@ -31,7 +31,7 @@ public class CatmaidVolatileShortArrayLoader implements CacheArrayLoader< Volati
 	@Override
 	public int getBytesPerElement()
 	{
-		return 1;
+		return 2;
 	}
 
 	@Override
diff --git a/src/main/java/net/imglib2/img/basictypeaccess/volatiles/VolatileByteAccess.java b/src/main/java/net/imglib2/img/basictypeaccess/volatiles/VolatileByteAccess.java
new file mode 100644
index 0000000000000000000000000000000000000000..9a79fbdbacf988b24b78e516df36cb766b38e4d9
--- /dev/null
+++ b/src/main/java/net/imglib2/img/basictypeaccess/volatiles/VolatileByteAccess.java
@@ -0,0 +1,11 @@
+package net.imglib2.img.basictypeaccess.volatiles;
+
+import net.imglib2.img.basictypeaccess.ByteAccess;
+
+
+/**
+ * @author Stephan Saalfeld <saalfelds@janelia.hhmi.org>
+ * @author Tobias Pietzsch <tobias.pietzsch@gmail.com>
+ */
+public interface VolatileByteAccess extends ByteAccess, VolatileAccess
+{}
diff --git a/src/main/java/net/imglib2/img/basictypeaccess/volatiles/array/VolatileByteArray.java b/src/main/java/net/imglib2/img/basictypeaccess/volatiles/array/VolatileByteArray.java
new file mode 100644
index 0000000000000000000000000000000000000000..ebec4451d9280c2109e5cf2b5059492a51019381
--- /dev/null
+++ b/src/main/java/net/imglib2/img/basictypeaccess/volatiles/array/VolatileByteArray.java
@@ -0,0 +1,52 @@
+package net.imglib2.img.basictypeaccess.volatiles.array;
+
+import net.imglib2.img.basictypeaccess.volatiles.VolatileByteAccess;
+
+/**
+ * A {@link ByteArray} with an {@link #isValid()} flag.
+ *
+ * @author Stephan Saalfeld <saalfelds@janelia.hhmi.org>
+ * @author Tobias Pietzsch <tobias.pietzsch@gmail.com>
+ */
+public class VolatileByteArray extends AbstractVolatileArray< VolatileByteArray > implements VolatileByteAccess
+{
+	private static final long serialVersionUID = -2609245209721069962L;
+
+	protected byte[] data;
+
+	public VolatileByteArray( final int numEntities, final boolean isValid )
+	{
+		super( isValid );
+		this.data = new byte[ numEntities ];
+	}
+
+	public VolatileByteArray( final byte[] data, final boolean isValid )
+	{
+		super( isValid );
+		this.data = data;
+	}
+
+	@Override
+	public byte getValue( final int index )
+	{
+		return data[ index ];
+	}
+
+	@Override
+	public void setValue( final int index, final byte value )
+	{
+		data[ index ] = value;
+	}
+
+	@Override
+	public VolatileByteArray createArray( final int numEntities )
+	{
+		return new VolatileByteArray( numEntities, true );
+	}
+
+	@Override
+	public byte[] getCurrentStorageArray()
+	{
+		return data;
+	}
+}
diff --git a/src/main/java/net/imglib2/img/basictypeaccess/volatiles/array/VolatileShortArray.java b/src/main/java/net/imglib2/img/basictypeaccess/volatiles/array/VolatileShortArray.java
index 869d891bde599252ddf00a5acf99fbcc19cf62ec..5f754222ccaa54945d258dc8ac429011519c7d21 100644
--- a/src/main/java/net/imglib2/img/basictypeaccess/volatiles/array/VolatileShortArray.java
+++ b/src/main/java/net/imglib2/img/basictypeaccess/volatiles/array/VolatileShortArray.java
@@ -10,6 +10,8 @@ import net.imglib2.img.basictypeaccess.volatiles.VolatileShortAccess;
  */
 public class VolatileShortArray extends AbstractVolatileArray< VolatileShortArray > implements VolatileShortAccess
 {
+	private static final long serialVersionUID = -8460450507170281183L;
+
 	protected short data[];
 
 	public VolatileShortArray( final int numEntities, final boolean isValid )
diff --git a/src/main/java/net/imglib2/type/volatiles/VolatileUnsignedByteType.java b/src/main/java/net/imglib2/type/volatiles/VolatileUnsignedByteType.java
new file mode 100644
index 0000000000000000000000000000000000000000..a2a5a43abc76d68e0a50a23c98da81945738e23d
--- /dev/null
+++ b/src/main/java/net/imglib2/type/volatiles/VolatileUnsignedByteType.java
@@ -0,0 +1,106 @@
+package net.imglib2.type.volatiles;
+
+import net.imglib2.Volatile;
+import net.imglib2.img.NativeImg;
+import net.imglib2.img.NativeImgFactory;
+import net.imglib2.img.basictypeaccess.ByteAccess;
+import net.imglib2.img.basictypeaccess.volatiles.VolatileByteAccess;
+import net.imglib2.img.basictypeaccess.volatiles.array.VolatileByteArray;
+import net.imglib2.type.numeric.integer.UnsignedByteType;
+
+/**
+ * A {@link Volatile} variant of {@link UnsignedByteType}. It uses an
+ * underlying {@link UnsignedByteType} that maps into a
+ * {@link VolatileByteAccess}.
+ *
+ * @author Stephan Saalfeld <saalfelds@janelia.hhmi.org>
+ * @author Tobias Pietzsch <tobias.pietzsch@gmail.com>
+ */
+public class VolatileUnsignedByteType extends AbstractVolatileNativeRealType< UnsignedByteType, VolatileUnsignedByteType >
+{
+	final protected NativeImg< ?, ? extends VolatileByteAccess > img;
+
+	private static class WrappedUnsignedByteType extends UnsignedByteType
+	{
+		public WrappedUnsignedByteType( final NativeImg<?, ? extends ByteAccess> img )
+		{
+			super( img );
+		}
+		
+		public WrappedUnsignedByteType( final ByteAccess access )
+		{
+			super( access );
+		}
+
+		public void setAccess( final ByteAccess access )
+		{
+			dataAccess = access;
+		}
+	}
+
+	// this is the constructor if you want it to read from an array
+	public VolatileUnsignedByteType( final NativeImg< ?, ? extends VolatileByteAccess > img )
+	{
+		super( new WrappedUnsignedByteType( img ), false );
+		this.img = img;
+	}
+
+	// this is the constructor if you want to specify the dataAccess
+	public VolatileUnsignedByteType( final VolatileByteAccess access )
+	{
+		super( new WrappedUnsignedByteType( access ), access.isValid() );
+		this.img = null;
+	}
+
+	// this is the constructor if you want it to be a variable
+	public VolatileUnsignedByteType( final int value )
+	{
+		this( new VolatileByteArray( 1, true ) );
+		set( value );
+	}
+
+	// this is the constructor if you want it to be a variable
+	public VolatileUnsignedByteType()
+	{
+		this( 0 );
+	}
+
+	public void set( final int value )
+	{
+		get().set( value );
+	}
+
+	@Override
+	public void updateContainer( final Object c )
+	{
+		final VolatileByteAccess a = img.update( c );
+		( ( WrappedUnsignedByteType )t ).setAccess( a );
+		setValid( a.isValid() );
+	}
+
+	@Override
+	public NativeImg< VolatileUnsignedByteType, ? extends VolatileByteAccess > createSuitableNativeImg( final NativeImgFactory< VolatileUnsignedByteType > storageFactory, final long[] dim )
+	{
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public VolatileUnsignedByteType duplicateTypeOnSameNativeImg()
+	{
+		return new VolatileUnsignedByteType( img );
+	}
+
+	@Override
+	public VolatileUnsignedByteType createVariable()
+	{
+		return new VolatileUnsignedByteType();
+	}
+
+	@Override
+	public VolatileUnsignedByteType copy()
+	{
+		final VolatileUnsignedByteType v = createVariable();
+		v.set( this );
+		return v;
+	}
+}