diff --git a/Code/IO/otbJPEG2000ImageIO.cxx b/Code/IO/otbJPEG2000ImageIO.cxx
index a24bf7264db0876b48a92c8d4c5b41e4a9cac4db..accfbe4e5f6da4cb72f5fd91448f7602507121cc 100644
--- a/Code/IO/otbJPEG2000ImageIO.cxx
+++ b/Code/IO/otbJPEG2000ImageIO.cxx
@@ -635,22 +635,8 @@ void JPEG2000ImageIO::Read(void* buffer)
       {
       (*it)->Clean();
       }
-    itkExceptionMacro(<< " IORegion is not correct in terme of tile!");
+    itkExceptionMacro(<< " IORegion does not correspond to any tile!");
     }
-  // Get nb. of lines and columns of the region to read
-  int lNbLines     = this->GetIORegion().GetSize()[1];
-  int lNbColumns   = this->GetIORegion().GetSize()[0];
-  int lFirstLine   = this->GetIORegion().GetIndex()[1]; // [1... ]
-  int lFirstColumn = this->GetIORegion().GetIndex()[0]; // [1... ]
-
-  otbMsgDevMacro(<< " JPEG2000ImageIO::Read()  ");
-  otbMsgDevMacro(<< " ImageDimension   : " << m_Dimensions[0] << "," << m_Dimensions[1]);
-  otbMsgDevMacro(<< " IORegion         : " << this->GetIORegion());
-  otbMsgDevMacro(<< " Nb Of Components : " << this->GetNumberOfComponents());
-  otbMsgDevMacro(<< " Area to read: " << lFirstColumn << " " << lFirstLine  << " "
-                 << lFirstColumn + lNbColumns << " " << lFirstLine + lNbLines);
-  otbMsgDevMacro(<< "Component type: " << this->GetComponentTypeAsString(this->GetComponentType()));
-
 
   // Here we sort between tiles from cache and tiles to read
   std::vector<JPEG2000TileCache::CachedTileType> cachedTiles;
@@ -688,20 +674,6 @@ void JPEG2000ImageIO::Read(void* buffer)
     this->GetMultiThreader()->SingleMethodExecute();
     }
 
-  // for (std::vector<JPEG2000TileCache::CachedTileType>::iterator itTile = toReadTiles.begin(); itTile < toReadTiles.end(); ++itTile)
-  //   {
-  //   // Call the reader
-  //   itTile->second = m_InternalReaders.front()->DecodeTile(itTile->first);
-    
-  //   // Check if tile is valid
-  //   if(!itTile->second)
-  //     {
-  //     this->m_InternalReaders.front()->Clean();
-  //     itkExceptionMacro(<< " otbopenjpeg failed to decode the desired tile "<< itTile->first << "!");
-  //     }
-  //   otbMsgDevMacro(<< " Tile " << itTile->first << " is decoded.");
-  //   }
-
   // Build the list of all tiles
   allNeededTiles = cachedTiles;
   allNeededTiles.insert(allNeededTiles.end(),toReadTiles.begin(),toReadTiles.end());
@@ -709,119 +681,129 @@ void JPEG2000ImageIO::Read(void* buffer)
   
   for (std::vector<JPEG2000TileCache::CachedTileType>::iterator itTile = allNeededTiles.begin(); itTile < allNeededTiles.end(); ++itTile)
     {
-    opj_image_t * currentTile = itTile->second;
+    this->LoadTileData(buffer,itTile->second);
+    }
+  
 
-    if(!currentTile)
-      {
-      itkExceptionMacro(<<"Tile "<<itTile->first<<" needed but not loaded.");
-      }
+  // Now, do cache book-keeping
+  for (std::vector<JPEG2000TileCache::CachedTileType>::iterator itTile = toReadTiles.begin(); itTile < toReadTiles.end(); ++itTile)
+    {
+    m_TileCache->AddTile(itTile->first,itTile->second);
+    }
+  chrono.Stop();
+  otbMsgDevMacro( << "JPEG2000ImageIO::Read took " << chrono.GetTotal() << " sec");
+
+
+  for(ReaderVectorType::iterator it = m_InternalReaders.begin();
+       it != m_InternalReaders.end();
+      ++it)
+    {
+    (*it)->Clean();
+    }
+}
+
+void JPEG2000ImageIO::LoadTileData(void * buffer, void * tile)
+{
+  opj_image_t * currentTile = static_cast<opj_image_t *>(tile);
 
-    unsigned int lWidthSrc; // Width of the input pixel in nb of pixel
-    unsigned int lHeightDest; // Height of the area where write in nb of pixel
-    unsigned int lWidthDest; // Width of the area where write in nb of pixel
-    unsigned int lStartOffsetPxlDest; // Offset where begin to write the area in the otb buffer in nb of pixel
-    unsigned int lStartOffsetPxlSrc; // Offset where begin to write the area in the otb buffer in nb of pixel
+  if(!currentTile)
+    {
+    itkExceptionMacro(<<"Tile needed but not loaded.");
+    }
 
-    ComputeOffsets(currentTile,this->GetIORegion(),lWidthSrc, lHeightDest, lWidthDest, lStartOffsetPxlDest, lStartOffsetPxlSrc);
+ // Get nb. of lines and columns of the region to read
+  int lNbLines     = this->GetIORegion().GetSize()[1];
+  int lNbColumns   = this->GetIORegion().GetSize()[0];
+  int lFirstLine   = this->GetIORegion().GetIndex()[1]; // [1... ]
+  int lFirstColumn = this->GetIORegion().GetIndex()[0]; // [1... ]
+  unsigned int lWidthSrc; // Width of the input pixel in nb of pixel
+  unsigned int lHeightDest; // Height of the area where write in nb of pixel
+  unsigned int lWidthDest; // Width of the area where write in nb of pixel
+  unsigned int lStartOffsetPxlDest; // Offset where begin to write the area in the otb buffer in nb of pixel
+  unsigned int lStartOffsetPxlSrc; // Offset where begin to write the area in the otb buffer in nb of pixel
 
-    switch (this->GetComponentType())
+  ComputeOffsets(currentTile,this->GetIORegion(),lWidthSrc, lHeightDest, lWidthDest, lStartOffsetPxlDest, lStartOffsetPxlSrc);
+
+  switch (this->GetComponentType())
+    {
+    case CHAR:
+    {
+    char *p = static_cast<char *> (buffer);
+    for (unsigned int j = 0; j < lHeightDest; ++j)
       {
-      case CHAR:
+      char* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents;
+
+      for (unsigned int k = 0; k < lWidthDest; ++k)
         {
-        char *p = static_cast<char *> (buffer);
-        for (unsigned int j = 0; j < lHeightDest; ++j)
+        for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++)
           {
-          char* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents;
-
-          for (unsigned int k = 0; k < lWidthDest; ++k)
-            {
-            for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++)
-              {
-              OPJ_INT32* data = currentTile->comps[itComp].data;
-              *(current_dst_line++) = static_cast<char> (data[lStartOffsetPxlSrc + k + j * lWidthSrc]);
-              }
-            }
+          OPJ_INT32* data = currentTile->comps[itComp].data;
+          *(current_dst_line++) = static_cast<char> (data[lStartOffsetPxlSrc + k + j * lWidthSrc]);
           }
         }
-        break;
-      case UCHAR:
+      }
+    }
+    break;
+    case UCHAR:
+    {
+    unsigned char *p = static_cast<unsigned char *> (buffer);
+    for (unsigned int j = 0; j < lHeightDest; ++j)
+      {
+      unsigned char* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents;
+
+      for (unsigned int k = 0; k < lWidthDest; ++k)
         {
-        unsigned char *p = static_cast<unsigned char *> (buffer);
-        for (unsigned int j = 0; j < lHeightDest; ++j)
+        for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++)
           {
-          unsigned char* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents;
-
-          for (unsigned int k = 0; k < lWidthDest; ++k)
-            {
-            for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++)
-              {
-              OPJ_INT32* data = currentTile->comps[itComp].data;
-              unsigned char component_val = data[lStartOffsetPxlSrc + k + j * lWidthSrc] & 0xff;
-              *(current_dst_line++) = static_cast<unsigned char> (component_val);
-              }
-            }
+          OPJ_INT32* data = currentTile->comps[itComp].data;
+          unsigned char component_val = data[lStartOffsetPxlSrc + k + j * lWidthSrc] & 0xff;
+          *(current_dst_line++) = static_cast<unsigned char> (component_val);
           }
         }
-        break;
-      case SHORT:
+      }
+    }
+    break;
+    case SHORT:
+    {
+    short *p = static_cast<short *> (buffer);
+    for (unsigned int j = 0; j < lHeightDest; ++j)
+      {
+      short* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents;
+
+      for (unsigned int k = 0; k < lWidthDest; ++k)
         {
-        short *p = static_cast<short *> (buffer);
-        for (unsigned int j = 0; j < lHeightDest; ++j)
+        for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++)
           {
-          short* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents;
-
-          for (unsigned int k = 0; k < lWidthDest; ++k)
-            {
-            for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++)
-              {
-              OPJ_INT32* data = currentTile->comps[itComp].data;
-              *(current_dst_line++) = static_cast<short> (data[lStartOffsetPxlSrc + k + j * lWidthSrc]);
-              }
-            }
+          OPJ_INT32* data = currentTile->comps[itComp].data;
+          *(current_dst_line++) = static_cast<short> (data[lStartOffsetPxlSrc + k + j * lWidthSrc]);
           }
         }
-        break;
-      case USHORT:
+      }
+    }
+    break;
+    case USHORT:
+    {
+    unsigned short *p = static_cast<unsigned short *> (buffer);
+    for (unsigned int j = 0; j < lHeightDest; ++j)
+      {
+      unsigned short* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents;
+
+      for (unsigned int k = 0; k < lWidthDest; ++k)
         {
-        unsigned short *p = static_cast<unsigned short *> (buffer);
-        for (unsigned int j = 0; j < lHeightDest; ++j)
+        for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++)
           {
-          unsigned short* current_dst_line = p + (lStartOffsetPxlDest + j * lNbColumns) * this->m_NumberOfComponents;
-
-          for (unsigned int k = 0; k < lWidthDest; ++k)
-            {
-            for (unsigned int itComp = 0; itComp < this->m_NumberOfComponents; itComp++)
-              {
-              OPJ_INT32* data = currentTile->comps[itComp].data;
-              *(current_dst_line++) = static_cast<unsigned short> (data[lStartOffsetPxlSrc + k + j * lWidthSrc] & 0xffff);
-              }
-            }
+          OPJ_INT32* data = currentTile->comps[itComp].data;
+          *(current_dst_line++) = static_cast<unsigned short> (data[lStartOffsetPxlSrc + k + j * lWidthSrc] & 0xffff);
           }
         }
-        break;
-      case INT:
-      case UINT:
-      default:
-        itkGenericExceptionMacro(<< "This data type is not handled");
-        break;
       }
     }
-  
-
-  // Now, do cache book-keeping
-  for (std::vector<JPEG2000TileCache::CachedTileType>::iterator itTile = toReadTiles.begin(); itTile < toReadTiles.end(); ++itTile)
-    {
-    m_TileCache->AddTile(itTile->first,itTile->second);
-    }
-  chrono.Stop();
-  otbMsgDevMacro( << "JPEG2000ImageIO::Read took " << chrono.GetTotal() << " sec");
-
-
-  for(ReaderVectorType::iterator it = m_InternalReaders.begin();
-       it != m_InternalReaders.end();
-      ++it)
-    {
-    (*it)->Clean();
+    break;
+    case INT:
+    case UINT:
+    default:
+      itkGenericExceptionMacro(<< "This data type is not handled");
+      break;
     }
 }
 
diff --git a/Code/IO/otbJPEG2000ImageIO.h b/Code/IO/otbJPEG2000ImageIO.h
index 615f3f738c26a977b9c0fd2396e5d0d03c6408b9..f94b0e5a4f347b6a777d841e9f10db0163f41408 100644
--- a/Code/IO/otbJPEG2000ImageIO.h
+++ b/Code/IO/otbJPEG2000ImageIO.h
@@ -121,6 +121,9 @@ private:
   /** pixel nb of octets */
   unsigned int m_BytePerPixel;
 
+  /** Load data from a tile into the buffer. 2nd argument is a
+* pointer to opj_image_t, hidden in void * to avoid forward declaration. */
+  void LoadTileData(void * buffer, void * tile);
 
   /** Support processing data in multiple threads. Used by subclasses
    * (e.g., ImageSource). */