X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=vv%2FvvMainWindow.cxx;h=cde6d50ada2dd6e719bb98a4bda9915b83fb393c;hb=9ac2232043d7a08735edf00572ccb6565919fd3d;hp=a7c61a997efa1a9b0527a56e3c73ed4b874855f4;hpb=e8efeb699b696aa952ed5301dc3d92629c2b57ec;p=clitk.git diff --git a/vv/vvMainWindow.cxx b/vv/vvMainWindow.cxx index a7c61a9..cde6d50 100644 --- a/vv/vvMainWindow.cxx +++ b/vv/vvMainWindow.cxx @@ -70,6 +70,13 @@ #include #include #include +#include +#ifdef CLITK_EXPERIMENTAL +# include +#endif +#ifdef VTK_USE_VIDEO_FOR_WINDOWS +# include +#endif #ifdef VTK_USE_FFMPEG_ENCODER # include #endif @@ -93,7 +100,12 @@ #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 )" +#ifdef CLITK_PRIVATE_FEATURES +#define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr *.refscan *.nii.gz *.usf)" +#else +#define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr *.refscan *.nii.gz)" +#endif + /*Data Tree values 0,Qt::UserRole full filename @@ -161,17 +173,18 @@ vvMainWindow::vvMainWindow():vvMainWindowBase() contextMenu.addAction(actionAdd_VF_to_current_Image); contextActions.push_back(actionAdd_VF_to_current_Image); - QAction* actionAdd_Overlay_to_current_Image = menuOverlay->addAction(QIcon(QString::fromUtf8(":/common/icons/GPSup.png")), - tr("Add overlay image to current image")); - contextMenu.addAction(actionAdd_Overlay_to_current_Image); - contextActions.push_back(actionAdd_Overlay_to_current_Image); - - connect(actionAdd_Overlay_to_current_Image,SIGNAL(triggered()), this,SLOT(SelectOverlayImage())); + //QAction* actionAdd_Overlay_to_current_Image = menuOverlay->addAction(QIcon(QString::fromUtf8(":/common/icons/GPSup.png")), + // tr("Add overlay image to current image")); + contextMenu.addAction(actionAdd_overlay_image_to_current_image); + contextActions.push_back(actionAdd_overlay_image_to_current_image); contextMenu.addAction(actionAdd_fusion_image); - connect(actionAdd_fusion_image,SIGNAL(triggered()),this,SLOT(SelectFusionImage())); contextActions.push_back(actionAdd_fusion_image); + contextMenu.addAction(actionAdd_USSequence_toCT); + contextActions.push_back(actionAdd_USSequence_toCT); + + contextMenu.addSeparator(); QAction* actionResetMatrix = contextMenu.addAction(QIcon(QString::fromUtf8(":/common/icons/identity.png")), tr("Reset transformation to identity")); @@ -221,10 +234,11 @@ vvMainWindow::vvMainWindow():vvMainWindowBase() dicomSeriesSelector = new vvDicomSeriesSelector(); inverseButton->setEnabled(0); - actionAdd_Overlay_to_current_Image->setEnabled(0); + actionAdd_overlay_image_to_current_image->setEnabled(0); actionSave_As->setEnabled(0); actionAdd_VF_to_current_Image->setEnabled(0); actionAdd_fusion_image->setEnabled(0); + actionAdd_USSequence_toCT->setEnabled(0); //init the sliders verticalSliders.push_back(NOVerticalSlider); @@ -271,10 +285,16 @@ vvMainWindow::vvMainWindow():vvMainWindowBase() connect(actionRead_saved_state,SIGNAL(triggered()),this,SLOT(ReadSavedState())); connect(actionExit,SIGNAL(triggered()),this,SLOT(close())); connect(actionAdd_VF_to_current_Image,SIGNAL(triggered()),this,SLOT(OpenField())); + connect(actionAdd_fusion_image,SIGNAL(triggered()),this,SLOT(SelectFusionImage())); + connect(actionAdd_overlay_image_to_current_image,SIGNAL(triggered()), this,SLOT(SelectOverlayImage())); + connect(actionAdd_USSequence_toCT,SIGNAL(triggered()), this,SLOT(SelectFusionSequence())); connect(actionNavigation_Help,SIGNAL(triggered()),this,SLOT(ShowHelpDialog())); connect(actionDocumentation,SIGNAL(triggered()),this,SLOT(ShowDocumentation())); connect(actionRegister_vv,SIGNAL(triggered()),this,SLOT(PopupRegisterForm())); + connect(overlayPanel, SIGNAL(FusionSequenceSignalButtonPressed()), this, SLOT(SelectFusionSequenceTemporalSignal())); + + /////////////////////////////////////////////// connect(actionSegmentation,SIGNAL(triggered()),this,SLOT(SegmentationOnCurrentImage())); connect(actionSurface_Viewer,SIGNAL(triggered()),this,SLOT(SurfaceViewerLaunch())); @@ -300,22 +320,25 @@ 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))); -#include "vvSaveState.h" - 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())); + connect(overlayPanel,SIGNAL(FusionSequencePropertyUpdated(int, bool, unsigned int, bool)), + this,SLOT(SetFusionSequenceProperty(int, bool,unsigned int, bool))); + + playMode = 0;//pause mFrameRate = 10; playButton->setEnabled(0); @@ -352,6 +375,7 @@ vvMainWindow::vvMainWindow():vvMainWindowBase() //timerMemory->setInterval(5); connect(timerMemory, SIGNAL(timeout()), this, SLOT(UpdateMemoryUsage())); timerMemory->start(2000); + } //------------------------------------------------------------------------------ void vvMainWindow::show() @@ -494,15 +518,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; @@ -522,6 +539,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); } } //------------------------------------------------------------------------------ @@ -689,51 +719,8 @@ void vvMainWindow::MergeImagesWithTime() mInputPathName = itksys::SystemTools::GetFilenamePath(files[0].toStdString()).c_str(); std::vector vector; - unsigned int currentDim = 0; - std::vector currentSpacing; - std::vector currentSize; - std::vector currentOrigin; - - for (int i = 0; i < files.size(); i++) { - itk::ImageIOBase::Pointer reader = itk::ImageIOFactory::CreateImageIO( - files[i].toStdString().c_str(), itk::ImageIOFactory::ReadMode); - if (reader) { - reader->SetFileName(files[i].toStdString().c_str()); - reader->ReadImageInformation(); - if (i == 0) - currentDim = reader->GetNumberOfDimensions(); - bool IsOk = true; - for (unsigned int j = 0; j < currentDim; j++) { - if (i == 0) { - if (j == 0) { - currentSpacing.resize(currentDim); - currentSize.resize(currentDim); - currentOrigin.resize(currentDim); - } - currentOrigin[j] = reader->GetOrigin(j); - currentSpacing[j] = reader->GetSpacing(j); - currentSize[j] = reader->GetDimensions(j); - } else if (currentDim != reader->GetNumberOfDimensions() - || currentSpacing[j] != reader->GetSpacing(j) - || currentSize[j] != (int)reader->GetDimensions(j) - || currentOrigin[j] != reader->GetOrigin(j)) { - QString error = "Cannot read file (too different from others "; - error += files[i].toStdString().c_str(); - QMessageBox::information(this,tr("Reading problem"),error); - IsOk = false; - break; - } - } - if (IsOk) - vector.push_back(files[i].toStdString()); - } else { - QString error = "Cannot read file info for "; - error += files[i].toStdString().c_str(); - error += "\n"; - error += "Maybe you're trying to open an image in an unsupported format?\n"; - QMessageBox::information(this,tr("Reading problem"),error); - } - } + for (int i = 0; i < files.size(); i++) + vector.push_back(files[i].toStdString()); sort(vector.begin(),vector.end()); if (vector.size() > 1) LoadImages(vector, vvImageReader::MERGEDWITHTIME); @@ -853,12 +840,11 @@ void vvMainWindow::LoadImages(std::vector files, vvImageReader::Loa int numberofsuccesulreads=0; //open images as 1 or multiples for (int i = 0; i < fileSize; i++) { - progress.SetText("Opening " + files[i]); progress.SetProgress(i,fileSize); qApp->processEvents(); - for (unsigned int j = 0; j < nSlices[i]; j++) { + for (unsigned int j = 0; j < nSlices[i]; j++) { //read the image and put it in mSlicerManagers vvSlicerManager* imageManager = new vvSlicerManager(4); qApp->processEvents(); @@ -873,7 +859,8 @@ void vvMainWindow::LoadImages(std::vector files, vvImageReader::Loa else { SetImageSucceed = imageManager->SetImages(files,filetype, number); } - if (!SetImageSucceed) { + + if (!SetImageSucceed) { QApplication::restoreOverrideCursor(); QString error = "Cannot open file \n"; error += imageManager->GetLastError().c_str(); @@ -891,7 +878,7 @@ void vvMainWindow::LoadImages(std::vector files, vvImageReader::Loa item->setToolTip(COLUMN_IMAGE_NAME, imageManager->GetListOfAbsoluteFilePathInOneString("image").c_str()); qApp->processEvents(); - //Create the buttons for reload and close + //Create the buttons for reload and close qApp->processEvents(); QTreePushButton* cButton = new QTreePushButton; cButton->setItem(item); @@ -914,13 +901,13 @@ void vvMainWindow::LoadImages(std::vector 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()); linkPanel->addImage(imageManager->GetFileName(), id.toStdString()); - connect(mSlicerManagers.back(), SIGNAL(currentImageChanged(std::string)), + connect(mSlicerManagers.back(), SIGNAL(currentImageChanged(std::string)), this,SLOT(CurrentImageChanged(std::string))); connect(mSlicerManagers.back(), SIGNAL(currentPickedImageChanged(std::string)), this, SLOT(CurrentPickedImageChanged(std::string))); @@ -938,6 +925,8 @@ void vvMainWindow::LoadImages(std::vector 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)), @@ -947,7 +936,8 @@ void vvMainWindow::LoadImages(std::vector files, vvImageReader::Loa connect(mSlicerManagers.back(), SIGNAL(ChangeImageWithIndexOffset(vvSlicerManager*,int,int)), this,SLOT(ChangeImageWithIndexOffset(vvSlicerManager*,int,int))); connect(mSlicerManagers.back(),SIGNAL(LandmarkAdded()),landmarksPanel,SLOT(AddPoint())); - InitSlicers(); + + InitSlicers(); numberofsuccesulreads++; } } @@ -1038,6 +1028,8 @@ void vvMainWindow::ImageInfoChanged() actionSave_As->setEnabled(1); actionAdd_VF_to_current_Image->setEnabled(1); actionAdd_fusion_image->setEnabled(1); + actionAdd_overlay_image_to_current_image->setEnabled(1); + actionAdd_USSequence_toCT->setEnabled(1); actionNorth_East_Window->setEnabled(1); actionNorth_West_Window->setEnabled(1); actionSouth_East_Window->setEnabled(1); @@ -1053,13 +1045,14 @@ void vvMainWindow::ImageInfoChanged() colorMapComboBox->setEnabled(1); for (int i = 0; i < DataTree->topLevelItem(index)->childCount(); i++) { if (DataTree->topLevelItem(index)->child(i)->data(1,Qt::UserRole).toString() == "overlay" || - DataTree->topLevelItem(index)->child(i)->data(1,Qt::UserRole).toString() == "fusion") { + DataTree->topLevelItem(index)->child(i)->data(1,Qt::UserRole).toString() == "fusion" || + DataTree->topLevelItem(index)->child(i)->data(1,Qt::UserRole).toString() == "fusionSequence") { colorMapComboBox->setEnabled(0); break; } } - std::vector origin; + std::vector origin; std::vector inputSpacing; std::vector inputSize; std::vector sizeMM; @@ -1069,7 +1062,9 @@ 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); @@ -1082,24 +1077,35 @@ 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(); + imageSelected = mSlicerManagers[index]->GetSlicer(0)->GetFusion(); + tSlice = mSlicerManagers[index]->GetSlicer(0)->GetFusionTSlice(); } + else if (DataTree->selectedItems()[0]->data(1,Qt::UserRole).toString() == "fusionSequence") { + 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(); + imageSelected = mSlicerManagers[index]->GetSlicer(0)->GetImage(); + tSlice = mSlicerManagers[index]->GetSlicer(0)->GetTSlice(); } else { - imageSelected = mSlicerManagers[index]->GetSlicer(0)->GetImage(); + imageSelected = mSlicerManagers[index]->GetSlicer(0)->GetImage(); + tSlice = mSlicerManagers[index]->GetSlicer(0)->GetTSlice(); } - dimension = imageSelected->GetNumberOfDimensions(); + dimension = imageSelected->GetNumberOfDimensions(); origin.resize(dimension); inputSpacing.resize(dimension); inputSize.resize(dimension); @@ -1113,7 +1119,7 @@ void vvMainWindow::ImageInfoChanged() NPixel *= inputSize[i]; } inputSizeInBytes = GetSizeInBytes(imageSelected->GetActualMemorySize()*1000); - + QString dim = QString::number(dimension) + " ("; dim += pixelType + ")"; @@ -1124,10 +1130,11 @@ 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(), + landmarksPanel->SetCurrentLandmarks(mSlicerManagers[index]->GetLandmarks(), mSlicerManagers[index]->GetSlicer(0)->GetImage()->GetVTKImages().size()); landmarksPanel->SetCurrentPath(mInputPathName.toStdString()); landmarksPanel->SetCurrentImage(mSlicerManagers[index]->GetFileName().c_str()); @@ -1140,7 +1147,7 @@ void vvMainWindow::ImageInfoChanged() } } - infoPanel->setFileName(image); + infoPanel->setFileName(image); infoPanel->setDimension(dim); infoPanel->setSizePixel(GetVectorIntAsString(inputSize)); infoPanel->setSizeMM(GetVectorDoubleAsString(sizeMM)); @@ -1160,9 +1167,11 @@ void vvMainWindow::ImageInfoChanged() break; } } - WindowLevelChanged(); + WindowLevelChanged(); + + slicingPresetComboBox->setCurrentIndex(mSlicerManagers[index]->GetSlicingPreset()); - if (mSlicerManagers[index]->GetSlicer(0)->GetVF()) { + if (mSlicerManagers[index]->GetSlicer(0)->GetVF()) { overlayPanel->getVFName(mSlicerManagers[index]->GetVFName().c_str()); overlayPanel->getVFProperty(mSlicerManagers[index]->GetSlicer(0)->GetVFSubSampling(), mSlicerManagers[index]->GetSlicer(0)->GetVFScale(), @@ -1176,8 +1185,8 @@ void vvMainWindow::ImageInfoChanged() } else { overlayPanel->getOverlayName(mSlicerManagers[index]->GetOverlayName().c_str()); } - - if (mSlicerManagers[index]->GetSlicer(0)->GetFusion()) { + + if (mSlicerManagers[index]->GetSlicer(0)->GetFusion()) { overlayPanel->getFusionName(mSlicerManagers[index]->GetFusionName().c_str()); } else { overlayPanel->getFusionName(mSlicerManagers[index]->GetFusionName().c_str()); @@ -1218,25 +1227,70 @@ void vvMainWindow::ShowHelpDialog() //------------------------------------------------------------------------------ void vvMainWindow::ChangeViewMode() { - QList size; + typedef struct _SIZE{ + QSplitter* splitter; + QList 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 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(); /* @@ -1244,10 +1298,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(); } } //------------------------------------------------------------------------------ @@ -1275,20 +1331,29 @@ QString vvMainWindow::GetSizeInBytes(unsigned long size) //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ -QString vvMainWindow::Get4x4MatrixDoubleAsString(vtkSmartPointer matrix) +QString vvMainWindow::Get4x4MatrixDoubleAsString(vtkSmartPointer 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; } @@ -1324,6 +1389,7 @@ QString vvMainWindow::GetVectorIntAsString(std::vector vectorInt) //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ +//this actually returns the SlicerManager index! int vvMainWindow::GetSlicerIndexFromItem(QTreeWidgetItem* item) { QString id = item->data(COLUMN_IMAGE_NAME,Qt::UserRole).toString(); @@ -1442,13 +1508,13 @@ void vvMainWindow::InitDisplay() for (int i = 0; i < DataTree->topLevelItemCount(); i++) { mSlicerManagers[i]->SetInteractorStyleNavigator(j,style); - //select the image only if previous are not selected + //select the image only if previous are not selected if (DataTree->topLevelItem(i)->data(j+1,Qt::CheckStateRole).toInt() > 1) { mSlicerManagers[i]->UpdateSlicer(j,1); - AlreadySelected = true; + AlreadySelected = true; } else if (i == DataTree->topLevelItemCount()-1 && !AlreadySelected) { if (DataTree->selectedItems().size() == 0) - DataTree->topLevelItem(i)->setSelected(1); + DataTree->topLevelItem(i)->setSelected(1); //RB: crash here when loading an image... DataTree->topLevelItem(i)->setData(j+1,Qt::CheckStateRole,2); mSlicerManagers[i]->UpdateSlicer(j,1); DisplaySliders(i,j); @@ -1466,38 +1532,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); } //------------------------------------------------------------------------------ @@ -1523,6 +1579,16 @@ void vvMainWindow::CloseImage(QTreeWidgetItem* item, int column) overlay_index++; if (DataTree->topLevelItem(index)->child(child) == item) break; } + if (overlay_type=="fusionSequence") { + //removing the overlay sequence in a fusion sequence visualization mode + //TODO: remove the synchronization (transform matrices, etc...) + + //=> unlink and untie the slicer managers + mSlicerManagers[index]->SetFusionSequenceInvolvmentCode(-1); + mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->SetFusionSequenceInvolvmentCode(-1); + RemoveLink(mSlicerManagers[index]->GetId().c_str(), mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->GetId().c_str()); + + } mSlicerManagers[index]->RemoveActor(overlay_type, overlay_index-1); mSlicerManagers[index]->SetColorMap(0); DataTree->topLevelItem(index)->takeChild(DataTree->topLevelItem(index)->indexOfChild(item)); @@ -1558,6 +1624,17 @@ void vvMainWindow::CloseImage(QTreeWidgetItem* item, int column) } linkPanel->removeImage(index); mSlicerManagers[index]->RemoveActors(); + + //if the slicer manager was involved in a fusion sequence visualization... + if ( item->data(1,Qt::UserRole).toString().toStdString() == "fusionSequence" ) { + //TODO + //make sure both SlicerManager exit the FusionSequence visualization mode + //disable the temporal and spatial sync? make sure we reset the spatial transforms to their initial states... + mSlicerManagers[index]->SetFusionSequenceInvolvmentCode(-1); + mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->SetFusionSequenceInvolvmentCode(-1); + } + + //remove the slicer manager delete mSlicerManagers[index]; mSlicerManagers.erase(Manageriter); @@ -1583,17 +1660,24 @@ void vvMainWindow::ReloadImage(QTreeWidgetItem* item, int column) int index = GetSlicerIndexFromItem(item); QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); QString role=item->data(1,Qt::UserRole).toString(); - if ( role == "vector"){ + if ( role == "vector") { mSlicerManagers[index]->ReloadVF(); } - else if (role == "overlay"){ + else if (role == "overlay") { mSlicerManagers[index]->ReloadOverlay(); } - else if (role == "fusion"){ + else if (role == "fusion") { mSlicerManagers[index]->ReloadFusion(); } - else{ + else if (role == "fusionSequence") { + //both versions of the secondary sequence must be updated. + mSlicerManagers[index]->ReloadFusionSequence(); + mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->Reload(); + } + else { mSlicerManagers[index]->Reload(); + //if we update the secondary sequence, then the overlay of the main sequence should also be updated + if (mSlicerManagers[index]->IsSecondarySequenceOfFusionSequence()) mSlicerManagers[mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()]->ReloadFusionSequence(); } // Update view and info ImageInfoChanged(); @@ -1650,15 +1734,38 @@ void vvMainWindow::WindowLevelChanged() else overlayPanel->getOverlayProperty(-1,0,0.,0.); - // Fusion image - if (mSlicerManagers[index]->GetSlicer(0)->GetFusion()) - overlayPanel->getFusionProperty(mSlicerManagers[index]->GetFusionOpacity(), - mSlicerManagers[index]->GetFusionThresholdOpacity(), - mSlicerManagers[index]->GetFusionColorMap(), - mSlicerManagers[index]->GetFusionWindow(), - mSlicerManagers[index]->GetFusionLevel()); + // Fusion & SequenceFusion image + if (mSlicerManagers[index]->GetSlicer(0)->GetFusion()) { + overlayPanel->getFusionProperty(mSlicerManagers[index]->GetFusionOpacity(), + mSlicerManagers[index]->GetFusionThresholdOpacity(), + mSlicerManagers[index]->GetFusionColorMap(), + mSlicerManagers[index]->GetFusionWindow(), + mSlicerManagers[index]->GetFusionLevel()); + if (mSlicerManagers[index]->IsMainSequenceOfFusionSequence()) { + overlayPanel->getFusionSequenceProperty(mSlicerManagers[index]->GetFusionSequenceFrameIndex(), + mSlicerManagers[index]->GetFusionSequenceSpatialSyncFlag(), + mSlicerManagers[index]->GetFusionSequenceNbFrames(), + mSlicerManagers[index]->GetFusionSequenceTemporalSyncFlag()); + } + } + else if ( mSlicerManagers[index]->IsSecondarySequenceOfFusionSequence() ) { + //if the image is involved in a fusion sequence, preserve the overlay panel! + int ind = mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager(); + overlayPanel->getFusionProperty(mSlicerManagers[ind]->GetFusionOpacity(), + mSlicerManagers[ind]->GetFusionThresholdOpacity(), + mSlicerManagers[ind]->GetFusionColorMap(), + mSlicerManagers[ind]->GetFusionWindow(), + mSlicerManagers[ind]->GetFusionLevel()); + overlayPanel->getFusionSequenceProperty(mSlicerManagers[ind]->GetFusionSequenceFrameIndex(), + mSlicerManagers[ind]->GetFusionSequenceSpatialSyncFlag(), + mSlicerManagers[ind]->GetFusionSequenceNbFrames(), + mSlicerManagers[ind]->GetFusionSequenceTemporalSyncFlag()); + } else - overlayPanel->getFusionProperty(-1, -1, -1, -1, -1); + { + overlayPanel->getFusionProperty(-1, -1, -1, -1, -1); + overlayPanel->getFusionSequenceProperty(-1, false, 0, false); + } } //------------------------------------------------------------------------------ @@ -1697,6 +1804,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() { @@ -1737,19 +1854,44 @@ void vvMainWindow::ApplyWindowLevelToAllImages() //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ -void vvMainWindow::UpdateLinkManager(std::string id, int slicer, double x, double y, double z, int temps) +void vvMainWindow::ApplyWindowToSetOfImages(double window, unsigned int indexMin, unsigned int indexMax) { - for (unsigned int i = 0; i < mSlicerManagers.size(); i++) { - if (mSlicerManagers[i]->GetId() == id) { - //mSlicerManagers[i]->SetTSlice(temps); - mSlicerManagers[i]->GetSlicer(slicer)->SetCurrentPosition(x,y,z,temps); - mSlicerManagers[i]->UpdateViews(0,slicer); - break; - } + 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) +{ + for (unsigned int i = 0; i < mSlicerManagers.size(); i++) { + if (mSlicerManagers[i]->GetId() == id) { + mSlicerManagers[i]->GetSlicer(slicer)->SetCurrentPosition(x,y,z,temps); + mSlicerManagers[i]->UpdateViews(0,slicer); + break; + } + } +} +//------------------------------------------------------------------------------ + //------------------------------------------------------------------------------ void vvMainWindow::UpdateLinkedNavigation(std::string id, vvSlicerManager * sm, vvSlicer* refSlicer) { @@ -1821,79 +1963,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 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 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!"); } //------------------------------------------------------------------------------ @@ -1932,7 +2089,8 @@ void vvMainWindow::SelectFusionImage() //check if one fusion image is added for (int child = 0; child < DataTree->topLevelItem(index)->childCount(); child++) - if (DataTree->topLevelItem(index)->child(child)->data(1,Qt::UserRole).toString() == "fusion") { + if ( (DataTree->topLevelItem(index)->child(child)->data(1,Qt::UserRole).toString() == "fusion") || + (DataTree->topLevelItem(index)->child(child)->data(1,Qt::UserRole).toString() == "fusionSequence") ) { QString error = "Cannot add more than one fusion image\n"; error += "Please remove first "; error += DataTree->topLevelItem(index)->child(child)->data(COLUMN_IMAGE_NAME,Qt::DisplayRole).toString(); @@ -1961,73 +2119,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!"); } //------------------------------------------------------------------------------ @@ -2048,7 +2211,11 @@ void vvMainWindow::OpenField() QString Extensions = "Images ( *.mhd)"; Extensions += ";;Images ( *.mha)"; - Extensions += ";;Images ( *.vf)"; + Extensions += ";;VF Images ( *.vf)"; + Extensions += ";;nii Images ( *.nii)"; + Extensions += ";;nrrd Images ( *.nrrd)"; + Extensions += ";;nhdr Images ( *.nhdr)"; + Extensions += ";;All Files (*)"; QString file = QFileDialog::getOpenFileName(this,tr("Load deformation field"),mInputPathName,Extensions); if (!file.isEmpty()) AddField(file,index); @@ -2192,7 +2359,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()) { @@ -2201,12 +2368,295 @@ 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(); + mSlicerManagers[index]->Render(); } } //------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +void vvMainWindow::SelectFusionSequence() +{ + //get the index of the slicer manager of the main sequence (CT) + int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]); + //check if one overlay image is already associated + for (int child = 0; child < DataTree->topLevelItem(index)->childCount(); child++) + if ( (DataTree->topLevelItem(index)->child(child)->data(1,Qt::UserRole).toString() == "fusion") || + (DataTree->topLevelItem(index)->child(child)->data(1,Qt::UserRole).toString() == "fusionSequence") ) { + QString error = "Cannot add more than one compared image\n"; + error += "Please remove first "; + error += DataTree->topLevelItem(index)->child(child)->data(COLUMN_IMAGE_NAME,Qt::DisplayRole).toString(); + QMessageBox::information(this,tr("Problem adding compared image !"),error); + return; + } + + QString Extensions = EXTENSIONS; + Extensions += ";;All Files (*)"; + QStringList files = QFileDialog::getOpenFileNames(this,tr("Load Overlay image sequence"),mInputPathName,Extensions); + if (files.isEmpty()) + return; + + std::vector vecFileNames; + for (int i = 0; i < files.size(); i++) { + vecFileNames.push_back(files[i].toStdString()); + } + + //associate the secondary sequence (US) to the main one + AddFusionSequence(index,vecFileNames,vvImageReader::MERGEDWITHTIME); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvMainWindow::SelectFusionSequenceTemporalSignal() { + + //make sure the index is right? + //in the end, I should attach the temporal data to the right sequence! + int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]); + //in case the other sequence got selected, make sure we select the primary sequence + if ( (!mSlicerManagers[index]->GetSlicer(0)->GetFusion()) && mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager()>=0 ) { + index = mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager(); + } + + //open a dialog box to find a file + QString Extensions = EXTENSIONS; + Extensions += ";;All Files (*)"; + QString fileName = QFileDialog::getOpenFileName(this,tr("Load respiratory signal for fused sequence"),mInputPathName,Extensions); + if (fileName.isNull()) + return; + + //read it as a vector of values + std::vector signal; + //...TODO, look for itk functions that can do that... vnl in the worst case. + signal.push_back(1);signal.push_back(2); + + //TODO: instead: if the loaded signal is longer, just crop it... + //this allows loading only the first few frames when testing. + //->maybe raise a message that this behavior may be unsafe... + + //if compatible with the fused image sequence (number of images = number of entries), enable the temporalSync + if ( signal.size() >= mSlicerManagers[index]->GetFusionSequenceNbFrames()) { + //for convenience, associate this sequence to both the current slicer manager, and to the linked one + mSlicerManagers[index]->SetFusionSequenceTemporalSignal(signal); + mSlicerManagers[ mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager() ]->SetFusionSequenceTemporalSignal(signal); + overlayPanel->enableFusionSequenceTemporalSync(); + QMessageBox::information(this,tr("Adding signal"),"would add the signal from file: "+ fileName); + } + else {//else, send a message to signal the failure... + QString error = "The provided signal doesn't have the same duration as the sequence\n"; + error += "Ignoring file: " + fileName; + QMessageBox::information(this,tr("Problem adding signal!"),error); + return; + } + +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +//when this function is called index is the slicer manager index corresponding to the main sequence (CT) +//the files behind fileNames points to the data for the secondary sequence +void vvMainWindow::AddFusionSequence(int index, std::vector 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(); + + std::string filename = itksys::SystemTools::GetFilenameWithoutExtension(file.toStdString()).c_str(); + + if (mSlicerManagers[index]->SetFusionSequence(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("fusionSequence")); + + 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("fusionSequence").c_str()); + qApp->processEvents(); + 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))); + + 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); + + //store the original transform matrix + int indexParent = GetSlicerIndexFromItem( DataTree->topLevelItem(index) ); + mSlicerManagers[indexParent]->SetFusionSequenceMainTransformMatrix( mSlicerManagers[indexParent]->GetSlicer(0)->GetImage()->GetTransform()[0]->GetMatrix() ); + + //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(); + // Update the display to update, e.g., the sliders + for(int i=0; i<4; i++) + DisplaySliders(index, i); + + + //This loads the secondary sequence (US) as an independent sequence + LoadImages(fileNames, type); + //reset the transforms to identiy + for (unsigned i=0 ; iGetImage()->GetTransform().size() ; i++) { + mSlicerManagers.back()->GetImage()->GetTransform()[i]->Identity(); + mSlicerManagers.back()->GetImage()->GetTransform()[i]->Update(); + } + + //automatically link both images... + AddLink(mSlicerManagers[indexParent]->GetId().c_str(), mSlicerManagers.back()->GetId().c_str(), false); + + //tie the main and secondary sequences by raising flags and informing each another of their respective SlicerManager indices + mSlicerManagers[indexParent]->SetFusionSequenceIndexOfLinkedManager(mSlicerManagers.size()-1); + mSlicerManagers[indexParent]->SetFusionSequenceInvolvmentCode(0); //main sequence + mSlicerManagers.back()->SetFusionSequenceIndexOfLinkedManager(indexParent); + mSlicerManagers.back()->SetFusionSequenceInvolvmentCode(1); //secondary sequence + + } 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(); + } + else { + QMessageBox::information(this,tr("Problem reading fusion sequence !"),"File doesn't exist!"); + return; + } + +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +//fusionSequenceFrameIndex and fusionSequenceNbFrames are relative to the secondary sequence (US) +void vvMainWindow::SetFusionSequenceProperty(int fusionSequenceFrameIndex, bool spatialSyncFlag, unsigned int fusionSequenceNbFrames, bool temporalSyncFlag) +{ + int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]); + + //check if the focus moved to the linked sequence, and in this case, select the master sequence instead + if (!mSlicerManagers[index]->IsMainSequenceOfFusionSequence()) { + index = mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager(); + } + + int secondaryIndex = mSlicerManagers[index]->GetFusionSequenceIndexOfLinkedManager(); + if ( (!mSlicerManagers[index]->IsMainSequenceOfFusionSequence()) || + (!mSlicerManagers[secondaryIndex]->IsSecondarySequenceOfFusionSequence()) ) + {return;} //this should never happen, raise an exception? + + if (mSlicerManagers[index]->GetSlicer(0)->GetFusion()) { + int indexParent = GetSlicerIndexFromItem( DataTree->topLevelItem(index) ); +//check whether this really makes sense to look at 'parentIndex'... +std::cout<<"index = "<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()) { @@ -2301,8 +2779,6 @@ void vvMainWindow::SaveCurrentStateAs(const std::string& stateFile) { vvSaveState save_state; save_state.Run(this, stateFile); - - std::cout << "void vvMainWindow::SaveCurrentState()" << std::endl; } //------------------------------------------------------------------------------ @@ -2333,8 +2809,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; @@ -2391,20 +2873,31 @@ void vvMainWindow::ChangeImageWithIndexOffset(vvSlicerManager *sm, int slicer, i DisplayChanged(item,slicer+1); } //------------------------------------------------------------------------------ - void vvMainWindow::HorizontalSliderMoved(int value,int column, int slicer_index) { - for (unsigned int i = 0; i < mSlicerManagers.size(); i++) { - if (DataTree->topLevelItem(i)->data(column,Qt::CheckStateRole).toInt() > 1) { - for (int j = 0; j < 4; j++) { - mSlicerManagers[i]->SetTSliceInSlicer(value,j); - //if (mSlicerManagers[i]->GetSlicer(j)->GetImageActor()->GetVisibility()) - //UpdateTSlice(j,value); - } - mSlicerManagers[i]->GetSlicer(slicer_index)->Render(); - break; - } - } + for (unsigned int i = 0; i < mSlicerManagers.size(); i++) { + if (DataTree->topLevelItem(i)->data(column,Qt::CheckStateRole).toInt() > 1) { + + if (mSlicerManagers[i]->IsInvolvedInFusionSequence()) { + //if the slicerManager is involved in a fusionSequence as the secondary sequence, then update the slider position in the overlay panel and everything accordingly + if (mSlicerManagers[i]->IsSecondarySequenceOfFusionSequence()) { overlayPanel->updateFusionSequenceSliderValueFromWindow(value, true); } + else { //if this is the primary sequence that has been modified + if (mSlicerManagers[i]->GetFusionSequenceTemporalSyncFlag()) { + //TODO: if temporal sync is active + //estimate a corresponding time index for the secondary (US) sequence, and update it accordingly. + int estimatedValue=0; + overlayPanel->updateFusionSequenceSliderValueFromWindow(estimatedValue, true); + } + } + } + + for (int j = 0; j < 4; j++) { + mSlicerManagers[i]->SetTSliceInSlicer(value,j); + } + mSlicerManagers[i]->GetSlicer(slicer_index)->Render(); + break; + } + } } //------------------------------------------------------------------------------ @@ -2591,23 +3084,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); } } //------------------------------------------------------------------------------ @@ -2703,11 +3197,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]); @@ -2722,82 +3219,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; iSetNextTSlice(0); - vtkSmartPointer w2i = vtkSmartPointer::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; iSetInput(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 w2i = vtkSmartPointer::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 !!!")); } } //------------------------------------------------------------------------------ @@ -2832,7 +3358,7 @@ void vvMainWindow::PlayPause() int image_number=DataTree->topLevelItemCount(); bool has_temporal; for (int i=0; iGetImage()->GetVTKImages().size() > 1) { + if (mSlicerManagers[i]->GetSlicer(0)->GetTMax() > 0) { has_temporal=true; break; } @@ -2853,7 +3379,7 @@ void vvMainWindow::PlayNext() ///Only play one slicer per SM, and only if the SM is being displayed for (int i=0; iGetImage()->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; @@ -2876,6 +3402,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(); @@ -2962,7 +3494,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()); @@ -2980,13 +3512,17 @@ vvSlicerManager* vvMainWindow::AddImage(vvImage::Pointer image,std::string filen connect(mSlicerManagers.back(), SIGNAL(UpdateOverlay(int, double, double)), this, SLOT(OverlayChanged(int,double,double))); connect(mSlicerManagers.back(), SIGNAL(UpdateFusion(int, double)), - this, SLOT(FusionChanged(int,double))); + this, SLOT(FusionChanged(int,double))); + //connect(mSlicerManagers.back(), SIGNAL(UpdateFusionSequence(int, bool, unsigned int)), + // this, SLOT(FusionSequenceChanged(int, bool, unsigned int))); connect(mSlicerManagers.back(), SIGNAL(WindowLevelChanged()), this,SLOT(WindowLevelChanged())); connect(mSlicerManagers.back(), SIGNAL(UpdateSlice(int,int)), 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)), @@ -2996,6 +3532,8 @@ vvSlicerManager* vvMainWindow::AddImage(vvImage::Pointer image,std::string filen connect(mSlicerManagers.back(), SIGNAL(ChangeImageWithIndexOffset(vvSlicerManager*,int,int)), this,SLOT(ChangeImageWithIndexOffset(vvSlicerManager*,int,int))); connect(mSlicerManagers.back(), SIGNAL(LandmarkAdded()),landmarksPanel,SLOT(AddPoint())); + + UpdateTree(); qApp->processEvents(); InitSlicers();