diff --git a/IO/Image/vtkTIFFReader.cxx b/IO/Image/vtkTIFFReader.cxx
index c1e849a8168f4dcd4c2a66c1dcc69055fc1440f7..d9ec1a8ef3c8331365e4968aeff69939aab52bcf 100644
--- a/IO/Image/vtkTIFFReader.cxx
+++ b/IO/Image/vtkTIFFReader.cxx
@@ -27,6 +27,62 @@ extern "C" {
 #include "vtk_tiff.h"
 }
 
+namespace {
+struct FlipTrue {};
+struct FlipFalse {};
+
+int GetFileRow(int row, int height, FlipTrue)
+{
+  return height - row - 1;
+}
+
+int GetFileRow(int row, int, FlipFalse)
+{
+  return row;
+}
+
+// Simple scan line copy of a slice in a volume with tightly packed memory.
+template<typename T, typename Flip>
+bool ReadTemplatedImage(T* out, Flip flip,
+                        int startCol, int endCol,
+                        int startRow, int endRow,
+                        int yIncrements,
+                        unsigned int height, TIFF *image)
+{
+  unsigned int isize = TIFFScanlineSize(image);
+  size_t scanLineSize = endCol - startCol + 1;
+  if (scanLineSize * sizeof(T) == isize)
+    {
+    // We can copy straight into the image data output.
+    for (int i = startRow; i <= endRow; ++i)
+      {
+      T* tmp = out + (i - startRow) * yIncrements;
+      if (TIFFReadScanline(image, tmp, GetFileRow(i, height, flip), 0) <= 0)
+        {
+        return false;
+        }
+      }
+    }
+  else
+    {
+    // Copy into a buffer of the appropriate size, then subset into the output.
+    tdata_t buf = _TIFFmalloc(isize);
+    for (int i = startRow; i <= endRow; ++i)
+      {
+      T* tmp = out + (i - startRow) * yIncrements;
+      if (TIFFReadScanline(image, buf, GetFileRow(i, height, flip), 0) <= 0)
+        {
+        _TIFFfree(buf);
+        return false;
+        }
+      memcpy(tmp, static_cast<T*>(buf) + startCol, sizeof(T) * scanLineSize);
+      }
+    _TIFFfree(buf);
+    }
+  return true;
+}
+}
+
 //-------------------------------------------------------------------------
 vtkStandardNewMacro(vtkTIFFReader)
 
@@ -1012,6 +1068,41 @@ void vtkTIFFReader::ReadTwoSamplesPerPixelImage(void *out,
 template<typename T>
 void vtkTIFFReader::ReadGenericImage(T* out, unsigned int, unsigned int height)
 {
+  // Fast path for simple images
+  unsigned int format = this->GetFormat();
+  if (this->InternalImage->PlanarConfig == PLANARCONFIG_CONTIG &&
+      this->OutputIncrements[0] == 1 &&
+      (format == vtkTIFFReader::GRAYSCALE &&
+       this->InternalImage->Photometrics == PHOTOMETRIC_MINISBLACK &&
+       this->InternalImage->SamplesPerPixel ==  1))
+    {
+    if (this->InternalImage->Orientation == ORIENTATION_TOPLEFT)
+      {
+      FlipFalse flip;
+      if (!ReadTemplatedImage(out, flip,
+                              this->OutputExtent[0], this->OutputExtent[1],
+                              this->OutputExtent[2], this->OutputExtent[3],
+                              this->OutputIncrements[1],
+                              height, this->InternalImage->Image))
+        {
+        vtkErrorMacro(<< "Problem reading slice of volume in TIFF file.");
+        }
+      }
+    else
+      {
+      FlipTrue flip;
+      if (!ReadTemplatedImage(out, flip,
+                              this->OutputExtent[0], this->OutputExtent[1],
+                              this->OutputExtent[2], this->OutputExtent[3],
+                              this->OutputIncrements[1],
+                              height, this->InternalImage->Image))
+        {
+        vtkErrorMacro(<< "Problem reading slice of volume in TIFF file.");
+        }
+      }
+    return;
+    }
+
   unsigned int isize = TIFFScanlineSize(this->InternalImage->Image);
   tdata_t buf = _TIFFmalloc(isize);