diff --git a/Code/Visu/otbImageAlternateViewer.h b/Code/Visu/otbImageAlternateViewer.h
index 8bd373f14b8e83c61a427a0948d49622fb7694b1..480479aea8e31dad1c1af1f505c3d0a0149332b2 100644
--- a/Code/Visu/otbImageAlternateViewer.h
+++ b/Code/Visu/otbImageAlternateViewer.h
@@ -108,6 +108,10 @@ class ITK_EXPORT ImageAlternateViewer
 
     itkSetObjectMacro(Image,ImageType);
     itkGetObjectMacro(Image,ImageType);
+    
+    itkSetObjectMacro(SecondImage,ImageType);
+    itkGetObjectMacro(SecondImage,ImageType);
+
 
     itkSetMacro(DisplayExtent,RegionType);
     itkGetMacro(DisplayExtent,RegionType);
@@ -161,11 +165,19 @@ protected:
 
   RegionType GetAdditionalBufferRegion(unsigned int i);
   
-  unsigned char * CreateAdditionalBuffer(RegionType region);
+  unsigned char * CreateAdditionalBuffer(RegionType region,ImagePointerType image);
   
   virtual void MergeBuffersAndFreeMemory(std::vector<unsigned char *> bufferList, 
 					 std::vector<RegionType> bufferRegionList);
+
+  virtual void AdditionalRedraw(void);
+
+  virtual void DecorationRedraw(void);
   
+  virtual void DrawRegionBoundary(RegionType& region);
+
+  virtual long IndexInOldGrid(PointType point, PointType oldUpperLeft, SpacingType spacing, SizeType size);
+
   RegionType ComputeRequestedRegion(RegionType &region);
  /**PrintSelf method */
   virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;
@@ -230,9 +242,24 @@ private:
 
   /** Prevent messing around with simultaneous update */
   bool m_Updating;
-
+  /** Region splitter */
   SplitterPointerType m_Splitter;
-
+  /** Swith the drag mode */
+  bool m_Drag;
+  /** Count drag events */
+  unsigned int m_DragEventCounter;
+  /** Remember the mouse pos in drag mode */
+  IndexType m_OldMousePos;
+
+  /** The second image */
+  ImagePointerType m_SecondImage;
+  /** The subwindow region */
+  RegionType m_SubWindowRegion;
+  /** subwindow mode switch */
+  bool m_SubWindowMode;
+/** subwindow mode switch */
+  bool m_SubWindowMove;
+  
 };
 }// End namespace otb
 #ifndef OTB_MANUAL_INSTANTIATION
diff --git a/Code/Visu/otbImageAlternateViewer.txx b/Code/Visu/otbImageAlternateViewer.txx
index 3db902d6a0099919981b10757943f5b4968386dc..9daddfafe794106c861ede65a27001f32bd2cd47 100644
--- a/Code/Visu/otbImageAlternateViewer.txx
+++ b/Code/Visu/otbImageAlternateViewer.txx
@@ -24,7 +24,7 @@ PURPOSE.  See the above copyright notices for more information.
 #include "otbMath.h"
 #include "itkTimeProbe.h"
 #include "GL/glu.h"
-
+#include "itkMacro.h"
 
 namespace otb
 {
@@ -55,8 +55,8 @@ namespace otb
     bsplineInterpolator->SetSplineOrder(3);
 
 
-    m_ZoomInInterpolator = WindowedSincInterpolatorType::New();
-    // m_ZoomInInterpolator=DefaultInterpolatorType::New();
+    // m_ZoomInInterpolator = WindowedSincInterpolatorType::New();
+    m_ZoomInInterpolator=DefaultInterpolatorType::New();
     // m_ZoomInInterpolator=bsplineInterpolator;
 
     m_ZoomOutInterpolator = DefaultInterpolatorType::New();
@@ -89,6 +89,14 @@ namespace otb
     m_ZoomState = 0;
     m_Splitter=SplitterType::New();
     m_Updating = false;
+    m_Drag = false;
+    m_DragEventCounter = 0;
+    m_OldMousePos.Fill(0);
+    
+    m_SubWindowRegion.SetIndex(index);
+    m_SubWindowRegion.SetSize(nullSize);
+    m_SubWindowMode = false;
+    m_SubWindowMove = false;
   }
   /**
    * Destructor
@@ -156,26 +164,35 @@ namespace otb
   {
     if(m_Updating)
       return;
-    m_Updating = true;
     // avoid odd sizes
     if(w%2==1)
       w+=1;
     if(h%2==1)
       h+=1;
 
-    IndexType index;
-    SizeType size;
+    IndexType index,subWindowIndex;
+    SizeType size,subWindowSize;
     m_OldDisplayExtent=m_DisplayExtent;
     index[0]=x;
     index[1]=y;
     size[0]=w;
     size[1]=h; 
+
+    subWindowIndex[0] = 3*static_cast<long>(size[0])/8;
+    subWindowIndex[1] = 3*static_cast<long>(size[1])/8;
+    subWindowSize[0] = size[0]/4;
+    subWindowSize[1] = size[1]/4;
+
+    m_SubWindowRegion.SetIndex(subWindowIndex);
+    m_SubWindowRegion.SetSize(subWindowSize);
+
     m_DisplayExtent.SetIndex(index);
     m_DisplayExtent.SetSize(size);
+
+    
     //comment std::cout<<"New display extent: "<<m_DisplayExtent<<std::endl;
     this->Fl_Gl_Window::resize(x,y,w,h);
     this->redraw();
-    m_Updating = false;
   }
   /**
    * Set view mode to RGB.
@@ -224,28 +241,101 @@ namespace otb
   ImageAlternateViewer<TPixel>
   ::draw(void)
   {
-    IncrementalOpenGlBufferUpdate();
-    ResetOpenGlContext();
-    this->Draw(m_OpenGlBuffer,m_BufferedRegion);
-    
+    if(!m_Updating)
+      {
+	m_Updating = true;
+	IncrementalOpenGlBufferUpdate();
+	ResetOpenGlContext();
+	this->Draw(m_OpenGlBuffer,m_BufferedRegion);
+	//COMMENT std::cout<<"Buffered region: "<<m_BufferedRegion<<std::endl;
+	
+	if(!m_Drag)
+	  {
+	    AdditionalRedraw();
+	  }
+	m_Updating = false;
+      }
+  }
+
+
+  template <class TPixel>
+  void
+  ImageAlternateViewer<TPixel>
+  ::AdditionalRedraw(void)
+  {
     std::vector<unsigned char *> bufferList;
     std::vector<RegionType> bufferRegionList;
-
+     
     if(m_BufferedRegion!=m_DisplayExtent)
       {
 	for(unsigned int i = 0;i<8;++i)
 	  {
 	    RegionType additionalBufferRegion = GetAdditionalBufferRegion(i);
-	    //comment std::cout<<"Additional region required: "<<additionalBufferRegion<<std::endl;
-	    unsigned char * additionalBuffer = CreateAdditionalBuffer(additionalBufferRegion);
+	    //COMMENT std::cout<<"Additional region required: "<<additionalBufferRegion<<std::endl;
+	    unsigned char * additionalBuffer = CreateAdditionalBuffer(additionalBufferRegion,m_Image);
 	    this->Draw(additionalBuffer,additionalBufferRegion);
 	    bufferList.push_back(additionalBuffer);
 	    bufferRegionList.push_back(additionalBufferRegion);
 	  }
+	DecorationRedraw();
 	MergeBuffersAndFreeMemory(bufferList,bufferRegionList);
       }
+    if(m_SubWindowMode)
+      {
+	unsigned char * subWindowBuffer = CreateAdditionalBuffer(m_SubWindowRegion,m_SecondImage);
+	this->Draw(subWindowBuffer,m_SubWindowRegion);
+	delete [] subWindowBuffer;
+      }
+    DecorationRedraw();
+  }
+
+
+  template <class TPixel>
+  void
+  ImageAlternateViewer<TPixel>
+  ::DecorationRedraw(void)
+  {
+    if(m_SubWindowMode)
+      {
+	this->DrawRegionBoundary(m_SubWindowRegion);
+      }
+    itk::OStringStream oss;
+    oss<<"Zoom: "<<m_OpenGlIsotropicZoom<<", scale: "<<m_SpacingZoomFactor;
+    gl_color(FL_RED);
+    gl_font(FL_SCREEN_BOLD,10);
+    gl_draw(oss.str().c_str(),static_cast<int>(m_DisplayExtent.GetIndex()[0])+10,static_cast<int>(m_DisplayExtent.GetIndex()[1])+10);
+    swap_buffers();
+    glFlush();
+  }
+
+  template <class TPixel>
+  long 
+  ImageAlternateViewer<TPixel>
+  ::IndexInOldGrid(PointType point, PointType oldUpperLeft, SpacingType spacing, SizeType size)
+  {
+    long resp;
+    double x = (point[0]-oldUpperLeft[0])/spacing[0];
+    double y = (point[1]-oldUpperLeft[1])/spacing[1];
+
+   // std::cout<<"x: "<<x<<", y: "<<y<<std::endl;
+    
+    if ((vcl_floor(x)!=x)||(vcl_floor(y)!=y))
+      {
+	resp=-1;
+      }
+    else if(x<0||x>size[0]||y<0||y>size[1])
+      {
+	resp = -1;
+      }
+    else 
+      {
+	resp = 4*(static_cast<long>(y)*size[0]+static_cast<long>(x));
+      }
+
+    return resp;
   }
 
+
   template <class TPixel>
   void
   ImageAlternateViewer<TPixel>
@@ -255,8 +345,19 @@ namespace otb
     focusOffset[0]=static_cast<long>(static_cast<double>(m_ViewedRegionCenter[0]-m_OldViewedRegionCenter[0])/m_SpacingZoomFactor);
     focusOffset[1]=static_cast<long>(static_cast<double>(m_ViewedRegionCenter[1]-m_OldViewedRegionCenter[1])/m_SpacingZoomFactor);
 
+    //COMMENT std::cout<<"Focus offset: "<<focusOffset<<std::endl;
 
     IndexType newBufferedRegionIndex;
+
+    SizeType newBufferedRegionSize;
+
+    newBufferedRegionSize[0]=static_cast<unsigned long>(static_cast<double>((m_BufferedRegion.GetSize()[0])*m_OldSpacingZoomFactor/m_SpacingZoomFactor));
+    newBufferedRegionSize[1]=static_cast<unsigned long>(static_cast<double>((m_BufferedRegion.GetSize()[1])*m_OldSpacingZoomFactor/m_SpacingZoomFactor));
+
+    m_OldBufferedRegion = m_BufferedRegion;
+
+    m_BufferedRegion.SetSize(newBufferedRegionSize);
+
     newBufferedRegionIndex[0]=(static_cast<long>(m_DisplayExtent.GetSize()[0])
 			       -static_cast<long>(m_BufferedRegion.GetSize()[0]))/2;
     newBufferedRegionIndex[1]=(static_cast<long>(m_DisplayExtent.GetSize()[1])
@@ -265,22 +366,195 @@ namespace otb
     newBufferedRegionIndex[1]-=focusOffset[1];
     //std::cout<<"NewBufferedRegionIndex: "<<newBufferedRegionIndex<<std::endl;
     m_BufferedRegion.SetIndex(newBufferedRegionIndex);
-    m_OldViewedRegionCenter = m_ViewedRegionCenter;
+    // m_OldViewedRegionCenter = m_ViewedRegionCenter;
     
+    //std::cout<<"New buffered region: "<<m_BufferedRegion<<std::endl;
     
+    PointType center;
+    m_Image->TransformIndexToPhysicalPoint(m_ViewedRegionCenter,center);
+    //COMMENT std::cout<<"Center: "<<center<<std::endl;
 
     if(m_SpacingZoomFactor != m_OldSpacingZoomFactor)
       {
-	SizeType newSize;
-	newSize.Fill(0);
-	m_BufferedRegion.SetSize(newSize);
-	IndexType newIndex;
-	newIndex[0]= static_cast<long>(m_DisplayExtent.GetSize()[0])/2;
-	newIndex[1]= static_cast<long>(m_DisplayExtent.GetSize()[1])/2;
-	m_BufferedRegion.SetIndex(newIndex);
+	m_BufferedRegion.Crop(m_DisplayExtent);
+// 	std::cout<<"New buffered region2 "<<m_BufferedRegion<<std::endl;
+
+
+	SpacingType spacing = m_Image->GetSpacing()*m_SpacingZoomFactor;
+	SpacingType oldSpacing = m_Image->GetSpacing()*m_OldSpacingZoomFactor;
+	
+	PointType origin;
+	origin[0]=center[0]-(static_cast<double>(this->m_DisplayExtent.GetSize()[0])/2-1)*spacing[0];
+	origin[1]=center[1]-(static_cast<double>(this->m_DisplayExtent.GetSize()[1])/2-1)*spacing[1];
+	
+	PointType oldOrigin;
+	oldOrigin[0]=center[0]-(static_cast<double>(this->m_DisplayExtent.GetSize()[0])/2-1)*oldSpacing[0];
+	oldOrigin[1]=center[1]-(static_cast<double>(this->m_DisplayExtent.GetSize()[1])/2-1)*oldSpacing[1];
+		
+	PointType oldBufferedUpperLeft;
+	oldBufferedUpperLeft[0]=oldOrigin[0]+static_cast<double>(m_OldBufferedRegion.GetIndex()[0])*oldSpacing[0];
+	oldBufferedUpperLeft[1]=oldOrigin[1]+static_cast<double>(m_OldBufferedRegion.GetIndex()[1])*oldSpacing[1];
+
+	PointType bufferedUpperLeft;
+	bufferedUpperLeft[0]=origin[0]+static_cast<double>(m_BufferedRegion.GetIndex()[0])*spacing[0];
+	bufferedUpperLeft[1]=origin[1]+static_cast<double>(m_BufferedRegion.GetIndex()[1])*spacing[1];
+
+	//std::cout<<"OldBufferedRegion: "<<m_OldBufferedRegion<<std::endl;
+// 	std::cout<<"DisplayExtent: "<<m_DisplayExtent<<std::endl;
+// 	std::cout<<"Center: "<<center<<std::endl;
+// 	std::cout<<"Spacing: "<<spacing<<std::endl;
+// 	std::cout<<"OldSpacing: "<<oldSpacing<<std::endl;
+// 	std::cout<<"BufferedUpperLeft: "<<bufferedUpperLeft<<std::endl;
+// 	std::cout<<"oldBufferedUpperLeft: "<<oldBufferedUpperLeft<<std::endl;
+	
+
+	unsigned char *  newBuffer = NULL;
+	unsigned int bufferLenght = 4*m_BufferedRegion.GetSize()[0]*m_BufferedRegion.GetSize()[1];
+   
+	newBuffer = new unsigned char[bufferLenght];
+	typename ImageListType::Pointer bandList;
+	unsigned int index = 0;
+	PixelType interpolatedValue = 0;
+	PointType interpolatedPos;
+	interpolatedPos.Fill(0);
+	unsigned int numberOfSplits=1;
+	
+	unsigned int optiCount = 0;
+
+	if(m_SpacingZoomFactor>0)
+	  {
+	    numberOfSplits=max((static_cast<unsigned int>(m_SpacingZoomFactor))*(static_cast<unsigned int>(m_SpacingZoomFactor)),1U);
+	  }
+	
+	unsigned int splitterNumberOfSplits = m_Splitter->GetNumberOfSplits(m_BufferedRegion,numberOfSplits);
+
+	//std::cout<<"numberOfSplits: "<<numberOfSplits<<std::endl;
+	//std::cout<<"splitterNumberOfSplits: "<<splitterNumberOfSplits<<std::endl;
+	
+	for(unsigned int splitIndex = 0;splitIndex<splitterNumberOfSplits;++splitIndex)
+	  {
+	    RegionType splitRegion = m_Splitter->GetSplit(splitIndex,splitterNumberOfSplits,m_BufferedRegion);
+	    //std::cout<<splitRegion<<std::endl;
+	    m_RequestedRegion = ComputeRequestedRegion(splitRegion);
+	    if(! m_RequestedRegion.Crop(m_Image->GetLargestPossibleRegion()))
+	      {
+		SizeType nullSize;
+		nullSize.Fill(0);
+		IndexType nullIndex;
+		nullIndex.Fill(0);
+		m_RequestedRegion.SetSize(nullSize);
+		m_RequestedRegion.SetIndex(nullIndex);
+	      }
+	    //std::cout<<"Image Requested Region: "<<m_RequestedRegion<<std::endl;
+	    
+	    // 	if(!m_RequestedRegion.IsInside(bandList->GetNthElement(m_RedChannelIndex)->GetBufferedRegion()))
+	    // 	  {
+	    //std::cout<<"Requested region: "<<m_RequestedRegion<<std::endl;
+	    m_DecompositionFilter = VectorImageDecompositionFilterType::New();
+	    m_DecompositionFilter->SetInput(m_Image);
+	    bandList = m_DecompositionFilter->GetOutput();
+	    bandList->UpdateOutputInformation();
+	    bandList->GetNthElement(m_RedChannelIndex)->SetRequestedRegion(m_RequestedRegion);
+	    if(m_ViewModelIsRGB)
+	      {
+		bandList->GetNthElement(m_GreenChannelIndex)->SetRequestedRegion(m_RequestedRegion);
+		bandList->GetNthElement(m_BlueChannelIndex)->SetRequestedRegion(m_RequestedRegion);
+	      }
+	    bandList->PropagateRequestedRegion();
+	    bandList->UpdateOutputData();
+	    
+	    // 	  }
+
+	    PointType upperLeft;
+	    upperLeft[0]=origin[0]+static_cast<double>(splitRegion.GetIndex()[0])*spacing[0];
+	    upperLeft[1]=origin[1]+static_cast<double>(splitRegion.GetIndex()[1])*spacing[1];
+
+
+	    interpolatedPos[1]=upperLeft[1];
+	    for(unsigned int j = 0;j<splitRegion.GetSize()[1];++j)
+	      {
+		interpolatedPos[0]=upperLeft[0];
+		for(unsigned int i = 0;i<splitRegion.GetSize()[0];++i)
+		  {
+		    
+		    long indexInOldBuffer = IndexInOldGrid(interpolatedPos,oldBufferedUpperLeft,oldSpacing,m_OldBufferedRegion.GetSize());
+		    // std::cout<<interpolatedPos<<" "<<indexInOldBuffer<<std::endl;
+		    if(indexInOldBuffer>0)
+		      {
+			newBuffer[index] = m_OpenGlBuffer[indexInOldBuffer];
+			newBuffer[index+1] = m_OpenGlBuffer[indexInOldBuffer+1];
+			newBuffer[index+2] = m_OpenGlBuffer[indexInOldBuffer+2];
+			newBuffer[index+3] = m_OpenGlBuffer[indexInOldBuffer+3];
+			index+=4;
+			optiCount++;
+		      }
+		    else
+		      {
+			m_ZoomInInterpolator->SetInputImage(bandList->GetNthElement(m_RedChannelIndex));
+			if( m_ZoomInInterpolator->IsInsideBuffer(interpolatedPos))
+			  {
+			    interpolatedValue = static_cast<PixelType>(m_ZoomInInterpolator->Evaluate(interpolatedPos));
+			  }
+			else
+			  {
+			    interpolatedValue = 0;
+			  }
+			newBuffer[index] = Normalize(interpolatedValue,m_RedChannelIndex);
+			if(m_ViewModelIsRGB)
+			  {
+			    m_ZoomInInterpolator->SetInputImage(bandList->GetNthElement(m_GreenChannelIndex));
+			    if( m_ZoomInInterpolator->IsInsideBuffer(interpolatedPos))
+			      {
+				interpolatedValue = static_cast<PixelType>( m_ZoomInInterpolator->Evaluate(interpolatedPos));
+			      }
+			    else
+			      {
+				interpolatedValue = 0;
+			      }
+			    newBuffer[index+1] = Normalize(interpolatedValue,m_GreenChannelIndex);
+			    m_ZoomInInterpolator->SetInputImage(bandList->GetNthElement(m_BlueChannelIndex));
+			    if( m_ZoomInInterpolator->IsInsideBuffer(interpolatedPos))
+			      {
+				interpolatedValue = static_cast<PixelType>(m_ZoomInInterpolator->Evaluate(interpolatedPos));
+			      }
+			    else
+			      {
+				interpolatedValue = 0;
+			      }
+			    newBuffer[index+2] = Normalize(interpolatedValue,m_BlueChannelIndex);
+			    newBuffer[index+3] = 255;
+			    index+=4;
+			  }
+			else
+			  {
+			    newBuffer[index+1] = Normalize(interpolatedValue,m_RedChannelIndex);
+			    newBuffer[index+2] = Normalize(interpolatedValue,m_RedChannelIndex);
+			    newBuffer[index+3] = 255;
+			    index+=4; 
+			  }
+ 		      }
+		    interpolatedPos[0] +=spacing[0];
+		  }
+		interpolatedPos[1] +=spacing[1];
+	      }
+	  }
+	if(m_OpenGlBuffer!=NULL)
+	  {
+	    delete [] m_OpenGlBuffer;
+	  }
+	m_OpenGlBuffer = newBuffer;
+
 	m_OldSpacingZoomFactor = m_SpacingZoomFactor;
+	//std::cout<<"Optimisation called "<<optiCount<<" times over "<<m_BufferedRegion.GetNumberOfPixels()<<std::endl;
       }
-    //comment std::cout<<"New buffered region: "<<m_BufferedRegion<<std::endl;
+   
+//     std::cout<<"BufferedRegion: "<<m_BufferedRegion<<std::endl;
+//     std::cout<<"OldBufferedRegion: "<<m_OldBufferedRegion<<std::endl;
+//     std::cout<<"BufferedUpperLeft: "<<bufferedUpperLeft<<std::endl;
+//     std::cout<<"OldBufferedUpperLeft: "<<oldBufferedUpperLeft<<std::endl;
+//     std::cout<<"Spacing: "<<spacing<<std::endl;
+//     std::cout<<"OldSpacing: "<<oldSpacing<<std::endl;
+  
   }
   
   template <class TPixel>
@@ -363,89 +637,6 @@ namespace otb
 	index[1] = min(deLR[1],bufLR[1]);
 	size[0]  = max(deLR[0]-bufLR[0],0L);
 	size[1]  = max(deLR[1]-bufLR[1],0L);
-
-	// case 0:
-	// 	index[0]=deIndex[0];
-	// 	index[1]=deIndex[1];
-	// 	size[0]=max(bufIndex[0]-deIndex[0],0L);
-	// 	size[1]=max(bufIndex[1]-deIndex[1],0L);
-	// 	break;
-
-	//       case 1:
-	// 	index[0]=max(bufIndex[0],0L);
-	// 	index[1]=deIndex[1];
-	// 	// size[0]=max(0L,static_cast<long>(bufSize[0])-vcl_abs(bufIndex[0]));
-	// 	size[0]=max(0L,min(static_cast<long>(bufSize[0])-vcl_abs(bufIndex[0]),static_cast<long>(deSize[0])-index[0]));
-	// 	size[1]=max(bufIndex[1]-deIndex[1],0L);
-	// 	break;
-	
-	//       case 2:
-	// 	index[0]=bufIndex[0]+bufSize[0];
-	// 	index[1]=deIndex[1];
-	// 	size[0]=max(deIndex[0]+static_cast<long>(deSize[0])-bufIndex[0]-static_cast<long>(bufSize[0]),0L);
-	// 	size[1]=max(bufIndex[1]-deIndex[1],0L);
-	// 	break;
-
-	//       case 3:
-	// 	index[0]=deIndex[0];
-	// 	index[1]=max(bufIndex[1],0L);
-	// 	size[0]=max(bufIndex[0]-deIndex[0], 0L);
-	// 	// size[1]=max(0L,static_cast<long>(bufSize[1])-vcl_abs(bufIndex[1]));
-	// 	size[1]=max(0L,min(static_cast<long>(bufSize[1])-vcl_abs(bufIndex[1]),static_cast<long>(deSize[1])-index[1]));
-	
-	// 	break;
-
-	//       case 4:
-	// 	index[0]=bufIndex[0]+bufSize[0];
-	// 	index[1]=max(bufIndex[1],0L);
-	// 	size[0]=max(deIndex[0]+static_cast<long>(deSize[0])-bufIndex[0]-static_cast<long>(bufSize[0]),0L);
-	// 	// size[1]=max(0L,static_cast<long>(bufSize[1])-vcl_abs(bufIndex[1]));
-	// 	size[1]=max(0L,min(static_cast<long>(bufSize[1])-vcl_abs(bufIndex[1]),static_cast<long>(deSize[1])-index[1]));
-
-	// 	break;
-
-	//       case 5:
-	// 	index[0]=deIndex[0];
-	// 	index[1]=bufIndex[1]+bufSize[1];
-	// 	size[0]=max(bufIndex[0]-deIndex[0],0L);
-	// 	size[1]=max(deIndex[1]+static_cast<long>(deSize[1])-bufIndex[1]-static_cast<long>(bufSize[1]),0L);
-	// 	break;
-
-	//       case 6:
-	// 	index[0]=max(bufIndex[0],0L);
-	// 	index[1]=bufIndex[1]+bufSize[1];
-	// 	// size[0]=max(0L,static_cast<long>(bufSize[0])-vcl_abs(bufIndex[0]));
-	// 	size[0]=max(0L,min(static_cast<long>(bufSize[0])-vcl_abs(bufIndex[0]),static_cast<long>(deSize[0])-index[0]));
-	// 	size[1]=max(deIndex[1]+static_cast<long>(deSize[1])-bufIndex[1]-static_cast<long>(bufSize[1]),0L);
-	// 	break;
-
-	//       case 7:
-	// 	index[0]=bufIndex[0]+bufSize[0];
-	// 	index[1]=bufIndex[1]+bufSize[1];
-	// 	size[0]=max(deIndex[0]+static_cast<long>(deSize[0])-bufIndex[0]-static_cast<long>(bufSize[0]),0L);
-	// 	size[1]=max(deIndex[1]+static_cast<long>(deSize[1])-bufIndex[1]-static_cast<long>(bufSize[1]),0L);
-	// 	break;
-
-	// size[0]=deSize[0];
-	// 	size[1]=(bufIndex[1] > deIndex[1] ? bufIndex[1]-deIndex[1] : 0);
-	// 	index[0]=deIndex[0];
-	// 	index[1]=deIndex[1];
-	// 	break;
-	//       case 1:
-	
-	// 	break;
-	//       case 2:
-	// 	size[0]=(deIndex[0]+deSize[0] > bufIndex[0]+bufSize[0] ? deIndex[0]+deSize[0]-bufIndex[0]-bufSize[0] : 0);
-	// 	size[1]=bufSize[1];
-	// 	index[0]=bufIndex[0]+bufSize[0];
-	// 	index[1]=max(bufIndex[1],0L);
-	// 	break;
-	//       case 3:
-	// 	size[0]=deSize[0];
-	// 	size[1]=(deIndex[1]+deSize[1] > bufIndex[1]+bufSize[1] ?deIndex[1]+deSize[1]-bufIndex[1]-bufSize[1] : 0);
-	// 	index[0]=deIndex[0];
-	// 	index[1]=bufIndex[1]+bufSize[1];
-	// 	break;
       }
     region.SetSize(size);
     region.SetIndex(index);
@@ -490,6 +681,11 @@ namespace otb
     bufferedLowerRight[0]=bufferedUpperLeft[0]+static_cast<double>(m_BufferedRegion.GetSize()[0]-1)*spacing[0];
     bufferedLowerRight[1]=bufferedUpperLeft[1]+static_cast<double>(m_BufferedRegion.GetSize()[1]-1)*spacing[1];
 
+    //COMMENT std::cout<<"UpperLeft: "<<upperLeft<<std::endl;
+    //COMMENT std::cout<<"LowerRight: "<<lowerRight<<std::endl;
+    //COMMENT std::cout<<"BufferedUpperLeft: "<<bufferedUpperLeft<<std::endl;
+    //COMMENT std::cout<<"BufferedLowerRight: "<<bufferedLowerRight<<std::endl;
+
     IndexType lowerRightIndex;
     IndexType requestedIndex;
     SizeType requestedSize;
@@ -510,7 +706,7 @@ namespace otb
   template <class TPixel>
   unsigned char *
   ImageAlternateViewer<TPixel>
-  ::CreateAdditionalBuffer(RegionType region)
+  ::CreateAdditionalBuffer(RegionType region,ImagePointerType image)
   {
     itk::TimeProbe total,filter,interpolation;
     total.Start();
@@ -537,23 +733,22 @@ namespace otb
     interpolatedPos.Fill(0);
     unsigned int numberOfSplits=1;
 
-    if(m_ZoomState>0)
+    if(m_SpacingZoomFactor>0)
       {
-	numberOfSplits=(m_ZoomState+1)*(m_ZoomState+1);
+	numberOfSplits=max((static_cast<unsigned int>(m_SpacingZoomFactor))*(static_cast<unsigned int>(m_SpacingZoomFactor)),1U);
       }
-
     
     unsigned int splitterNumberOfSplits = m_Splitter->GetNumberOfSplits(region,numberOfSplits);
     
-  //   std::cout<<"ZoomState: "<<m_ZoomState<<std::endl;
-//     std::cout<<"Number of splits: "<<numberOfSplits<<std::endl;
-//     std::cout<<"Zoom out number of splits: "<<splitterNumberOfSplits<<std::endl;
+    //   std::cout<<"ZoomState: "<<m_ZoomState<<std::endl;
+    //     std::cout<<"Number of splits: "<<numberOfSplits<<std::endl;
+    //     std::cout<<"Zoom out number of splits: "<<splitterNumberOfSplits<<std::endl;
     
-    SpacingType spacing = m_Image->GetSpacing()*m_SpacingZoomFactor;
+    SpacingType spacing = image->GetSpacing()*m_SpacingZoomFactor;
 
     PointType center;
-    m_Image->TransformIndexToPhysicalPoint(m_ViewedRegionCenter,center);
-    
+    image->TransformIndexToPhysicalPoint(m_ViewedRegionCenter,center);
+    //COMMENT std::cout<<"Center(ad): "<<center<<std::endl;
     PointType origin;
     origin[0]=center[0]-(static_cast<double>(this->m_DisplayExtent.GetSize()[0])/2-1)*spacing[0];
     origin[1]=center[1]-(static_cast<double>(this->m_DisplayExtent.GetSize()[1])/2-1)*spacing[1];
@@ -565,29 +760,39 @@ namespace otb
 	PointType upperLeft;
 	upperLeft[0]=origin[0]+(static_cast<double>(splitRegion.GetIndex()[0]))*spacing[0];
 	upperLeft[1]=origin[1]+(static_cast<double>(splitRegion.GetIndex()[1]))*spacing[1];
-
+	//COMMENT std::cout<<"Loop upper left: "<<upperLeft<<std::endl;
 	m_RequestedRegion = ComputeRequestedRegion(splitRegion);
-	m_RequestedRegion.Crop(m_Image->GetLargestPossibleRegion());
-
+	//	std::cout<<"Additional requested region: "<<m_RequestedRegion<<std::endl;
+	//	std::cout<<"Largest possible region: "<<image->GetLargestPossibleRegion()<<std::endl;
+	if(!m_RequestedRegion.Crop(image->GetLargestPossibleRegion()))
+	  {
+	    SizeType nullSize;
+	    nullSize.Fill(0);
+	    IndexType nullIndex;
+	    nullIndex.Fill(0);
+	    m_RequestedRegion.SetSize(nullSize);
+	    m_RequestedRegion.SetIndex(nullIndex);
+	  }
+	//std::cout<<"Additional cropped requested region: "<<m_RequestedRegion<<std::endl;
 	
-// 	if(!m_RequestedRegion.IsInside(bandList->GetNthElement(m_RedChannelIndex)->GetBufferedRegion()))
-// 	  {
-	    m_DecompositionFilter = VectorImageDecompositionFilterType::New();
-	    m_DecompositionFilter->SetInput(m_Image);
-	    bandList = m_DecompositionFilter->GetOutput();
-	    //std::cout<<"Requested region: "<<m_RequestedRegion<<std::endl;
-	    bandList->UpdateOutputInformation();
-	    bandList->GetNthElement(m_RedChannelIndex)->SetRequestedRegion(m_RequestedRegion);
-	    if(m_ViewModelIsRGB)
-	      {
-		bandList->GetNthElement(m_GreenChannelIndex)->SetRequestedRegion(m_RequestedRegion);
-		bandList->GetNthElement(m_BlueChannelIndex)->SetRequestedRegion(m_RequestedRegion);
-	      }
-	    bandList->PropagateRequestedRegion();
-	    bandList->UpdateOutputData();
+	// 	if(!m_RequestedRegion.IsInside(bandList->GetNthElement(m_RedChannelIndex)->GetBufferedRegion()))
+	// 	  {
+	m_DecompositionFilter = VectorImageDecompositionFilterType::New();
+	m_DecompositionFilter->SetInput(image);
+	bandList = m_DecompositionFilter->GetOutput();
+	
+	bandList->UpdateOutputInformation();
+	bandList->GetNthElement(m_RedChannelIndex)->SetRequestedRegion(m_RequestedRegion);
+	if(m_ViewModelIsRGB)
+	  {
+	    bandList->GetNthElement(m_GreenChannelIndex)->SetRequestedRegion(m_RequestedRegion);
+	    bandList->GetNthElement(m_BlueChannelIndex)->SetRequestedRegion(m_RequestedRegion);
+	  }
+	bandList->PropagateRequestedRegion();
+	bandList->UpdateOutputData();
 
-	    filter.Stop();
-// 	  }
+	filter.Stop();
+	// 	  }
 
 	interpolation.Start();
 	interpolatedPos[1]=upperLeft[1];
@@ -664,26 +869,97 @@ namespace otb
   ImageAlternateViewer<TPixel>
   ::handle(int event)
   {
-    if(!m_Updating)
-      m_Updating=true;
+    if(m_Updating)
+      return 0;
     switch(event)
       {
       case FL_PUSH:
 	{
-	  int x = Fl::event_x();
-	  int y = Fl::event_y();
-	  SpacingType spacing = m_Image->GetSpacing()*m_SpacingZoomFactor;
-	  PointType origin;
-	  origin[0]=static_cast<double>(m_ViewedRegionCenter[0])-static_cast<double>(this->m_DisplayExtent.GetSize()[0]/2)*spacing[0];
-	  origin[1]=static_cast<double>(m_ViewedRegionCenter[1])-static_cast<double>(this->m_DisplayExtent.GetSize()[1]/2)*spacing[1];
-	    
-	  PointType newCenter;
-	  newCenter[0]=origin[0]+static_cast<double>(x)*spacing[0];
-	  newCenter[1]=origin[1]+static_cast<double>(y)*spacing[1];
+	  if(!m_Drag)
+	    {
+	      m_OldMousePos[0]= static_cast<long int>(static_cast<double>(m_DisplayExtent.GetSize()[0]/2)
+						      +(static_cast<double>(Fl::event_x())-static_cast<double>(m_DisplayExtent.GetSize()[0]/2))/m_OpenGlIsotropicZoom);
+	      m_OldMousePos[1]= static_cast<long int>(static_cast<double>(m_DisplayExtent.GetSize()[1]/2)
+						      +(static_cast<double>(Fl::event_y())-static_cast<double>(m_DisplayExtent.GetSize()[1]/2))/m_OpenGlIsotropicZoom);
+	      //  m_OldMousePos[1]= Fl::event_y();
+  	      m_Drag=true;
+	      m_DragEventCounter=0;
+	      
+	      if(m_SubWindowRegion.IsInside(m_OldMousePos))
+		{
+		  m_SubWindowMove = true;
+		}
+	      else
+		{
+		  m_OldViewedRegionCenter = m_ViewedRegionCenter;
+		}
+	    }
+ 	  return 1;  
+ 	}
+
+      case FL_DRAG:
+	{
+	  //std::cout<<"FL_DRAG"<<std::endl;
+ 	  m_Drag=true;
+	  
+	  int x =static_cast<int>(static_cast<double>(m_DisplayExtent.GetSize()[0]/2)
+				  +(Fl::event_x()-static_cast<double>(m_DisplayExtent.GetSize()[0]/2))/m_OpenGlIsotropicZoom);
+	  int y = static_cast<long int>(static_cast<double>(m_DisplayExtent.GetSize()[1]/2)
+					+(Fl::event_y()-static_cast<double>(m_DisplayExtent.GetSize()[1]/2))/m_OpenGlIsotropicZoom);
+	  if(Fl::event_button()==FL_MIDDLE_MOUSE)
+	    {
+	      if(!m_SubWindowMode)
+		m_SubWindowMode = true;
+	      IndexType newIndex;
+	      SizeType newSize;
+
+	      newIndex[0]=(x>m_OldMousePos[0] ? m_OldMousePos[0] : x);
+	      newIndex[1]=(y>m_OldMousePos[1] ? m_OldMousePos[1] : y);
+	      newSize[0]=vcl_abs(x-m_OldMousePos[0]);
+	      newSize[1]=vcl_abs(y-m_OldMousePos[1]);
+	      m_SubWindowRegion.SetIndex(newIndex);
+	      m_SubWindowRegion.SetSize(newSize);
+	      //COMMENT std::cout<<"new subWindowRegion: "<<m_SubWindowRegion<<std::endl;
+	      this->redraw();
+	      m_DragEventCounter++;
+	    }
+	  else if(m_SubWindowMove)
+	    {
+	      IndexType index = m_SubWindowRegion.GetIndex();
+	      index[0]+=(x-m_OldMousePos[0]);
+	      index[1]+=(y-m_OldMousePos[1]);
+	      m_SubWindowRegion.SetIndex(index);
+	      m_OldMousePos[0]=x;
+	      m_OldMousePos[1]=y;
+	      this->redraw();
+	      m_DragEventCounter++;
+	    }
+	  
+	  else
+	    {
+	      SpacingType spacing = m_Image->GetSpacing()*m_SpacingZoomFactor;
+	      PointType origin;
+	      origin[0]=static_cast<double>(m_OldViewedRegionCenter[0])-static_cast<double>(this->m_DisplayExtent.GetSize()[0]/2)*spacing[0];
+	      origin[1]=static_cast<double>(m_OldViewedRegionCenter[1])-static_cast<double>(this->m_DisplayExtent.GetSize()[1]/2)*spacing[1];
+	      PointType newCenter;
+	      newCenter[0]=origin[0]+static_cast<double>(m_OldMousePos[0]-x+static_cast<long>(this->m_DisplayExtent.GetSize()[0])/2)*spacing[0];
+	      newCenter[1]=origin[1]+static_cast<double>(m_OldMousePos[1]-y+static_cast<long>(this->m_DisplayExtent.GetSize()[1])/2)*spacing[1];
+	      //COMMENT std::cout<<"Drag focus offset: "<<m_OldMousePos[0]-x<<", "<<m_OldMousePos[1]-y<<std::endl;
+	      m_Image->TransformPhysicalPointToIndex(newCenter,m_ViewedRegionCenter);
+	      this->redraw();
+	      m_DragEventCounter++;
+	    }
+	  
+	  DecorationRedraw();
+	  return 1;
+	}
+
+      case FL_RELEASE:
+	{
 	  m_OldViewedRegionCenter = m_ViewedRegionCenter;
-	  m_Image->TransformPhysicalPointToIndex(newCenter,m_ViewedRegionCenter);
-	  this->redraw();
-	  m_Updating=false;
+	  m_Drag=false;
+	  AdditionalRedraw();
+	  m_SubWindowMove = false;
 	  return 1;
 	}
 
@@ -691,38 +967,46 @@ namespace otb
 	{
 	  int dy = Fl::event_dy();
 	  int oldState = m_ZoomState;
-	  
+	  m_OldSpacingZoomFactor = m_SpacingZoomFactor;
 	  m_OpenGlIsotropicZoom -=static_cast<double>(dy)/10;
 	  if(m_OpenGlIsotropicZoom>2)
 	    {
-	      
 	      m_SpacingZoomFactor/=2;
 	      m_OpenGlIsotropicZoom = 1;
 	    }
 	  else if(m_OpenGlIsotropicZoom<1)
 	    {
 	      m_SpacingZoomFactor*=2;
-	      m_OpenGlIsotropicZoom = 1.9;
-	      
+	      m_OpenGlIsotropicZoom = 1.9;	      
 	    }
-
-	  // std::cout<<"Zoom state: "<<m_ZoomState<<std::endl;
-// 	  std::cout<<"Old zoom state: "<<oldState<<std::endl;
-// 	  std::cout<<"Opengl zoom: "<<m_OpenGlIsotropicZoom<<std::endl;
-// 	  std::cout<<"Interpolator zoom factor: "<<m_SpacingZoomFactor<<std::endl;
 	  this->redraw();
-	   m_Updating=false;
-	   return 1;
+	  return 1;
+	}
+      case FL_FOCUS:
+	{
+	  return 1;
+	}
+      case FL_UNFOCUS:
+	{
+	  return 1;
+	}
+      case FL_KEYDOWN:
+	{
+	  if(Fl::event_key()==116) // T kye
+	    {
+	      m_SubWindowMode = !m_SubWindowMode;
+	      this->redraw();
+	    }
+	  return 1;
 	}
       }
-    m_Updating=false;
     return 0;
   }
 
   template <class TPixel>
   void
   ImageAlternateViewer<TPixel>
-  ::MergeBuffersAndFreeMemory(std::vector<unsigned char *> bufferList, std::vector<RegionType> bufferRegionList)
+ ::MergeBuffersAndFreeMemory(std::vector<unsigned char *> bufferList, std::vector<RegionType> bufferRegionList)
   {
     //std::cout<<"Entering merge method"<<std::endl;
     if(bufferList.size()!=8 || bufferRegionList.size()!=8)
@@ -919,6 +1203,7 @@ namespace otb
       }
 
     // update buffered region
+    m_OldBufferedRegion = m_BufferedRegion;
     m_BufferedRegion=m_DisplayExtent;
     // delete previous buffer
     if (m_OpenGlBuffer!=NULL)
@@ -955,6 +1240,8 @@ namespace otb
 	double movey = static_cast<double>(m_DisplayExtent.GetSize()[1])-static_cast<double>(region.GetIndex()[1])-zoomOffsetY;
 	glBitmap(0,0,0,0,movex,movey,NULL);
 	glPixelZoom(m_OpenGlIsotropicZoom,-m_OpenGlIsotropicZoom);
+
+
 	// display the image
 	glDrawPixels(region.GetSize()[0],
 		     region.GetSize()[1], 
@@ -968,6 +1255,43 @@ namespace otb
     total.Stop();
   }
 
+
+  template <class TPixel>
+  void
+  ImageAlternateViewer<TPixel>
+  ::DrawRegionBoundary(RegionType& region)
+  {
+    double zoomOffsetX = 0;
+    double zoomOffsetY = 0;
+    
+    zoomOffsetX = (1-m_OpenGlIsotropicZoom)*(static_cast<double>(m_DisplayExtent.GetSize()[0]/2)-static_cast<double>(region.GetIndex()[0]));
+    zoomOffsetY = (1-m_OpenGlIsotropicZoom)*( static_cast<double>(m_DisplayExtent.GetSize()[1]/2)-static_cast<double>(region.GetIndex()[1]));
+    double minx,maxx,miny,maxy;
+    
+    minx = static_cast<double>(region.GetIndex()[0])/**m_OpenGlIsotropicZoom*/+zoomOffsetX;
+    maxx = minx + static_cast<double>(region.GetSize()[0])*m_OpenGlIsotropicZoom;
+    miny = static_cast<double>(m_DisplayExtent.GetSize()[1])-static_cast<double>(region.GetIndex()[1])/**m_OpenGlIsotropicZoom*/-zoomOffsetY;
+    maxy = miny-static_cast<double>(region.GetSize()[1])*m_OpenGlIsotropicZoom;
+    
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    glColor4f(1,0,0,1);
+    glBegin(GL_LINE_LOOP);
+    glVertex2f(minx,miny);
+    glVertex2f(minx,maxy);
+    glVertex2f(maxx,maxy);
+    glVertex2f(maxx,miny);
+    glEnd();
+    glDisable(GL_BLEND);
+
+  }
+
+
+
+
+
+
+
   // template <class TPixel>
   // void
   // ImageAlternateViewer<TPixel>