diff --git a/image_readers/source/java/ch/systemsx/cisd/imagereaders/IImageReader.java b/image_readers/source/java/ch/systemsx/cisd/imagereaders/IImageReader.java
index 7502c46aff9e7f090aac6b80586fdeb5eef1719d..4922fdf2d56fe9508f950b68a8a00edc4bacff74 100644
--- a/image_readers/source/java/ch/systemsx/cisd/imagereaders/IImageReader.java
+++ b/image_readers/source/java/ch/systemsx/cisd/imagereaders/IImageReader.java
@@ -16,6 +16,7 @@
 
 package ch.systemsx.cisd.imagereaders;
 
+import java.awt.Dimension;
 import java.awt.image.BufferedImage;
 import java.io.File;
 import java.util.List;
@@ -41,12 +42,12 @@ public interface IImageReader
      * Return the name of the reader.
      */
     public String getName();
-    
+
     /**
      * Returns a list of IDs uniquely identifying all images in the specified file.
      */
     public List<ImageID> getImageIDs(File file) throws IOExceptionUnchecked;
-    
+
     /**
      * Returns a list of IDs uniquely identifying all images in the specified byte array.
      */
@@ -56,7 +57,7 @@ public interface IImageReader
      * Returns a list of IDs uniquely identifying all images in the specified handle.
      */
     public List<ImageID> getImageIDs(IRandomAccessFile handle) throws IOExceptionUnchecked;
-    
+
     /**
      * Reads a {@link BufferedImage} from a {@link File}.
      * 
@@ -64,7 +65,8 @@ public interface IImageReader
      * @param imageID the ID of the image to be read
      * @param params read parameters
      */
-    public BufferedImage readImage(File file, ImageID imageID, IReadParams params) throws IOExceptionUnchecked;
+    public BufferedImage readImage(File file, ImageID imageID, IReadParams params)
+            throws IOExceptionUnchecked;
 
     /**
      * Reads a {@link BufferedImage} from a byte array.
@@ -119,7 +121,15 @@ public interface IImageReader
      * @param imageID the ID of the image to be read
      * @param params read parameters
      */
-    public Map<String, Object> readMetaData(IRandomAccessFile handle, ImageID imageID, IReadParams params)
-            throws IOExceptionUnchecked;
+    public Map<String, Object> readMetaData(IRandomAccessFile handle, ImageID imageID,
+            IReadParams params) throws IOExceptionUnchecked;
 
+    /**
+     * Reads image dimensions (width and height).
+     * 
+     * @param handle the image file as {@link IRandomAccessFile}
+     * @param imageID the ID of the image to be read
+     * @return dimensions of the image
+     */
+    public Dimension readDimensions(IRandomAccessFile handle, ImageID imageID);
 }
diff --git a/image_readers/source/java/ch/systemsx/cisd/imagereaders/bioformats/BioFormatsImageUtils.java b/image_readers/source/java/ch/systemsx/cisd/imagereaders/bioformats/BioFormatsImageUtils.java
index 362631914698bf23ef74bf54eef21e0e793a500d..c20323f7123e2d4bc31e78f7273ad676defcec7c 100644
--- a/image_readers/source/java/ch/systemsx/cisd/imagereaders/bioformats/BioFormatsImageUtils.java
+++ b/image_readers/source/java/ch/systemsx/cisd/imagereaders/bioformats/BioFormatsImageUtils.java
@@ -20,6 +20,7 @@ import ij.ImagePlus;
 import ij.ImageStack;
 import ij.process.ImageProcessor;
 
+import java.awt.Dimension;
 import java.awt.image.BufferedImage;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -149,7 +150,7 @@ final class BioFormatsImageUtils
     {
         return reader.getClass().getSimpleName();
     }
-    
+
     static List<ImageID> listImageIDs(IFormatReader reader, IRandomAccess handle)
     {
         String handleId = generateHandleId(reader);
@@ -196,8 +197,8 @@ final class BioFormatsImageUtils
      * 
      * @throws IOExceptionUnchecked If access to <var>handle</var> fails.
      */
-    static BufferedImage readImage(IFormatReader reader,
-            IRandomAccess handle, ImageID imageID) throws IOExceptionUnchecked, IllegalArgumentException
+    static BufferedImage readImage(IFormatReader reader, IRandomAccess handle, ImageID imageID)
+            throws IOExceptionUnchecked, IllegalArgumentException
     {
         String handleId = generateHandleId(reader);
         // Add to static map.
@@ -235,7 +236,7 @@ final class BioFormatsImageUtils
     /**
      * Returns the metadata of the image file represented by <var>handle</var>.
      * 
-     * @param imageID 
+     * @param imageID
      * @throws IOExceptionUnchecked If access to <var>handle</var> fails.
      */
     public static Map<String, Object> readMetadata(IFormatReader reader, IRandomAccess handle,
@@ -268,7 +269,6 @@ final class BioFormatsImageUtils
         }
     }
 
-
     /**
      * An utility method that uses bio-formats reader to read an image and ImageJ to do a basic
      * intensity rescaling.
@@ -295,7 +295,8 @@ final class BioFormatsImageUtils
             int height = reader.getSizeY();
             final ImageStack stack = new ImageStack(width, height);
             int imageIndex = calculateImageIndex(reader, imageID);
-            final ImageProcessor ip = BioFormatsImageProcessor.openProcessor(reader, imageIndex, channel);
+            final ImageProcessor ip =
+                    BioFormatsImageProcessor.openProcessor(reader, imageIndex, channel);
             stack.addSlice("", ip);
             final ImagePlus imp = new ImagePlus(handleId, stack);
 
@@ -315,6 +316,34 @@ final class BioFormatsImageUtils
         }
     }
 
+    static Dimension readImageDimensions(IFormatReader reader, IRandomAccess handle, ImageID imageID)
+            throws IOExceptionUnchecked, IllegalArgumentException
+    {
+        // Add to static map.
+        String handleId = generateHandleId(reader);
+        Location.mapFile(handleId, handle);
+        try
+        {
+            // This does the actual parsing.
+            reader.setId(handleId);
+            reader.setSeries(imageID.getSeriesIndex());
+            int width = reader.getSizeX();
+            int height = reader.getSizeY();
+            reader.close();
+            return new Dimension(width, height);
+        } catch (FormatException ex)
+        {
+            throw CheckedExceptionTunnel.wrapIfNecessary(ex);
+        } catch (IOException ex)
+        {
+            throw CheckedExceptionTunnel.wrapIfNecessary(ex);
+        } finally
+        {
+            // Remove from static map.
+            Location.mapFile(handleId, null);
+        }
+    }
+
     public static String generateHandleId(IFormatHandler formatHandler)
     {
         return UUID.randomUUID().toString() + "." + formatHandler.getSuffixes()[0];
diff --git a/image_readers/source/java/ch/systemsx/cisd/imagereaders/bioformats/DefaultBioformatsImageReader.java b/image_readers/source/java/ch/systemsx/cisd/imagereaders/bioformats/DefaultBioformatsImageReader.java
index b87e6334dd6e21db1f5e0f9c7a77dd93f66ca38d..c0d745d1eda12e7dddc25bd45c8520e283ece5ca 100644
--- a/image_readers/source/java/ch/systemsx/cisd/imagereaders/bioformats/DefaultBioformatsImageReader.java
+++ b/image_readers/source/java/ch/systemsx/cisd/imagereaders/bioformats/DefaultBioformatsImageReader.java
@@ -16,6 +16,7 @@
 
 package ch.systemsx.cisd.imagereaders.bioformats;
 
+import java.awt.Dimension;
 import java.awt.image.BufferedImage;
 import java.util.List;
 import java.util.Map;
@@ -91,4 +92,10 @@ class DefaultBioformatsImageReader extends AbstractMetaDataAwareImageReader
         IRandomAccess input = new BioFormatsRandomAccessAdapter(handle);
         return BioFormatsImageUtils.readMetadata(formatReader, input, imageID);
     }
+
+    public Dimension readDimensions(IRandomAccessFile handle, ImageID imageID)
+    {
+        IRandomAccess input = new BioFormatsRandomAccessAdapter(handle);
+        return BioFormatsImageUtils.readImageDimensions(formatReader, input, imageID);
+    }
 }
\ No newline at end of file
diff --git a/image_readers/source/java/ch/systemsx/cisd/imagereaders/ij/ImageJReaderLibrary.java b/image_readers/source/java/ch/systemsx/cisd/imagereaders/ij/ImageJReaderLibrary.java
index 165b0d53ccbc21b26b26be8635a5ff8877a1830c..64ed38cdf46b622f6cc30b94132e754030c1aae5 100644
--- a/image_readers/source/java/ch/systemsx/cisd/imagereaders/ij/ImageJReaderLibrary.java
+++ b/image_readers/source/java/ch/systemsx/cisd/imagereaders/ij/ImageJReaderLibrary.java
@@ -21,6 +21,7 @@ import ij.io.Opener;
 import ij.process.ImageProcessor;
 import ij.process.ShortProcessor;
 
+import java.awt.Dimension;
 import java.awt.Graphics2D;
 import java.awt.image.BufferedImage;
 import java.util.Arrays;
@@ -67,6 +68,17 @@ public class ImageJReaderLibrary implements IImageReaderLibrary
                 }
                 return createBufferedImageOfSameType(imagePlus);
             }
+
+            public Dimension readDimensions(IRandomAccessFile handle, ImageID imageID)
+            {
+                AdapterIInputStreamToInputStream is = new AdapterIInputStreamToInputStream(handle);
+                ImagePlus imagePlus = new Opener().openTiff(is, "");
+                if (imagePlus == null)
+                {
+                    throw new IllegalStateException("Cannot open the image file with ImageJ.");
+                }
+                return new Dimension(imagePlus.getWidth(), imagePlus.getHeight());
+            }
         };
 
     private BufferedImage createBufferedImageOfSameType(ImagePlus imagePlus)
diff --git a/image_readers/source/java/ch/systemsx/cisd/imagereaders/imageio/ImageIOReaderLibrary.java b/image_readers/source/java/ch/systemsx/cisd/imagereaders/imageio/ImageIOReaderLibrary.java
index 13e53309e578b2a978173b4b777676270af08683..f39fa4d7879fc125957ea28ea04976702ed93879 100644
--- a/image_readers/source/java/ch/systemsx/cisd/imagereaders/imageio/ImageIOReaderLibrary.java
+++ b/image_readers/source/java/ch/systemsx/cisd/imagereaders/imageio/ImageIOReaderLibrary.java
@@ -17,6 +17,7 @@
 
 package ch.systemsx.cisd.imagereaders.imageio;
 
+import java.awt.Dimension;
 import java.awt.image.BufferedImage;
 import java.io.IOException;
 import java.io.InputStream;
@@ -113,6 +114,19 @@ public class ImageIOReaderLibrary implements IImageReaderLibrary
                     }
                 }
 
+                public Dimension readDimensions(IRandomAccessFile handle, ImageID imageID)
+                {
+                    try
+                    {
+                        ImageInputStream imageInput = adaptHandle(handle);
+                        ioReader.setInput(imageInput);
+                        return new Dimension(ioReader.getWidth(0), ioReader.getHeight(0));
+                    } catch (IOException ex)
+                    {
+                        throw CheckedExceptionTunnel.wrapIfNecessary(ex);
+                    }
+                }
+
                 private ImageInputStream adaptHandle(IRandomAccessFile handle)
                 {
 
diff --git a/image_readers/source/java/ch/systemsx/cisd/imagereaders/jai/DefaultImageReader.java b/image_readers/source/java/ch/systemsx/cisd/imagereaders/jai/DefaultImageReader.java
index 1894f6febfbd1ca694070b6392c62540d2483501..e7140c9cab1821172bf40a3afb324fb6d87092e9 100644
--- a/image_readers/source/java/ch/systemsx/cisd/imagereaders/jai/DefaultImageReader.java
+++ b/image_readers/source/java/ch/systemsx/cisd/imagereaders/jai/DefaultImageReader.java
@@ -16,6 +16,7 @@
 
 package ch.systemsx.cisd.imagereaders.jai;
 
+import java.awt.Dimension;
 import java.awt.image.BufferedImage;
 import java.awt.image.RenderedImage;
 import java.io.IOException;
@@ -92,4 +93,19 @@ class DefaultImageReader extends AbstractImageReader
             throw CheckedExceptionTunnel.wrapIfNecessary(ex);
         }
     }
+
+    public Dimension readDimensions(IRandomAccessFile handle, ImageID imageID)
+    {
+        try
+        {
+            InputStream input = new AdapterIInputStreamToInputStream(handle);
+            ImageDecoder decoder = ImageCodec.createImageDecoder(getName(), input, null);
+            RenderedImage renderedImage =
+                    decoder.decodeAsRenderedImage(imageID.getTimeSeriesIndex());
+            return new Dimension(renderedImage.getWidth(), renderedImage.getHeight());
+        } catch (IOException ex)
+        {
+            throw CheckedExceptionTunnel.wrapIfNecessary(ex);
+        }
+    }
 }
\ No newline at end of file