]> Creatis software - clitk.git/blobdiff - vv/vvMainWindow.cxx
Added svl file format (Clarity)
[clitk.git] / vv / vvMainWindow.cxx
index 83fb2f4dc67476104f74ca9175d46ccb87254a7b..5cf7c9810cbeb46e7cc83f67773edc59be3f205a 100644 (file)
 #include <vtkPNMWriter.h>
 #include <vtkPNGWriter.h>
 #include <vtkJPEGWriter.h>
+#include <vtkGenericMovieWriter.h>
+#ifdef CLITK_EXPERIMENTAL
+#  include <vvAnimatedGIFWriter.h>
+#endif
+#ifdef VTK_USE_VIDEO_FOR_WINDOWS
+#  include <vtkAVIWriter.h>
+#endif
 #ifdef VTK_USE_FFMPEG_ENCODER
 #  include <vtkFFMPEGWriter.h>
 #endif
 #define COLUMN_RELOAD_IMAGE 6
 #define COLUMN_IMAGE_NAME 7
 
-#define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN )"
+#if CLITK_PRIVATE_FEATURES
+  #define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr *.refscan *.usf *.svl)"
+#else
+  #define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr *.refscan)"
+#endif
 
 /*Data Tree values
   0,Qt::UserRole full filename
@@ -298,19 +309,19 @@ vvMainWindow::vvMainWindow():vvMainWindowBase()
   connect(levelSpinBox,SIGNAL(editingFinished()),this,SLOT(WindowLevelEdited()));
   connect(colorMapComboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(UpdateColorMap()));
   connect(presetComboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(UpdateWindowLevel()));
+  connect(slicingPresetComboBox, SIGNAL(currentIndexChanged(int)),this,SLOT(UpdateSlicingPreset()));
   connect(inverseButton,SIGNAL(clicked()),this,SLOT(SwitchWindowLevel()));
   connect(applyWindowLevelToAllButton,SIGNAL(clicked()),this,SLOT(ApplyWindowLevelToAllImages()));
 
-
   connect(this,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(ShowContextMenu(QPoint)));
 
-  connect(linkPanel,SIGNAL(addLink(QString,QString)),this,SLOT(AddLink(QString,QString)));
+  connect(linkPanel,SIGNAL(addLink(QString,QString,bool)),this,SLOT(AddLink(QString,QString,bool)));
   connect(linkPanel,SIGNAL(removeLink(QString,QString)),this,SLOT(RemoveLink(QString,QString)));
   connect(overlayPanel,SIGNAL(VFPropertyUpdated(int,int,int,int,double,double,double)),this,SLOT(SetVFProperty(int,int,int,int,double,double,double)));
   connect(overlayPanel,SIGNAL(OverlayPropertyUpdated(int,int,double,double)),
           this,SLOT(SetOverlayProperty(int,int,double,double)));
-  connect(overlayPanel,SIGNAL(FusionPropertyUpdated(int,int,int,double,double)),
-          this,SLOT(SetFusionProperty(int,int,int,double,double)));
+  connect(overlayPanel,SIGNAL(FusionPropertyUpdated(int,int,int,double,double, bool)),
+          this,SLOT(SetFusionProperty(int,int,int,double,double, bool)));
   connect(landmarksPanel,SIGNAL(UpdateRenderWindows()),this,SLOT(UpdateRenderWindows()));
 
   playMode = 0;//pause
@@ -491,15 +502,8 @@ void vvMainWindow::OpenVTKContour()
 
 
 //------------------------------------------------------------------------------
-void vvMainWindow::OpenDCStructContour()
+void vvMainWindow::AddDCStructContour(int index, QString file)
 {
-  if (mSlicerManagers.size() > 0) {
-    QString Extensions = "Dicom Files ( *.dcm RS*)";
-    Extensions += ";;All Files (*)";
-    QString file = QFileDialog::getOpenFileName(this,tr("Merge Images"),mInputPathName,Extensions);
-    if (file.isNull())
-      return;
-    int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
     vvMeshReader reader;
     reader.SetFilename(file.toStdString());
     vvStructSelector selector;
@@ -519,6 +523,19 @@ void vvMainWindow::OpenDCStructContour()
         AddContour(index,*i,selector.PropagationEnabled());
       QApplication::restoreOverrideCursor();
     }
+}
+
+//------------------------------------------------------------------------------
+void vvMainWindow::OpenDCStructContour()
+{
+  if (mSlicerManagers.size() > 0) {
+    QString Extensions = "Dicom Files ( *.dcm RS*)";
+    Extensions += ";;All Files (*)";
+    QString file = QFileDialog::getOpenFileName(this,tr("Merge Images"),mInputPathName,Extensions);
+    if (file.isNull())
+      return;
+    int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
+    AddDCStructContour(index, file);
   }
 }
 //------------------------------------------------------------------------------
@@ -911,7 +928,7 @@ void vvMainWindow::LoadImages(std::vector<std::string> files, vvImageReader::Loa
         DataTree->setItemWidget(item, COLUMN_RELOAD_IMAGE, rButton);
 
         //set the id of the image
-        QString id = files[i].c_str() + QString::number(mSlicerManagers.size()-1);
+        QString id = QDir::current().absoluteFilePath(files[i].c_str()) + QString::number(mSlicerManagers.size()-1);
         item->setData(COLUMN_IMAGE_NAME,Qt::UserRole,id.toStdString().c_str());
         mSlicerManagers.back()->SetId(id.toStdString());
 
@@ -935,6 +952,8 @@ void vvMainWindow::LoadImages(std::vector<std::string> files, vvImageReader::Loa
                 this,SLOT(UpdateSlice(int,int)));
         connect(mSlicerManagers.back(), SIGNAL(UpdateTSlice(int, int)),
                 this,SLOT(UpdateTSlice(int, int)));
+        connect(mSlicerManagers.back(), SIGNAL(UpdateTSlice(int, int)),
+                this,SLOT(ImageInfoChanged()));
         connect(mSlicerManagers.back(), SIGNAL(UpdateSliceRange(int,int,int,int,int)),
                 this,SLOT(UpdateSliceRange(int,int,int,int,int)));
         connect(mSlicerManagers.back(), SIGNAL(UpdateLinkManager(std::string,int,double,double,double,int)),
@@ -1067,7 +1086,8 @@ void vvMainWindow::ImageInfoChanged()
     QString inputSizeInBytes;
     QString image = DataTree->selectedItems()[0]->data(COLUMN_IMAGE_NAME,Qt::DisplayRole).toString();
 
-    if (mSlicerManagers[index]->GetSlicer(0)->GetImage()->GetVTKImages().size() > 1 || playMode == 1) {
+    int nframes = mSlicerManagers[index]->GetSlicer(0)->GetTMax();
+    if (nframes > 1 || playMode == 1) {
       playButton->setEnabled(1);
       frameRateLabel->setEnabled(1);
       frameRateSpinBox->setEnabled(1);
@@ -1080,21 +1100,28 @@ void vvMainWindow::ImageInfoChanged()
     //read image header
     int NPixel = 1;
 
+    int tSlice = 0;
     vvImage::Pointer imageSelected;
     if (DataTree->topLevelItem(index) == DataTree->selectedItems()[0]) {
       imageSelected = mSlicerManagers[index]->GetSlicer(0)->GetImage();
+      tSlice = mSlicerManagers[index]->GetSlicer(0)->GetTSlice();
     } else if (DataTree->selectedItems()[0]->data(1,Qt::UserRole).toString() == "vector") {
       imageSelected = mSlicerManagers[index]->GetSlicer(0)->GetVF();
+      tSlice = mSlicerManagers[index]->GetSlicer(0)->GetOverlayTSlice();
     } else if (DataTree->selectedItems()[0]->data(1,Qt::UserRole).toString() == "overlay") {
       imageSelected = mSlicerManagers[index]->GetSlicer(0)->GetOverlay();
+      tSlice = mSlicerManagers[index]->GetSlicer(0)->GetOverlayTSlice();
     } else if (DataTree->selectedItems()[0]->data(1,Qt::UserRole).toString() == "fusion") {
       imageSelected = mSlicerManagers[index]->GetSlicer(0)->GetFusion();
+      tSlice = mSlicerManagers[index]->GetSlicer(0)->GetFusionTSlice();
     }
     else if (DataTree->selectedItems()[0]->data(1,Qt::UserRole).toString() == "contour") {
       imageSelected = mSlicerManagers[index]->GetSlicer(0)->GetImage();
+      tSlice = mSlicerManagers[index]->GetSlicer(0)->GetTSlice();
     }
     else {
       imageSelected = mSlicerManagers[index]->GetSlicer(0)->GetImage();
+      tSlice = mSlicerManagers[index]->GetSlicer(0)->GetTSlice();
     }
 
     dimension = imageSelected->GetNumberOfDimensions();
@@ -1122,7 +1149,7 @@ void vvMainWindow::ImageInfoChanged()
     infoPanel->setOrigin(GetVectorDoubleAsString(origin));
     infoPanel->setSpacing(GetVectorDoubleAsString(inputSpacing));
     infoPanel->setNPixel(QString::number(NPixel)+" ("+inputSizeInBytes+")");
-    transformation = imageSelected->GetTransform()->GetMatrix();
+    transformation = imageSelected->GetTransform()[tSlice]->GetMatrix();
     infoPanel->setTransformation(Get4x4MatrixDoubleAsString(transformation));
 
     landmarksPanel->SetCurrentLandmarks(mSlicerManagers[index]->GetLandmarks(),
@@ -1159,6 +1186,7 @@ void vvMainWindow::ImageInfoChanged()
       }
     }
     WindowLevelChanged();
+    slicingPresetComboBox->setCurrentIndex(mSlicerManagers[index]->GetSlicingPreset());
 
     if (mSlicerManagers[index]->GetSlicer(0)->GetVF()) {
       overlayPanel->getVFName(mSlicerManagers[index]->GetVFName().c_str());
@@ -1216,25 +1244,70 @@ void vvMainWindow::ShowHelpDialog()
 //------------------------------------------------------------------------------
 void vvMainWindow::ChangeViewMode()
 {
-  QList<int> size;
+  typedef struct _SIZE{
+    QSplitter* splitter;
+    QList<int> size1, size2;
+    int cols[3];
+  }SplitterSize;
+  SplitterSize sizes[4];
+  sizes[0].splitter = OSplitter;
+  sizes[0].size1.push_back(1);
+  sizes[0].size1.push_back(0);
+  sizes[0].size2.push_back(1);
+  sizes[0].size2.push_back(0);
+  sizes[0].cols[0] = 2;
+  sizes[0].cols[1] = 3;
+  sizes[0].cols[2] = 4;
+
+  sizes[1].splitter = ESplitter;
+  sizes[1].size1.push_back(0);
+  sizes[1].size1.push_back(1);
+  sizes[1].size2.push_back(1);
+  sizes[1].size2.push_back(0);
+  sizes[1].cols[0] = 1;
+  sizes[1].cols[1] = 3;
+  sizes[1].cols[2] = 4;
+
+  sizes[2].splitter = OSplitter;
+  sizes[2].size1.push_back(1);
+  sizes[2].size1.push_back(0);
+  sizes[2].size2.push_back(0);
+  sizes[2].size2.push_back(1);
+  sizes[2].cols[0] = 1;
+  sizes[2].cols[1] = 2;
+  sizes[2].cols[2] = 4;
+
+  sizes[3].splitter = ESplitter;
+  sizes[3].size1.push_back(0);
+  sizes[3].size1.push_back(1);
+  sizes[3].size2.push_back(0);
+  sizes[3].size2.push_back(1);
+  sizes[3].cols[0] = 1;
+  sizes[3].cols[1] = 2;
+  sizes[3].cols[2] = 3;
+  
+  int slicer = mSlicerManagers[mCurrentPickedImageIndex]->GetSelectedSlicer();
   if (viewMode == 1) {
-    viewMode = 0;
-    size.push_back(1);
-    size.push_back(0);
-    splitter_3->setSizes(size);
-    OSplitter->setSizes(size);
-    DataTree->setColumnHidden(2,1);
-    DataTree->setColumnHidden(3,1);
-    DataTree->setColumnHidden(4,1);
+    if (slicer >= 0) {
+      viewMode = 0;
+      splitter_3->setSizes(sizes[slicer].size1);
+      sizes[slicer].splitter->setSizes(sizes[slicer].size2);
+      DataTree->setColumnHidden(sizes[slicer].cols[0],1);
+      DataTree->setColumnHidden(sizes[slicer].cols[1],1);
+      DataTree->setColumnHidden(sizes[slicer].cols[2],1);
+    }
   } else {
-    viewMode = 1;
-    size.push_back(1);
-    size.push_back(1);
-    splitter_3->setSizes(size);
-    OSplitter->setSizes(size);
-    DataTree->setColumnHidden(2,0);
-    DataTree->setColumnHidden(3,0);
-    DataTree->setColumnHidden(4,0);
+    QList<int> size;
+    if (slicer >= 0) {
+      viewMode = 1;
+      size.push_back(1);
+      size.push_back(1);
+      splitter_3->setSizes(size);
+      sizes[slicer].splitter->setSizes(size);
+      DataTree->setColumnHidden(sizes[slicer].cols[0],0);
+      DataTree->setColumnHidden(sizes[slicer].cols[1],0);
+      DataTree->setColumnHidden(sizes[slicer].cols[2],0);
+    }
   }
   UpdateRenderWindows();
   /*
@@ -1242,10 +1315,12 @@ void vvMainWindow::ChangeViewMode()
   ** the associated Slicer to redraw crosses.
   */
   for (unsigned int i = 0; i < mSlicerManagers.size(); i++) {
-    if (DataTree->topLevelItem(i)->data(COLUMN_UL_VIEW,Qt::CheckStateRole).toInt() > 1)
+//     if (DataTree->topLevelItem(i)->data(COLUMN_UL_VIEW,Qt::CheckStateRole).toInt() > 1)
       mSlicerManagers[i]->GetSlicer(0)->Render();
-    if (DataTree->topLevelItem(i)->data(COLUMN_DL_VIEW,Qt::CheckStateRole).toInt() > 1)
+      mSlicerManagers[i]->GetSlicer(1)->Render();
+//     if (DataTree->topLevelItem(i)->data(COLUMN_DL_VIEW,Qt::CheckStateRole).toInt() > 1)
       mSlicerManagers[i]->GetSlicer(2)->Render();
+      mSlicerManagers[i]->GetSlicer(3)->Render();
   }
 }
 //------------------------------------------------------------------------------
@@ -1273,20 +1348,29 @@ QString vvMainWindow::GetSizeInBytes(unsigned long size)
 //------------------------------------------------------------------------------
 
 //------------------------------------------------------------------------------
-QString vvMainWindow::Get4x4MatrixDoubleAsString(vtkSmartPointer<vtkMatrix4x4> matrix)
+QString vvMainWindow::Get4x4MatrixDoubleAsString(vtkSmartPointer<vtkMatrix4x4> matrix, const int precision)
 {
   std::ostringstream strmatrix;
 
+  // Figure out the number of digits of the integer part of the largest absolute value
+  // for each column
+  unsigned width[4];
+  for (unsigned int j = 0; j < 4; j++){
+    double absmax = 0.;
+    for (unsigned int i = 0; i < 4; i++)
+      absmax = std::max(absmax, vnl_math_abs(matrix->GetElement(i, j)));
+    unsigned ndigits = (unsigned)std::max(0.,std::log10(absmax))+1;
+    width[j] = precision+ndigits+3;
+  }
+
+  // Output with correct width, aligned to the right
   for (unsigned int i = 0; i < 4; i++) {
     for (unsigned int j = 0; j < 4; j++) {
-      strmatrix.flags(ios::showpos);
-      strmatrix.width(10);
-      strmatrix.precision(3);
       strmatrix.setf(ios::fixed,ios::floatfield);
+      strmatrix.precision(precision);
       strmatrix.fill(' ');
-      strmatrix << std::left << matrix->GetElement(i, j);
-      //strmatrix.width(10);
-      strmatrix << " ";
+      strmatrix.width(width[j]);
+      strmatrix << std::right << matrix->GetElement(i, j);
     }
     strmatrix << std::endl;
   }
@@ -1464,38 +1548,28 @@ void vvMainWindow::InitDisplay()
 //------------------------------------------------------------------------------
 void vvMainWindow::DisplaySliders(int slicer, int window)
 {
+  if(!mSlicerManagers[slicer]->GetSlicer(window)->GetRenderer()->GetDraw())
+    return;
+
   int range[2];
   mSlicerManagers[slicer]->GetSlicer(window)->GetSliceRange(range);
   int position = mSlicerManagers[slicer]->GetSlicer(window)->GetSlice();
-
-  int tRange[2];
-  tRange[0] = 0;
-  tRange[1] = mSlicerManagers[slicer]->GetSlicer(window)->GetTMax();
-  int tPosition = mSlicerManagers[slicer]->GetSlicer(window)->GetTSlice();
-  bool showHorizontal = false;
-  bool showVertical = false;
-  if (mSlicerManagers[slicer]->GetSlicer(window)->GetImage()->GetNumberOfDimensions() > 3
-      || (mSlicerManagers[slicer]->GetSlicer(window)->GetImage()->GetNumberOfDimensions() > 2
-          && mSlicerManagers[slicer]->GetType() != vvImageReader::IMAGEWITHTIME
-          && mSlicerManagers[slicer]->GetType() != vvImageReader::MERGEDWITHTIME))
-    showVertical = true;
-  if (mSlicerManagers[slicer]->GetSlicer(window)->GetImage()->GetNumberOfDimensions() > 3
-      || mSlicerManagers[slicer]->GetType() == vvImageReader::IMAGEWITHTIME
-      || mSlicerManagers[slicer]->GetType() == vvImageReader::MERGEDWITHTIME)
-    showHorizontal = true;
-
-  if (showVertical)
+  if (range[1]>0)
     verticalSliders[window]->show();
   else
     verticalSliders[window]->hide();
   verticalSliders[window]->setRange(range[0],range[1]);
   verticalSliders[window]->setValue(position);
 
-  if (showHorizontal)
+  int tRange[2];
+  tRange[0] = 0;
+  tRange[1] = mSlicerManagers[slicer]->GetSlicer(window)->GetTMax();
+  if (tRange[1]>0)
     horizontalSliders[window]->show();
   else
     horizontalSliders[window]->hide();
   horizontalSliders[window]->setRange(tRange[0],tRange[1]);
+  int tPosition = mSlicerManagers[slicer]->GetSlicer(window)->GetMaxCurrentTSlice();
   horizontalSliders[window]->setValue(tPosition);
 }
 //------------------------------------------------------------------------------
@@ -1695,6 +1769,16 @@ void vvMainWindow::UpdateWindowLevel()
 }
 //------------------------------------------------------------------------------
 
+//------------------------------------------------------------------------------
+void vvMainWindow::UpdateSlicingPreset()
+{
+  if (DataTree->selectedItems().size()) {
+    int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
+    mSlicerManagers[index]->SetSlicingPreset(vvSlicerManager::SlicingPresetType(slicingPresetComboBox->currentIndex()));
+  }
+}
+//------------------------------------------------------------------------------
+
 //------------------------------------------------------------------------------
 void vvMainWindow::UpdateColorMap()
 {
@@ -1734,6 +1818,32 @@ void vvMainWindow::ApplyWindowLevelToAllImages()
 }
 //------------------------------------------------------------------------------
 
+//------------------------------------------------------------------------------
+void vvMainWindow::ApplyWindowToSetOfImages(double window, unsigned int indexMin, unsigned int indexMax)
+{
+  for (unsigned int i = indexMin; i <= indexMax && i < mSlicerManagers.size(); i++) {
+    if (mSlicerManagers[i] == NULL)
+      continue;
+    mSlicerManagers[i]->SetColorWindow(window);
+    mSlicerManagers[i]->SetPreset(6);
+    mSlicerManagers[i]->Render();
+  }
+}
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+void vvMainWindow::ApplyLevelToSetOfImages(double level, unsigned int indexMin, unsigned int indexMax)
+{
+  for (unsigned int i = indexMin; i <= indexMax && i < mSlicerManagers.size(); i++) {
+    if (mSlicerManagers[i] == NULL)
+      continue;
+    mSlicerManagers[i]->SetColorLevel(level);
+    mSlicerManagers[i]->SetPreset(6);
+    mSlicerManagers[i]->Render();
+  }
+}
+//------------------------------------------------------------------------------
+
 //------------------------------------------------------------------------------
 void vvMainWindow::UpdateLinkManager(std::string id, int slicer, double x, double y, double z, int temps)
 {
@@ -1819,79 +1929,94 @@ void vvMainWindow::SelectOverlayImage()
 
   QString Extensions = EXTENSIONS;
   Extensions += ";;All Files (*)";
-  QString file = QFileDialog::getOpenFileName(this,tr("Load Overlay image"),mInputPathName,Extensions);
-  if (!file.isEmpty())
-    AddOverlayImage(index,file);
+  QStringList files = QFileDialog::getOpenFileNames(this,tr("Load Overlay image"),mInputPathName,Extensions);
+  if (files.isEmpty())
+    return;
+
+  std::vector<std::string> vecFileNames;
+  for (int i = 0; i < files.size(); i++) {
+    vecFileNames.push_back(files[i].toStdString());
+  }
+  AddOverlayImage(index,vecFileNames,vvImageReader::IMAGE);
 }
 //------------------------------------------------------------------------------
 
 //------------------------------------------------------------------------------
-void vvMainWindow::AddOverlayImage(int index, QString file)
+void vvMainWindow::AddOverlayImage(int index, std::vector<std::string> fileNames, vvImageReader::LoadedImageType type)
 {
+  QString file(fileNames[0].c_str());
+  if (QFile::exists(file))
+  {
+    mInputPathName = itksys::SystemTools::GetFilenamePath(file.toStdString()).c_str();
+    itk::ImageIOBase::Pointer reader = itk::ImageIOFactory::CreateImageIO(
+        file.toStdString().c_str(), itk::ImageIOFactory::ReadMode);
+    reader->SetFileName(fileNames[0].c_str());
+    reader->ReadImageInformation();
+    std::string component = reader->GetComponentTypeAsString(reader->GetComponentType());
+    int dimension = reader->GetNumberOfDimensions();
+    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+    vvProgressDialog progress("Opening " + file.toStdString());
+    qApp->processEvents();
 
-  mInputPathName = itksys::SystemTools::GetFilenamePath(file.toStdString()).c_str();
-  itk::ImageIOBase::Pointer reader = itk::ImageIOFactory::CreateImageIO(
-                                       file.toStdString().c_str(), itk::ImageIOFactory::ReadMode);
-  reader->SetFileName(file.toStdString().c_str());
-  reader->ReadImageInformation();
-  std::string component = reader->GetComponentTypeAsString(reader->GetComponentType());
-  int dimension = reader->GetNumberOfDimensions();
-  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
-  vvProgressDialog progress("Opening " + file.toStdString());
-  qApp->processEvents();
+    std::string filename = itksys::SystemTools::GetFilenameWithoutExtension(file.toStdString()).c_str();
+    if (mSlicerManagers[index]->SetOverlay(fileNames,dimension, component,type)) {
+      //create an item in the tree with good settings
+      QTreeWidgetItem *item = new QTreeWidgetItem();
+      item->setData(0,Qt::UserRole,file.toStdString().c_str());
+      item->setData(1,Qt::UserRole,tr("overlay"));
+      QFileInfo fileinfo(file); //Do not show the path
+      item->setData(COLUMN_IMAGE_NAME,Qt::DisplayRole,fileinfo.fileName());
+      item->setToolTip(COLUMN_IMAGE_NAME, mSlicerManagers[index]->GetListOfAbsoluteFilePathInOneString("overlay").c_str());
+      qApp->processEvents();
 
-  std::string filename = itksys::SystemTools::GetFilenameWithoutExtension(file.toStdString()).c_str();
-  if (mSlicerManagers[index]->SetOverlay(file.toStdString(),dimension, component)) {
-    //create an item in the tree with good settings
-    QTreeWidgetItem *item = new QTreeWidgetItem();
-    item->setData(0,Qt::UserRole,file.toStdString().c_str());
-    item->setData(1,Qt::UserRole,tr("overlay"));
-    QFileInfo fileinfo(file); //Do not show the path
-    item->setData(COLUMN_IMAGE_NAME,Qt::DisplayRole,fileinfo.fileName());
-    item->setToolTip(COLUMN_IMAGE_NAME, mSlicerManagers[index]->GetListOfAbsoluteFilePathInOneString("overlay").c_str());
-    qApp->processEvents();
+      for (int j = 1; j <= 4; j++) {
+        item->setData(j,Qt::CheckStateRole,DataTree->topLevelItem(index)->data(j,Qt::CheckStateRole));
+      }
 
-    for (int j = 1; j <= 4; j++) {
-      item->setData(j,Qt::CheckStateRole,DataTree->topLevelItem(index)->data(j,Qt::CheckStateRole));
-    }
+      //Create the buttons for reload and close
+      qApp->processEvents();
+      QTreePushButton* cButton = new QTreePushButton;
+      cButton->setItem(item);
+      cButton->setColumn(COLUMN_CLOSE_IMAGE);
+      cButton->setToolTip(tr("close image"));
+      cButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/exit.png")));
+      connect(cButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
+          this,SLOT(CloseImage(QTreeWidgetItem*, int)));
 
-    //Create the buttons for reload and close
-    qApp->processEvents();
-    QTreePushButton* cButton = new QTreePushButton;
-    cButton->setItem(item);
-    cButton->setColumn(COLUMN_CLOSE_IMAGE);
-    cButton->setToolTip(tr("close image"));
-    cButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/exit.png")));
-    connect(cButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
-            this,SLOT(CloseImage(QTreeWidgetItem*, int)));
+      QTreePushButton* rButton = new QTreePushButton;
+      rButton->setItem(item);
+      rButton->setColumn(COLUMN_RELOAD_IMAGE);
+      rButton->setToolTip(tr("reload image"));
+      rButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/rotateright.png")));
+      connect(rButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
+          this,SLOT(ReloadImage(QTreeWidgetItem*, int)));
 
-    QTreePushButton* rButton = new QTreePushButton;
-    rButton->setItem(item);
-    rButton->setColumn(COLUMN_RELOAD_IMAGE);
-    rButton->setToolTip(tr("reload image"));
-    rButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/rotateright.png")));
-    connect(rButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
-            this,SLOT(ReloadImage(QTreeWidgetItem*, int)));
+      DataTree->topLevelItem(index)->setExpanded(1);
+      DataTree->topLevelItem(index)->addChild(item);
+      DataTree->setItemWidget(item, COLUMN_CLOSE_IMAGE, cButton);
+      DataTree->setItemWidget(item, COLUMN_RELOAD_IMAGE, rButton);
 
-    DataTree->topLevelItem(index)->setExpanded(1);
-    DataTree->topLevelItem(index)->addChild(item);
-    DataTree->setItemWidget(item, COLUMN_CLOSE_IMAGE, cButton);
-    DataTree->setItemWidget(item, COLUMN_RELOAD_IMAGE, rButton);
+      //set the id of the image
+      QString id = DataTree->topLevelItem(index)->data(COLUMN_IMAGE_NAME,Qt::UserRole).toString();
+      item->setData(COLUMN_IMAGE_NAME,Qt::UserRole,id.toStdString().c_str());
+      UpdateTree();
+      qApp->processEvents();
+      ImageInfoChanged();
+      QApplication::restoreOverrideCursor();
 
-    //set the id of the image
-    QString id = DataTree->topLevelItem(index)->data(COLUMN_IMAGE_NAME,Qt::UserRole).toString();
-    item->setData(COLUMN_IMAGE_NAME,Qt::UserRole,id.toStdString().c_str());
-    UpdateTree();
-    qApp->processEvents();
-    ImageInfoChanged();
-    QApplication::restoreOverrideCursor();
-  } else {
-    QApplication::restoreOverrideCursor();
-    QString error = "Cannot import the new image.\n";
-    error += mSlicerManagers[index]->GetLastError().c_str();
-    QMessageBox::information(this,tr("Problem reading image !"),error);
+      // Update the display to update, e.g., the sliders
+      for(int i=0; i<4; i++)
+        DisplaySliders(index, i);
+    } else {
+      QApplication::restoreOverrideCursor();
+      QString error = "Cannot import the new image.\n";
+      error += mSlicerManagers[index]->GetLastError().c_str();
+      QMessageBox::information(this,tr("Problem reading image !"),error);
+    }
+    WindowLevelChanged();
   }
-  WindowLevelChanged();
+  else
+    QMessageBox::information(this,tr("Problem reading Overlay !"),"File doesn't exist!");
 }
 //------------------------------------------------------------------------------
 
@@ -1959,73 +2084,78 @@ void vvMainWindow::ResetTransformationToIdentity()
 //------------------------------------------------------------------------------
 void vvMainWindow::AddFusionImage(int index, QString file)
 {
-  mInputPathName = itksys::SystemTools::GetFilenamePath(file.toStdString()).c_str();
-  itk::ImageIOBase::Pointer reader = itk::ImageIOFactory::CreateImageIO(
-                                       file.toStdString().c_str(), itk::ImageIOFactory::ReadMode);
-  reader->SetFileName(file.toStdString().c_str());
-  reader->ReadImageInformation();
-  std::string component = reader->GetComponentTypeAsString(reader->GetComponentType());
-  if (reader) {
-    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
-    vvProgressDialog progress("Opening fusion");
-    qApp->processEvents();
-
-    std::string filename = itksys::SystemTools::GetFilenameWithoutExtension(file.toStdString()).c_str();
-    if (mSlicerManagers[index]->SetFusion(file.toStdString(),
-                                          reader->GetNumberOfDimensions(), component)) {
-      //create an item in the tree with good settings
-      QTreeWidgetItem *item = new QTreeWidgetItem();
-      item->setData(0,Qt::UserRole,file.toStdString().c_str());
-      item->setData(1,Qt::UserRole,tr("fusion"));
-      QFileInfo fileinfo(filename.c_str()); //Do not show the path
-      item->setData(COLUMN_IMAGE_NAME,Qt::DisplayRole,fileinfo.fileName());
-      item->setToolTip(COLUMN_IMAGE_NAME, mSlicerManagers[index]->GetListOfAbsoluteFilePathInOneString("fusion").c_str());
+  if (QFile::exists(file))
+  {
+    mInputPathName = itksys::SystemTools::GetFilenamePath(file.toStdString()).c_str();
+    itk::ImageIOBase::Pointer reader = itk::ImageIOFactory::CreateImageIO(
+        file.toStdString().c_str(), itk::ImageIOFactory::ReadMode);
+    reader->SetFileName(file.toStdString().c_str());
+    reader->ReadImageInformation();
+    std::string component = reader->GetComponentTypeAsString(reader->GetComponentType());
+    if (reader) {
+      QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+      vvProgressDialog progress("Opening fusion");
       qApp->processEvents();
 
-      for (int j = 1; j <= 4; j++) {
-        item->setData(j,Qt::CheckStateRole,DataTree->topLevelItem(index)->data(j,Qt::CheckStateRole));
-      }
+      std::string filename = itksys::SystemTools::GetFilenameWithoutExtension(file.toStdString()).c_str();
+      if (mSlicerManagers[index]->SetFusion(file.toStdString(),
+            reader->GetNumberOfDimensions(), component)) {
+        //create an item in the tree with good settings
+        QTreeWidgetItem *item = new QTreeWidgetItem();
+        item->setData(0,Qt::UserRole,file.toStdString().c_str());
+        item->setData(1,Qt::UserRole,tr("fusion"));
+        QFileInfo fileinfo(filename.c_str()); //Do not show the path
+        item->setData(COLUMN_IMAGE_NAME,Qt::DisplayRole,fileinfo.fileName());
+        item->setToolTip(COLUMN_IMAGE_NAME, mSlicerManagers[index]->GetListOfAbsoluteFilePathInOneString("fusion").c_str());
+        qApp->processEvents();
 
-      //Create the buttons for reload and close
-      qApp->processEvents();
-      QTreePushButton* cButton = new QTreePushButton;
-      cButton->setItem(item);
-      cButton->setColumn(COLUMN_CLOSE_IMAGE);
-      cButton->setToolTip(tr("close image"));
-      cButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/exit.png")));
-      connect(cButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
-              this,SLOT(CloseImage(QTreeWidgetItem*, int)));
+        for (int j = 1; j <= 4; j++) {
+          item->setData(j,Qt::CheckStateRole,DataTree->topLevelItem(index)->data(j,Qt::CheckStateRole));
+        }
 
-      QTreePushButton* rButton = new QTreePushButton;
-      rButton->setItem(item);
-      rButton->setColumn(COLUMN_RELOAD_IMAGE);
-      rButton->setToolTip(tr("reload image"));
-      rButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/rotateright.png")));
-      connect(rButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
-              this,SLOT(ReloadImage(QTreeWidgetItem*, int)));
+        //Create the buttons for reload and close
+        qApp->processEvents();
+        QTreePushButton* cButton = new QTreePushButton;
+        cButton->setItem(item);
+        cButton->setColumn(COLUMN_CLOSE_IMAGE);
+        cButton->setToolTip(tr("close image"));
+        cButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/exit.png")));
+        connect(cButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
+            this,SLOT(CloseImage(QTreeWidgetItem*, int)));
 
-      DataTree->topLevelItem(index)->setExpanded(1);
-      DataTree->topLevelItem(index)->addChild(item);
-      DataTree->setItemWidget(item, COLUMN_CLOSE_IMAGE, cButton);
-      DataTree->setItemWidget(item, COLUMN_RELOAD_IMAGE, rButton);
+        QTreePushButton* rButton = new QTreePushButton;
+        rButton->setItem(item);
+        rButton->setColumn(COLUMN_RELOAD_IMAGE);
+        rButton->setToolTip(tr("reload image"));
+        rButton->setIcon(QIcon(QString::fromUtf8(":/common/icons/rotateright.png")));
+        connect(rButton,SIGNAL(clickedInto(QTreeWidgetItem*, int)),
+            this,SLOT(ReloadImage(QTreeWidgetItem*, int)));
 
-      //set the id of the image
-      QString id = DataTree->topLevelItem(index)->data(COLUMN_IMAGE_NAME,Qt::UserRole).toString();
-      item->setData(COLUMN_IMAGE_NAME,Qt::UserRole,id.toStdString().c_str());
-      UpdateTree();
-      qApp->processEvents();
-      ImageInfoChanged();
-      QApplication::restoreOverrideCursor();
+        DataTree->topLevelItem(index)->setExpanded(1);
+        DataTree->topLevelItem(index)->addChild(item);
+        DataTree->setItemWidget(item, COLUMN_CLOSE_IMAGE, cButton);
+        DataTree->setItemWidget(item, COLUMN_RELOAD_IMAGE, rButton);
+
+        //set the id of the image
+        QString id = DataTree->topLevelItem(index)->data(COLUMN_IMAGE_NAME,Qt::UserRole).toString();
+        item->setData(COLUMN_IMAGE_NAME,Qt::UserRole,id.toStdString().c_str());
+        UpdateTree();
+        qApp->processEvents();
+        ImageInfoChanged();
+        QApplication::restoreOverrideCursor();
+      } else {
+        QApplication::restoreOverrideCursor();
+        QString error = "Cannot import the new image.\n";
+        error += mSlicerManagers[index]->GetLastError().c_str();
+        QMessageBox::information(this,tr("Problem reading image !"),error);
+      }
     } else {
-      QApplication::restoreOverrideCursor();
       QString error = "Cannot import the new image.\n";
-      error += mSlicerManagers[index]->GetLastError().c_str();
       QMessageBox::information(this,tr("Problem reading image !"),error);
     }
-  } else {
-    QString error = "Cannot import the new image.\n";
-    QMessageBox::information(this,tr("Problem reading image !"),error);
   }
+  else
+    QMessageBox::information(this,tr("Problem reading Fusion !"),"File doesn't exist!");
 }
 //------------------------------------------------------------------------------
 
@@ -2190,7 +2320,7 @@ void vvMainWindow::SetOverlayProperty(int color, int linked, double window, doub
 //------------------------------------------------------------------------------
 
 //------------------------------------------------------------------------------
-void vvMainWindow::SetFusionProperty(int opacity, int thresOpacity, int colormap,double window, double level)
+void vvMainWindow::SetFusionProperty(int opacity, int thresOpacity, int colormap,double window, double level, bool showLegend)
 {
   int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
   if (mSlicerManagers[index]->GetSlicer(0)->GetFusion()) {
@@ -2199,6 +2329,7 @@ void vvMainWindow::SetFusionProperty(int opacity, int thresOpacity, int colormap
     mSlicerManagers[index]->SetFusionThresholdOpacity(thresOpacity);
     mSlicerManagers[index]->SetFusionWindow(window);
     mSlicerManagers[index]->SetFusionLevel(level);
+    mSlicerManagers[index]->SetFusionShowLegend(showLegend);
     mSlicerManagers[index]->SetColorMap(0);
     mSlicerManagers[index]->Render();
   }
@@ -2233,11 +2364,17 @@ void vvMainWindow::SaveAs()
   } else if (dimension == 3) {
     OutputListeFormat.push_back(".mhd");
     OutputListeFormat.push_back(".mha");
+    OutputListeFormat.push_back(".nii");
+    OutputListeFormat.push_back(".nrrd");
+    OutputListeFormat.push_back(".nhdr");
     OutputListeFormat.push_back(".hdr");
     OutputListeFormat.push_back(".vox");
   } else if (dimension == 4) {
     OutputListeFormat.push_back(".mhd");
     OutputListeFormat.push_back(".mha");
+    OutputListeFormat.push_back(".nii");
+    OutputListeFormat.push_back(".nrrd");
+    OutputListeFormat.push_back(".nhdr");
   }
   QString Extensions = "AllFiles(*.*)";
   for (int i = 0; i < OutputListeFormat.count(); i++) {
@@ -2260,6 +2397,28 @@ void vvMainWindow::SaveAs()
       vvImageWriter::Pointer writer = vvImageWriter::New();
       writer->SetOutputFileName(fileName.toStdString());
       writer->SetInput(mSlicerManagers[index]->GetImage());
+
+      // Check on transform and prompt user
+      writer->SetSaveTransform(false);
+      bool bId = true;
+      for(int i=0; i<4; i++)
+        for(int j=0; j<4; j++) {
+          // TODO SR and BP: check on the list of transforms and not the first only
+          double elt = mSlicerManagers[index]->GetImage()->GetTransform()[0]->GetMatrix()->GetElement(i,j);
+          if(i==j && elt!=1.)
+            bId = false;
+          if(i!=j && elt!=0.)
+            bId = false;
+        }
+      if( !bId ) {
+        QString warning = "The image has an associated linear transform. Do you want to save it along?";
+        QMessageBox msgBox(QMessageBox::Warning, tr("Save transform"), warning, 0, this);
+        msgBox.addButton(tr("Yes"), QMessageBox::AcceptRole);
+        msgBox.addButton(tr("No"), QMessageBox::RejectRole);
+        if (msgBox.exec() == QMessageBox::AcceptRole)
+          writer->SetSaveTransform(true);
+      }
+
       writer->Update();
       QApplication::restoreOverrideCursor();
       if (writer->GetLastError().size()) {
@@ -2299,8 +2458,6 @@ void vvMainWindow::SaveCurrentStateAs(const std::string& stateFile)
 {
   vvSaveState save_state;
   save_state.Run(this, stateFile);
-  
-  std::cout << "void vvMainWindow::SaveCurrentState()" << std::endl;
 }
 
 //------------------------------------------------------------------------------
@@ -2331,8 +2488,14 @@ void vvMainWindow::LinkAllImages()
 }
 
 //------------------------------------------------------------------------------
-void vvMainWindow::AddLink(QString image1,QString image2)
+void vvMainWindow::AddLink(QString image1,QString image2,bool fromPanel)
 {
+  if (!fromPanel) {
+    // delegate to linkPanel if call came from elsewhere...
+    linkPanel->addLinkFromIds(image1, image2);
+    return;
+  }
+  
   unsigned int sm1 = 0;
   unsigned int sm2 = 0;
 
@@ -2589,23 +2752,24 @@ void vvMainWindow::UpdateTSlice(int slicer, int slice)
 //------------------------------------------------------------------------------
 void vvMainWindow::UpdateSliceRange(int slicer, int min, int max, int tmin, int tmax)
 {
-  int position = int((min+max)/2);
+  //int position = int((min+max)/2);
+  int position = mSlicerManagers[mCurrentPickedImageIndex]->GetSlicer(slicer)->GetSlice();
   if (slicer == 0) {
-    NOVerticalSlider->setValue(position);
     NOVerticalSlider->setRange(min,max);
     NOHorizontalSlider->setRange(tmin,tmax);
+    NOVerticalSlider->setValue(position);
   } else if (slicer == 1) {
-    NEVerticalSlider->setValue(position);
     NEVerticalSlider->setRange(min,max);
     NEHorizontalSlider->setRange(tmin,tmax);
+    NEVerticalSlider->setValue(position);
   } else if (slicer == 2) {
-    SOVerticalSlider->setValue(position);
     SOVerticalSlider->setRange(min,max);
     SOHorizontalSlider->setRange(tmin,tmax);
+    SOVerticalSlider->setValue(position);
   } else if (slicer == 3) {
-    SEVerticalSlider->setValue(position);
     SEVerticalSlider->setRange(min,max);
     SEHorizontalSlider->setRange(tmin,tmax);
+    SEVerticalSlider->setValue(position);
   }
 }
 //------------------------------------------------------------------------------
@@ -2701,11 +2865,14 @@ void vvMainWindow::SaveScreenshot(QVTKWidget *widget)
   Extensions += "Images( *.bmp);;";
   Extensions += "Images( *.tif);;";
   Extensions += "Images( *.ppm)";
-#ifdef VTK_USE_FFMPEG_ENCODER
-  Extensions += "Images( *.avi)";
+#if defined(VTK_USE_FFMPEG_ENCODER) || defined(VTK_USE_VIDEO_FOR_WINDOWS)
+  Extensions += ";;Video( *.avi)";
 #endif
 #ifdef VTK_USE_MPEG2_ENCODER
-  Extensions += "Images( *.mpg)";
+  Extensions += ";;Video( *.mpg)";
+#endif
+#ifdef CLITK_EXPERIMENTAL
+  Extensions += ";;Video( *.gif)";
 #endif
 
   int smIndex=GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
@@ -2720,82 +2887,111 @@ void vvMainWindow::SaveScreenshot(QVTKWidget *widget)
     w2i->Update();
     vtkImageData *image = w2i->GetOutput();
 
-    const char *ext = fileName.toStdString().c_str() + strlen(fileName.toStdString().c_str()) - 4;
-    if (!strcmp(ext, ".bmp")) {
-      vtkBMPWriter *bmp = vtkBMPWriter::New();
-      bmp->SetInput(image);
-      bmp->SetFileName(fileName.toStdString().c_str());
-      bmp->Write();
-      bmp->Delete();
-    } else if (!strcmp(ext, ".tif")) {
-      vtkTIFFWriter *tif = vtkTIFFWriter::New();
-      tif->SetInput(image);
-      tif->SetFileName(fileName.toStdString().c_str());
-      tif->Write();
-      tif->Delete();
-    } else if (!strcmp(ext, ".ppm")) {
-      vtkPNMWriter *pnm = vtkPNMWriter::New();
-      pnm->SetInput(image);
-      pnm->SetFileName(fileName.toStdString().c_str());
-      pnm->Write();
-      pnm->Delete();
-    } else if (!strcmp(ext, ".png")) {
-      vtkPNGWriter *png = vtkPNGWriter::New();
-      png->SetInput(image);
-      png->SetFileName(fileName.toStdString().c_str());
-      png->Write();
-      png->Delete();
-    } else if (!strcmp(ext, ".jpg")) {
-      vtkJPEGWriter *jpg = vtkJPEGWriter::New();
-      jpg->SetInput(image);
-      jpg->SetFileName(fileName.toStdString().c_str());
-      jpg->Write();
-      jpg->Delete();
+    std::string ext(itksys::SystemTools::GetFilenameLastExtension(fileName.toStdString()));
+
+    // Image
+    vtkImageWriter *imgwriter = NULL;
+    if (ext==".bmp")
+      imgwriter = vtkBMPWriter::New();
+    else if (ext==".tif")
+      imgwriter = vtkTIFFWriter::New();
+    else if (ext==".ppm")
+      imgwriter = vtkPNMWriter::New();
+    else if (ext==".png")
+      imgwriter = vtkPNGWriter::New();
+    else if (ext==".jpg")
+      imgwriter = vtkJPEGWriter::New();
+
+    // Snapshot image if not null
+    if(imgwriter!=NULL) {
+      imgwriter->SetInput(image);
+      imgwriter->SetFileName(fileName.toStdString().c_str());
+      imgwriter->Write();
+      return;
+    }
+
+    // Video
+    vtkGenericMovieWriter *vidwriter = NULL;
+#if CLITK_EXPERIMENTAL == 1
+    if (ext==".gif") {
+      vvAnimatedGIFWriter *gif = vvAnimatedGIFWriter::New();
+      vidwriter = gif;
+
+      // FPS
+      bool ok;
+      int fps = QInputDialog::getInteger(this, tr("Number of frames per second"),
+                                     tr("FPS:"), 5, 0, 1000, 1, &ok);
+      if(ok)
+        gif->SetRate(fps);
+
+      // Loops
+      int loops = QInputDialog::getInteger(this, tr("Loops"),
+                                     tr("Number of loops (0 means infinite):"), 0, 0, 1000000000, 1, &ok);
+      if(ok)
+        gif->SetLoops(loops);
+
+      // Dithering
+      QString msg = "Would you like to activate dithering?";
+      QMessageBox msgBox(QMessageBox::Question, tr("Dithering"),msg, 0, this);
+      msgBox.addButton(tr("Yes"), QMessageBox::AcceptRole);
+      msgBox.addButton(tr("No"), QMessageBox::RejectRole);
+      gif->SetDither(msgBox.exec() == QMessageBox::AcceptRole);
+    }
+#endif
+#ifdef VTK_USE_VIDEO_FOR_WINDOWS
+    if (ext==".avi") {
+      vtkAVIWriter *mpg = vtkAVIWriter::New();
+      vidwriter = mpg;
+      mpg->SetQuality(2);
+      bool ok;
+      int fps = QInputDialog::getInteger(this, tr("Number of frames per second"),
+                                     tr("FPS:"), 5, 0, 1024, 1, &ok);
+      if(!ok)
+        fps = 5;
+      mpg->SetRate(fps);
+    }
+#endif
 #ifdef VTK_USE_FFMPEG_ENCODER
-    } else if (!strcmp(ext, ".avi")) {
+    if (ext==".avi") {
       vtkFFMPEGWriter *mpg = vtkFFMPEGWriter::New();
-      mpg->SetInput(image);
-      mpg->SetFileName(fileName.toStdString().c_str());
+      vidwriter = mpg;
       mpg->SetQuality(2);
-      mpg->SetRate(5);
-      mpg->Start();
-
-      vvImage * vvImg = mSlicerManagers[smIndex]->GetImage();
-      int nSlice = vvImg->GetVTKImages().size();
-      for(int i=0; i<nSlice; i++) {
-        mSlicerManagers[smIndex]->SetNextTSlice(0);
-        vtkSmartPointer<vtkWindowToImageFilter> w2i = vtkSmartPointer<vtkWindowToImageFilter>::New();
-        w2i->SetInput(widget->GetRenderWindow());
-        w2i->Update();
-        mpg->SetInput(w2i->GetOutput());
-        mpg->Write();
-      }
-      mpg->End();
-      mpg->Delete();
+      bool ok;
+      int fps = QInputDialog::getInteger(this, tr("Number of frames per second"),
+                                     tr("FPS:"), 5, 0, 1024, 1, &ok);
+      if(!ok)
+        fps = 5;
+      mpg->SetRate(fps);
+      mpg->SetBitRateTolerance(int(ceil(12.0*1024*1024/fps)));
+    }
 #endif
 #ifdef VTK_USE_MPEG2_ENCODER
-    } else if (!strcmp(ext, ".mpg")) {
+    if (ext==".mpg") {
       vtkMPEG2Writer *mpg = vtkMPEG2Writer::New();
-      mpg->SetInput(image);
-      mpg->SetFileName(fileName.toStdString().c_str());
-      mpg->Start();
+      vidwriter = mpg;
+    }
+#endif
 
-      vvImage * vvImg = mSlicerManagers[smIndex]->GetImage();
-      int nSlice = vvImg->GetVTKImages().size();
-      for(int i=0; i<nSlice; i++) {
+    // Take video if not null
+    if(vidwriter!=NULL){
+      vidwriter->SetInput(image);
+      vidwriter->SetFileName(fileName.toStdString().c_str());
+      vidwriter->Start();
+      int nSlice = mSlicerManagers[smIndex]->GetSlicer(0)->GetTMax();
+      for(int i=0; i<=nSlice; i++) {
         mSlicerManagers[smIndex]->SetNextTSlice(0);
         vtkSmartPointer<vtkWindowToImageFilter> w2i = vtkSmartPointer<vtkWindowToImageFilter>::New();
         w2i->SetInput(widget->GetRenderWindow());
         w2i->Update();
-        mpg->SetInput(w2i->GetOutput());
-        mpg->Write();
+        vidwriter->SetInput(w2i->GetOutput());
+        vidwriter->Write();
       }
-      mpg->End();
-      mpg->Delete();
-#endif
-    } else {
-      QMessageBox::information(this,tr("Problem saving screenshot !"),tr("Cannot save image.\nPlease set a file extension !!!"));
+      vidwriter->End();
+      vidwriter->Delete();
+      return;
     }
+
+    QMessageBox::information(this,tr("Problem saving screenshot !"),tr("Cannot save image.\nPlease set a file extension !!!"));
   }
 }
 //------------------------------------------------------------------------------
@@ -2830,7 +3026,7 @@ void vvMainWindow::PlayPause()
     int image_number=DataTree->topLevelItemCount();
     bool has_temporal;
     for (int i=0; i<image_number; i++)
-      if (mSlicerManagers[i]->GetImage()->GetVTKImages().size() > 1) {
+      if (mSlicerManagers[i]->GetSlicer(0)->GetTMax() > 0) {
         has_temporal=true;
         break;
       }
@@ -2851,7 +3047,7 @@ void vvMainWindow::PlayNext()
     ///Only play one slicer per SM, and only if the SM is being displayed
     for (int i=0; i<image_number; i++)
       for (int j=0; j<4; j++)
-        if (mSlicerManagers[i]->GetImage()->GetVTKImages().size() > 1 &&
+        if (mSlicerManagers[i]->GetSlicer(0)->GetTMax() > 0 &&
             DataTree->topLevelItem(i)->data(j+1,Qt::CheckStateRole).toInt() > 0) {
           mSlicerManagers[i]->SetNextTSlice(j);
           break;
@@ -2874,6 +3070,12 @@ void vvMainWindow::ShowLastImage()
 //------------------------------------------------------------------------------
 void vvMainWindow::UpdateRenderWindows()
 {
+  for (unsigned int i = 0; i < mSlicerManagers.size(); i++) {
+    mSlicerManagers[i]->GetSlicer(0)->UpdateLandmarks();
+    mSlicerManagers[i]->GetSlicer(1)->UpdateLandmarks();
+    mSlicerManagers[i]->GetSlicer(2)->UpdateLandmarks();
+    mSlicerManagers[i]->GetSlicer(3)->UpdateLandmarks();
+  }
   if (NOViewWidget->GetRenderWindow()) NOViewWidget->GetRenderWindow()->Render();
   if (NEViewWidget->GetRenderWindow()) NEViewWidget->GetRenderWindow()->Render();
   if (SOViewWidget->GetRenderWindow()) SOViewWidget->GetRenderWindow()->Render();
@@ -2960,7 +3162,7 @@ vvSlicerManager* vvMainWindow::AddImage(vvImage::Pointer image,std::string filen
   DataTree->setItemWidget(item, COLUMN_RELOAD_IMAGE, rButton);
 
   //set the id of the image
-  QString id = slicer_manager->GetFileName().c_str() + QString::number(mSlicerManagers.size()-1);
+  QString id = QDir::current().absoluteFilePath(slicer_manager->GetFileName().c_str()) + QString::number(mSlicerManagers.size()-1);
   item->setData(COLUMN_IMAGE_NAME,Qt::UserRole,id.toStdString().c_str());
   mSlicerManagers.back()->SetId(id.toStdString());
 
@@ -2985,6 +3187,8 @@ vvSlicerManager* vvMainWindow::AddImage(vvImage::Pointer image,std::string filen
           this,SLOT(UpdateSlice(int,int)));
   connect(mSlicerManagers.back(), SIGNAL(UpdateTSlice(int, int)),
           this,SLOT(UpdateTSlice(int, int)));
+  connect(mSlicerManagers.back(), SIGNAL(UpdateTSlice(int, int)),
+          this,SLOT(ImageInfoChanged()));
   connect(mSlicerManagers.back(), SIGNAL(UpdateSliceRange(int,int,int,int,int)),
           this,SLOT(UpdateSliceRange(int,int,int,int,int)));
   connect(mSlicerManagers.back(), SIGNAL(UpdateLinkManager(std::string,int,double,double,double,int)),