#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 *.usf)"
+#else
+ #define EXTENSIONS "Images ( *.bmp *.png *.jpeg *.jpg *.tif *.mhd *.mha *.hdr *.vox *.his *.xdr *.SCAN *.nii *.nrrd *.nhdr)"
+#endif
/*Data Tree values
0,Qt::UserRole full filename
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(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
//------------------------------------------------------------------------------
-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;
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);
}
}
//------------------------------------------------------------------------------
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)),
infoPanel->setOrigin(GetVectorDoubleAsString(origin));
infoPanel->setSpacing(GetVectorDoubleAsString(inputSpacing));
infoPanel->setNPixel(QString::number(NPixel)+" ("+inputSizeInBytes+")");
- transformation = imageSelected->GetTransform()->GetMatrix();
+ transformation = imageSelected->GetTransform()[mSlicerManagers[index]->GetTSlice()]->GetMatrix();
infoPanel->setTransformation(Get4x4MatrixDoubleAsString(transformation));
landmarksPanel->SetCurrentLandmarks(mSlicerManagers[index]->GetLandmarks(),
}
}
WindowLevelChanged();
+ slicingPresetComboBox->setCurrentIndex(mSlicerManagers[index]->GetSlicingPreset());
if (mSlicerManagers[index]->GetSlicer(0)->GetVF()) {
overlayPanel->getVFName(mSlicerManagers[index]->GetVFName().c_str());
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
-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;
}
}
//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+void vvMainWindow::UpdateSlicingPreset()
+{
+ if (DataTree->selectedItems().size()) {
+ int index = GetSlicerIndexFromItem(DataTree->selectedItems()[0]);
+ mSlicerManagers[index]->SetSlicingPreset(vvSlicerManager::SlicingPresetType(slicingPresetComboBox->currentIndex()));
+ }
+}
+//------------------------------------------------------------------------------
+
//------------------------------------------------------------------------------
void vvMainWindow::UpdateColorMap()
{
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(file.toStdString().c_str());
+ reader->SetFileName(fileNames[0].c_str());
reader->ReadImageInformation();
std::string component = reader->GetComponentTypeAsString(reader->GetComponentType());
int dimension = reader->GetNumberOfDimensions();
qApp->processEvents();
std::string filename = itksys::SystemTools::GetFilenameWithoutExtension(file.toStdString()).c_str();
- if (mSlicerManagers[index]->SetOverlay(file.toStdString(),dimension, component)) {
+ 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());
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
-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()) {
mSlicerManagers[index]->SetFusionThresholdOpacity(thresOpacity);
mSlicerManagers[index]->SetFusionWindow(window);
mSlicerManagers[index]->SetFusionLevel(level);
+ mSlicerManagers[index]->SetFusionShowLegend(showLegend);
mSlicerManagers[index]->SetColorMap(0);
mSlicerManagers[index]->Render();
}
} 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++) {
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()) {
{
vvSaveState save_state;
save_state.Run(this, stateFile);
-
- std::cout << "void vvMainWindow::SaveCurrentState()" << std::endl;
}
//------------------------------------------------------------------------------
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]);
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
+ // Take video if not null
+ if(vidwriter!=NULL){
+ vidwriter->SetInput(image);
+ vidwriter->SetFileName(fileName.toStdString().c_str());
+ vidwriter->Start();
vvImage * vvImg = mSlicerManagers[smIndex]->GetImage();
int nSlice = vvImg->GetVTKImages().size();
for(int i=0; i<nSlice; i++) {
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 !!!"));
}
}
//------------------------------------------------------------------------------
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)),