1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
5 - University of LYON http://www.universite-lyon.fr/
6 - Léon Bérard cancer center http://www.centreleonberard.fr
7 - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the copyright notices for more information.
13 It is distributed under dual licence
15 - BSD See included LICENSE.txt file
16 - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================**/
20 #include "vvToolROIManager.h"
21 #include "vvImageReader.h"
22 #include "vvROIActor.h"
24 #include "vvROIActor.h"
27 #include <QFileDialog>
28 #include <QMessageBox>
29 #include <QColorDialog>
30 #include <QAbstractEventDispatcher>
33 #include <vtkLookupTable.h>
34 #include <vtkRenderWindow.h>
36 //------------------------------------------------------------------------------
37 // Create the tool and automagically (I like this word) insert it in
38 // the main window menu.
39 ADD_TOOL(vvToolROIManager);
40 //------------------------------------------------------------------------------
42 //------------------------------------------------------------------------------
43 vvToolROIManager::vvToolROIManager(vvMainWindowBase * parent, Qt::WindowFlags f):
44 // vvToolWidgetBase(parent, f),
45 // if Qt::Widget -> No dialog in this case (in tab) ; PB = "invisible widget on menu" !
46 // if "f" normal widget
47 QWidget(parent->GetTab()->widget(4)),
48 vvToolBase<vvToolROIManager>(parent),
49 Ui::vvToolROIManager()
51 // Insert the current QWidget into the tab layout (required)
52 QWidget * mother = qFindChild<QWidget*>(parent->GetTab(), "ROItab");
53 mother->layout()->addWidget(this);
57 Ui_vvToolROIManager::setupUi(this);
58 setAttribute(Qt::WA_DeleteOnClose);
60 mTree->header()->resizeSection(0, 30);
61 parent->GetTab()->setCurrentIndex(2);
64 mDefaultLUTColor = vtkSmartPointer<vtkLookupTable>::New();
65 DD(mDefaultLUTColor->GetNumberOfTableValues());
66 for(int i=0; i<mDefaultLUTColor->GetNumberOfTableValues(); i++) {
67 double r = (rand()/(RAND_MAX+1.0));
68 double v = (rand()/(RAND_MAX+1.0));
69 double b = (rand()/(RAND_MAX+1.0));
70 mDefaultLUTColor->SetTableValue(i, r, v, b);
71 // std::cout << "mDefaultLUTColor->SetTableValue(" << i << ", " << r << ", " << v << ", " << b << ");" << std::endl;
73 #include "vvDefaultLut.h"
76 mNumberOfVisibleROI = 0;
77 mNumberOfVisibleContourROI = 0;
79 // Select the current image as the target
80 int i = parent->GetSlicerManagerCurrentIndex();
81 InputIsSelected(parent->GetSlicerManagers()[i]);
83 // Connect event from mainwindow to this widget
84 connect(parent, SIGNAL(AnImageIsBeingClosed(vvSlicerManager *)),
85 this, SLOT(AnImageIsBeingClosed(vvSlicerManager *)));
86 connect(parent, SIGNAL(SelectedImageHasChanged(vvSlicerManager *)),
87 this, SLOT(SelectedImageHasChanged(vvSlicerManager *)));
88 connect(mOpenBinaryButton, SIGNAL(clicked()), this, SLOT(OpenBinaryImage()));
89 connect(mTree, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItemChangedInTree()));
90 connect(mCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleROIToggled(bool)));
91 connect(mOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(OpacityChanged(int)));
92 connect(mChangeColorButton, SIGNAL(clicked()), this, SLOT(ChangeColor()));
93 connect(mContourCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleContourROIToggled(bool)));
94 connect(mChangeContourColorButton, SIGNAL(clicked()), this, SLOT(ChangeContourColor()));
95 connect(mContourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeContourWidth(int)));
96 connect(mDepthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeDepth(int)));
97 connect(mReloadButton, SIGNAL(clicked()), this, SLOT(ReloadCurrentROI()));
98 connect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int)));
99 connect(mContourCheckBoxShowAll, SIGNAL(toggled(bool)), this, SLOT(AllVisibleContourROIToggled(bool)));
101 // mMainWindowBase->GetTab()->setTabIcon(mTabNumber, GetToolIcon());
103 //------------------------------------------------------------------------------
106 //------------------------------------------------------------------------------
107 vvToolROIManager::~vvToolROIManager()
109 std::cout << "vvToolROIManager::~vvToolROIManager()" << std::endl;
111 //------------------------------------------------------------------------------
114 //------------------------------------------------------------------------------
116 void vvToolROIManager::Initialize() {
117 SetToolName("ROIManager");
118 SetToolMenuName("Display ROI (binary image)");
119 SetToolIconFilename(":/common/icons/tool-roi.png");
120 SetToolTip("Display ROI from a binary image.");
121 SetToolExperimental(true);
123 //------------------------------------------------------------------------------
126 //------------------------------------------------------------------------------
127 void vvToolROIManager::InputIsSelected(vvSlicerManager *m)
129 std::cout << "vvToolROIManager::InputIsSelected()" << std::endl;
133 connect(mCloseButton, SIGNAL(clicked()), this, SLOT(close()));
137 mCurrentImage = mSlicerManager->GetImage();
140 if (mCurrentImage->GetNumberOfDimensions() != 3) {
141 QMessageBox::information(this,tr("Sorry only 3D yet"), tr("Sorry only 3D yet"));
147 mLabelInputInfo->setText(QString("%1").arg(m->GetFileName().c_str()));
149 // Auto display browser to select new contours
152 //------------------------------------------------------------------------------
155 //------------------------------------------------------------------------------
156 void vvToolROIManager::AnImageIsBeingClosed(vvSlicerManager * m)
158 if (m == mSlicerManager) close();
160 //------------------------------------------------------------------------------
163 //------------------------------------------------------------------------------
164 void vvToolROIManager::SelectedImageHasChanged(vvSlicerManager * m) {
165 if (m != mSlicerManager) hide();
168 //------------------------------------------------------------------------------
171 //------------------------------------------------------------------------------
172 void vvToolROIManager::OpenBinaryImage()
175 QString Extensions = "Images files ( *.mha *.mhd *.hdr *.his)";
176 Extensions += ";;All Files (*)";
177 QStringList filename =
178 QFileDialog::getOpenFileNames(this,tr("Open binary image"),
179 mMainWindowBase->GetInputPathName(),Extensions);
180 if (filename.size() == 0) return;
182 // For each selected file, open the image
183 for(int i=0; i<filename.size(); i++) {
185 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
186 vvImageReader::Pointer reader = vvImageReader::New();
187 std::vector<std::string> filenames;
188 filenames.push_back(filename[i].toStdString());
189 reader->SetInputFilenames(filenames);
190 reader->Update(vvImageReader::IMAGE);
191 QApplication::restoreOverrideCursor();
193 if (reader->GetLastError().size() != 0) {
194 std::cerr << "Error while reading " << filename[i].toStdString() << std::endl;
195 QString error = "Cannot open file \n";
196 error += reader->GetLastError().c_str();
197 QMessageBox::information(this,tr("Reading problem"),error);
200 vvImage::Pointer binaryImage = reader->GetOutput();
201 AddImage(binaryImage, filename[i].toStdString(), mBackgroundValueSpinBox->value(),
202 (!mBGModeCheckBox->isChecked()));
203 mOpenedBinaryImage.push_back(binaryImage);
206 // Update the contours
209 //------------------------------------------------------------------------------
212 //------------------------------------------------------------------------------
213 void vvToolROIManager::AddImage(vvImage * binaryImage, std::string filename,
214 double BG, bool modeBG)
219 int dim = mCurrentImage->GetNumberOfDimensions();
220 int bin_dim = binaryImage->GetNumberOfDimensions();
222 std::ostringstream os;
223 os << "Error. Loaded binary image is " << bin_dim
224 << "D while selected image is " << dim << "D" << std::endl;
225 QMessageBox::information(this,tr("Reading problem"),os.str().c_str());
230 int n = mROIList.size();
233 // Compute the name of the new ROI
234 std::ostringstream oss;
235 oss << vtksys::SystemTools::GetFilenameName(vtksys::SystemTools::GetFilenameWithoutLastExtension(filename));
236 std::string name = oss.str();
240 std::vector<double> color;
246 clitk::DicomRT_ROI::Pointer roi = clitk::DicomRT_ROI::New();
247 roi->SetFromBinaryImage(binaryImage, n, name, color, filename);
249 // Add a new roi to the list
250 mROIList.push_back(roi);
254 roi->SetBackgroundValueLabelImage(BG);
256 roi->SetForegroundValueLabelImage(BG);
260 if (n<mDefaultLUTColor->GetNumberOfTableValues ()) {
261 double * color = mDefaultLUTColor->GetTableValue(n % mDefaultLUTColor->GetNumberOfTableValues ());
262 roi->SetDisplayColor(color[0], color[1], color[2]);
265 // Add a new roi actor
266 QSharedPointer<vvROIActor> actor = QSharedPointer<vvROIActor>(new vvROIActor);
267 actor->SetBGMode(modeBG);
269 actor->SetSlicerManager(mSlicerManager);
270 actor->Initialize(n+1); // depth is n+1 to start at 1
271 mROIActorsList.push_back(actor);
273 // CheckBox for "All"
274 if (actor->IsVisible()) mNumberOfVisibleROI++;
275 if (actor->IsContourVisible()) mNumberOfVisibleContourROI++;
278 mTreeWidgetList.push_back(QSharedPointer<QTreeWidgetItem>(new QTreeWidgetItem(mTree)));
279 QTreeWidgetItem * w = mTreeWidgetList.back().data();
280 w->setText(0, QString("%1").arg(roi->GetROINumber()));
281 w->setText(1, QString("%1").arg(roi->GetName().c_str()));
282 w->setText(3, QString("%1").arg(actor->GetDepth()));
283 QBrush brush(QColor(roi->GetDisplayColor()[0]*255,
284 roi->GetDisplayColor()[1]*255,
285 roi->GetDisplayColor()[2]*255));
286 brush.setStyle(Qt::SolidPattern);
287 w->setBackground(2, brush);
288 mMapROIToTreeWidget[roi] = w;
289 mMapTreeWidgetToROI[w] = roi;
290 mTree->resizeColumnToContents(0);
291 mTree->resizeColumnToContents(1);
294 UpdateAllROIStatus();
296 //------------------------------------------------------------------------------
299 //------------------------------------------------------------------------------
300 void vvToolROIManager::UpdateAllContours()
302 // Render loaded ROIs (the first is sufficient)
303 for(unsigned int i=0; i<mROIList.size(); i++) {
304 mROIActorsList[i]->Update();
306 for(int i=0; i<mSlicerManager->GetNumberOfSlicers(); i++) {
307 mSlicerManager->GetSlicer(i)->Render();
310 //------------------------------------------------------------------------------
313 //------------------------------------------------------------------------------
314 void vvToolROIManager::UpdateAllROIStatus() {
316 int nb = mROIList.size();
317 for(int i=0; i<nb; i++) {
318 if (mROIActorsList[i]->IsVisible()) {
325 disconnect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int)));
326 disconnect(mContourCheckBoxShowAll, SIGNAL(toggled(bool)), this, SLOT(AllVisibleContourROIToggled(bool)));
327 if (nbVisible == nb) mCheckBoxShowAll->setCheckState(Qt::Checked);
329 if (nbVisible == 0) mCheckBoxShowAll->setCheckState(Qt::Unchecked);
330 else mCheckBoxShowAll->setCheckState(Qt::PartiallyChecked);
332 connect(mContourCheckBoxShowAll, SIGNAL(toggled(bool)), this, SLOT(AllVisibleContourROIToggled(bool)));
333 connect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int)));
335 //------------------------------------------------------------------------------
338 //------------------------------------------------------------------------------
339 void vvToolROIManager::SelectedItemChangedInTree() {
341 // Search which roi is selected
342 QList<QTreeWidgetItem *> l = mTree->selectedItems();
344 // mCurrentROIActor = 0;
346 mGroupBoxROI->setEnabled(false);
349 QTreeWidgetItem * w = l[0];
350 //std::cout << "selected item -> " << w->text(1).toStdString() << std::endl;
351 //std::cout << "m_NumberOfTool -> " << m_NumberOfTool << std::endl;
352 if (mMapTreeWidgetToROI.find(w) == mMapTreeWidgetToROI.end()) {
353 // mCurrentROIActor = 0;
355 mGroupBoxROI->setEnabled(false);
358 clitk::DicomRT_ROI * roi = mMapTreeWidgetToROI[w];
359 // Get selected roi actor
360 QSharedPointer<vvROIActor> actor = mROIActorsList[roi->GetROINumber()];
362 mCurrentROIActor = actor;
364 // Warning -> avoid unuseful Render here by disconnect slider
366 disconnect(mTree, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItemChangedInTree()));
367 disconnect(mCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleROIToggled(bool)));
368 disconnect(mOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(OpacityChanged(int)));
369 disconnect(mChangeColorButton, SIGNAL(clicked()), this, SLOT(ChangeColor()));
370 disconnect(mContourCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleContourROIToggled(bool)));
371 disconnect(mChangeContourColorButton, SIGNAL(clicked()), this, SLOT(ChangeContourColor()));
372 disconnect(mContourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeContourWidth(int)));
373 disconnect(mDepthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeDepth(int)));
375 mGroupBoxROI->setEnabled(true);
376 mROInameLabel->setText(roi->GetName().c_str());
377 mCheckBoxShow->setChecked(actor->IsVisible());
378 mContourCheckBoxShow->setChecked(actor->IsContourVisible());
379 mContourWidthSpinBox->setValue(actor->GetContourWidth());
380 mDepthSpinBox->setValue(actor->GetDepth());
381 w->setText(3, QString("%1").arg(actor->GetDepth()));
382 mOpacitySlider->setValue((int)lrint(actor->GetOpacity()*100));
383 mOpacitySpinBox->setValue((int)lrint(actor->GetOpacity()*100));
385 connect(mTree, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItemChangedInTree()));
386 connect(mCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleROIToggled(bool)));
387 connect(mOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(OpacityChanged(int)));
388 connect(mChangeColorButton, SIGNAL(clicked()), this, SLOT(ChangeColor()));
389 connect(mContourCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleContourROIToggled(bool)));
390 connect(mChangeContourColorButton, SIGNAL(clicked()), this, SLOT(ChangeContourColor()));
391 connect(mContourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeContourWidth(int)));
392 connect(mDepthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeDepth(int)));
397 // mCurrentSlicerManager->Render();
399 //------------------------------------------------------------------------------
402 //------------------------------------------------------------------------------
403 void vvToolROIManager::VisibleROIToggled(bool b) {
404 if (mCurrentROIActor == NULL) return;
405 if (b == mCurrentROIActor->IsVisible()) return; // nothing to do
406 mCurrentROIActor->SetVisible(b);
407 UpdateAllROIStatus();
408 mSlicerManager->Render();
410 //------------------------------------------------------------------------------
413 //------------------------------------------------------------------------------
414 void vvToolROIManager::VisibleContourROIToggled(bool b) {
415 if (mCurrentROIActor == NULL) return;
416 if (mCurrentROIActor->IsContourVisible() == b) return; // nothing to do
417 mCurrentROIActor->SetContourVisible(b);
418 mCurrentROIActor->UpdateColor();
419 mSlicerManager->Render();
421 //------------------------------------------------------------------------------
424 //------------------------------------------------------------------------------
425 void vvToolROIManager::OpacityChanged(int v) {
426 if (mCurrentROIActor == NULL) return;
427 mCurrentROIActor->SetOpacity((double)v/100.0);
428 mCurrentROIActor->UpdateColor();
429 mSlicerManager->Render();
431 //------------------------------------------------------------------------------
434 //------------------------------------------------------------------------------
435 void vvToolROIManager::AllVisibleROIToggled(int b) {
437 if ((mCheckBoxShowAll->checkState() == Qt::Checked) ||
438 (mCheckBoxShowAll->checkState() == Qt::PartiallyChecked)) status = true;
440 for(uint i=0; i<mROIList.size(); i++) {
441 mROIActorsList[i]->SetVisible(status);
443 if (status) mCheckBoxShowAll->setCheckState(Qt::Checked);
444 else mCheckBoxShowAll->setCheckState(Qt::Unchecked);
445 mCheckBoxShow->setChecked(status);
446 mSlicerManager->Render();
448 //------------------------------------------------------------------------------
451 //------------------------------------------------------------------------------
452 void vvToolROIManager::AllVisibleContourROIToggled(bool b) {
454 if ((mContourCheckBoxShowAll->checkState() == Qt::Checked) ||
455 (mContourCheckBoxShowAll->checkState() == Qt::PartiallyChecked)) status = true;
457 for(uint i=0; i<mROIActorsList.size(); i++) {
458 mROIActorsList[i]->SetContourVisible(status);
460 // Update current selection
461 if (status) mContourCheckBoxShowAll->setCheckState(Qt::Checked);
462 else mContourCheckBoxShowAll->setCheckState(Qt::Unchecked);
463 mContourCheckBoxShow->setChecked(status);
464 mSlicerManager->Render();
466 //------------------------------------------------------------------------------
469 //------------------------------------------------------------------------------
470 void vvToolROIManager::ChangeColor() {
472 color.setRgbF(mCurrentROIActor->GetROI()->GetDisplayColor()[0],
473 mCurrentROIActor->GetROI()->GetDisplayColor()[1],
474 mCurrentROIActor->GetROI()->GetDisplayColor()[2]);
475 QColor c = QColorDialog::getColor(color, this, "Choose the ROI color");
476 mCurrentROIActor->GetROI()->SetDisplayColor(c.redF(), c.greenF(), c.blueF());
477 mCurrentROIActor->UpdateColor();
479 QTreeWidgetItem * w = mMapROIToTreeWidget[mCurrentROI];
480 QBrush brush(QColor(mCurrentROI->GetDisplayColor()[0]*255,
481 mCurrentROI->GetDisplayColor()[1]*255,
482 mCurrentROI->GetDisplayColor()[2]*255));
483 brush.setStyle(Qt::SolidPattern);
484 w->setBackground(2, brush);
486 mSlicerManager->Render();
488 //------------------------------------------------------------------------------
491 //------------------------------------------------------------------------------
492 void vvToolROIManager::ChangeContourColor() {
494 color.setRgbF(mCurrentROIActor->GetContourColor()[0],
495 mCurrentROIActor->GetContourColor()[1],
496 mCurrentROIActor->GetContourColor()[2]);
497 QColor c = QColorDialog::getColor(color, this, "Choose the contour color");
498 mCurrentROIActor->SetContourColor(c.redF(), c.greenF(), c.blueF());
499 mCurrentROIActor->UpdateColor();
500 mSlicerManager->Render();
502 //------------------------------------------------------------------------------
505 //------------------------------------------------------------------------------
506 void vvToolROIManager::ChangeContourWidth(int n) {
507 mCurrentROIActor->SetContourWidth(n);
508 mCurrentROIActor->UpdateColor();
509 mSlicerManager->Render();
511 //------------------------------------------------------------------------------
514 //------------------------------------------------------------------------------
515 void vvToolROIManager::ChangeDepth(int n) {
516 mCurrentROIActor->SetDepth(n);
517 mCurrentROIActor->UpdateImage();
518 mSlicerManager->Render();
519 QList<QTreeWidgetItem *> l = mTree->selectedItems();
520 QTreeWidgetItem * w = l[0];
521 w->setText(3, QString("%1").arg(mCurrentROIActor->GetDepth()));
523 //------------------------------------------------------------------------------
526 //------------------------------------------------------------------------------
527 void vvToolROIManager::ReloadCurrentROI() {
529 vvImageReader::Pointer reader = vvImageReader::New();
530 reader->SetInputFilename(mCurrentROI->GetFilename());
531 reader->Update(vvImageReader::IMAGE);
532 if (reader->GetLastError() != "") {
533 QMessageBox::information(mMainWindowBase, tr("Sorry, error. Could not reload"),
534 reader->GetLastError().c_str());
537 mCurrentROI->GetImage()->GetFirstVTKImageData()->ReleaseData();
538 mCurrentROI->SetImage(reader->GetOutput());
541 mCurrentROIActor->UpdateImage();
542 mSlicerManager->Render();
544 //------------------------------------------------------------------------------