]> Creatis software - clitk.git/blob - vv/vvToolResample.cxx
Merge branch 'master' of git://git.creatis.insa-lyon.fr/clitk
[clitk.git] / vv / vvToolResample.cxx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to:
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
8
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.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17   ===========================================================================**/
18
19 // vv
20 #include "vvToolResample.h"
21 #include "vvSlicer.h"
22 #include "vvToolCreator.h"
23
24 // qt
25 #include <QFileInfo>
26 #include <QMessageBox>
27 #include <QThread>
28
29 #define COLUMN_IMAGE_NAME 7
30
31 ADD_TOOL(vvToolResample);
32
33
34 #define SetArgOptionString(OPTION, VALUE)          \
35   {                                                \
36     OPTION##_given = VALUE.size();                 \
37     OPTION##_arg = new char[VALUE.size()];         \
38     strcpy(OPTION##_arg, VALUE.c_str());           \
39   }
40
41 //------------------------------------------------------------------------------
42 vvToolResample::vvToolResample(vvMainWindowBase * parent, Qt::WindowFlags f):
43   vvToolWidgetBase(parent,f),
44   vvToolBase<vvToolResample>(parent),
45   Ui::vvToolResample()
46 {
47   Ui_vvToolResample::setupUi(mToolWidget);
48
49   mFilter = clitk::ResampleImageGenericFilter::New();
50   //mFilter = clitk::ImageResampleGenericFilter::New();
51   mLastError ="";
52
53   mInputFileFormat = "";
54   ComponentType = "";
55   mPixelType = "";
56   mCurrentSlicerManager=NULL;
57
58   mInputSize.resize(0);
59   mInputSpacing.resize(0);
60   mInputOrigin.resize(0);
61   mOutputSize.resize(0);
62   mOutputSpacing.resize(0);
63
64   xSizeLineEdit->setText("");
65   ySizeLineEdit->setText("");
66   zSizeLineEdit->setText("");
67   xSpacingLineEdit->setText("");
68   ySpacingLineEdit->setText("");
69   zSpacingLineEdit->setText("");
70   scaleSizeLineEdit->setText("");
71   scaleSpacingLineEdit->setText("");
72
73   sizeRadioButton->setChecked(0);
74   scaleSizeRadioButton->setChecked(0);
75   isoSizeRadioButton->setChecked(0);
76   spacingRadioButton->setChecked(0);
77   scaleSpacingRadioButton->setChecked(0);
78   isoSpacingRadioButton->setChecked(0);
79
80   gaussianFilterCheckBox->setCheckState(Qt::Unchecked);
81
82   xGaussianLineEdit->hide();
83   yGaussianLineEdit->hide();
84   zGaussianLineEdit->hide();
85   gaussianFilterLabel->hide();
86
87   bSplineLabel->hide();
88   bSplineOrderSpinBox->hide();
89   bLUTFactorLabel->hide();
90   bLUTSpinBox->hide();
91   mDimension = -1;
92
93   QPalette qPalette;
94   qPalette.setColor(QPalette::Foreground, QColor(Qt::blue));
95   mInputFormatLabel->setPalette(qPalette);
96   mInputDimLabel->setPalette(qPalette);
97   mInputPixelTypeLabel->setPalette(qPalette);
98   mInputSizeLabel->setPalette(qPalette);
99   mInputSpacingLabel->setPalette(qPalette);
100
101   // Set how many inputs are needed for this tool
102   AddInputSelector("Select an image to resample", mFilter);
103
104   // Connect signals & slots
105
106   connect(sizeRadioButton, SIGNAL(clicked()), this, SLOT(UpdateControlSizeAndSpacing()));
107   connect(scaleSizeRadioButton, SIGNAL(clicked()), this, SLOT(UpdateControlSizeAndSpacing()));
108   connect(isoSizeRadioButton, SIGNAL(clicked()), this, SLOT(UpdateControlSizeAndSpacing()));
109   connect(spacingRadioButton, SIGNAL(clicked()), this, SLOT(UpdateControlSizeAndSpacing()));
110   connect(scaleSpacingRadioButton, SIGNAL(clicked()), this, SLOT(UpdateControlSizeAndSpacing()));
111   connect(isoSpacingRadioButton, SIGNAL(clicked()), this, SLOT(UpdateControlSizeAndSpacing()));
112
113   connect(xSizeLineEdit, SIGNAL(textEdited(QString)),this,SLOT(ComputeNewSpacingFromSize()));
114   connect(ySizeLineEdit, SIGNAL(textEdited(QString)),this,SLOT(ComputeNewSpacingFromSize()));
115   connect(zSizeLineEdit, SIGNAL(textEdited(QString)),this,SLOT(ComputeNewSpacingFromSize()));
116   connect(xSpacingLineEdit, SIGNAL(textEdited(QString)),this,SLOT(ComputeNewSizeFromSpacing()));
117   connect(ySpacingLineEdit, SIGNAL(textEdited(QString)),this,SLOT(ComputeNewSizeFromSpacing()));
118   connect(zSpacingLineEdit, SIGNAL(textEdited(QString)),this,SLOT(ComputeNewSizeFromSpacing()));
119   connect(scaleSizeLineEdit,SIGNAL(textEdited(QString)),this,SLOT(ComputeNewSizeFromScale()));
120   connect(scaleSpacingLineEdit,SIGNAL(textEdited(QString)),this,SLOT(ComputeNewSpacingFromScale()));
121   connect(isoSizeLineEdit,SIGNAL(textEdited(QString)),this,SLOT(ComputeNewSizeFromIso()));
122   connect(isoSpacingLineEdit,SIGNAL(textEdited(QString)),this,SLOT(ComputeNewSpacingFromIso()));
123
124   connect(gaussianFilterCheckBox,SIGNAL(stateChanged(int)),this,SLOT(UpdateGaussianFilter()));
125   connect(interpolationComboBox,SIGNAL(currentIndexChanged(QString)),this,SLOT(UpdateInterpolation()));
126 }
127 //------------------------------------------------------------------------------
128
129
130 //------------------------------------------------------------------------------
131 void vvToolResample::Initialize()
132 {
133   SetToolName("Resample Image");
134   SetToolMenuName("Resample");
135   SetToolIconFilename(":/common/icons/resample.png");
136   SetToolTip("Resample image with various interpolation methods.");
137 }
138 //------------------------------------------------------------------------------
139
140
141 //------------------------------------------------------------------------------
142 void vvToolResample::InputIsSelected(vvSlicerManager* m)
143 {
144
145   mCurrentSlicerManager = m;
146   mCurrentImage = mCurrentSlicerManager->GetSlicer(0)->GetImage();
147   if (mCurrentImage.IsNull()) return;
148   mInputFileName = mCurrentSlicerManager->GetFileName().c_str();
149
150   // Set current information
151   mPixelType = mCurrentImage->GetScalarTypeAsITKString().c_str();
152   //ds      ComponentType = mCurrentImageGetNumberOfScalarComponents();
153   mDimension = mCurrentImage->GetNumberOfDimensions();
154
155   // Copy size, spacing ...
156   mInputOrigin.resize(mDimension);
157   mInputSpacing.resize(mDimension);
158   mInputSize.resize(mDimension);
159   for (int i = 0; i < mDimension; i++) {
160     mInputOrigin[i] = mCurrentImage->GetOrigin()[i];
161     mInputSpacing[i] = mCurrentImage->GetSpacing()[i];
162     mInputSize[i] = mCurrentImage->GetSize()[i];
163   }
164
165   // Get file format
166   mInputFileFormat = itksys::SystemTools::GetFilenameLastExtension(mInputFileName.toStdString()).c_str();
167
168   // Display infos
169   mInputFormatLabel->setText(mInputFileFormat);
170   mInputSizeLabel->setText(GetVectorIntAsString(mInputSize));
171   mInputDimLabel->setText(QString::number(mDimension)+"D");
172   mInputSpacingLabel->setText(GetVectorDoubleAsString(mInputSpacing));
173   mInputPixelTypeLabel->setText(mPixelType);
174   mInputMemoryLabel->setText(GetSizeInBytes(mInputSize));
175
176   // Set current size
177   scaleSizeRadioButton->setChecked(true);
178   UpdateControlSizeAndSpacing();
179   scaleSizeLineEdit->setText("100");
180   ComputeNewSizeFromScale();
181
182   // Update output
183   UpdateOutputInfo();
184 }
185 //------------------------------------------------------------------------------
186
187
188 //------------------------------------------------------------------------------
189 void vvToolResample::UpdateOutputInfo()
190 {
191   mOutputSizeLabel->setText(GetVectorIntAsString(mOutputSize));
192   mOutputSpacingLabel->setText(GetVectorDoubleAsString(mOutputSpacing));
193   mOutputMemoryLabel->setText(GetSizeInBytes(mOutputSize));
194 }
195 //------------------------------------------------------------------------------
196
197
198 //------------------------------------------------------------------------------
199 QString vvToolResample::GetSizeInBytes(std::vector<int> & size)
200 {
201   int t = 1;
202   for (unsigned int i=0; i<size.size(); i++) t *= size[i];
203   t *= mCurrentImage->GetScalarSize()*mCurrentImage->GetNumberOfScalarComponents();
204   QString result = QString::number(t);
205   result += " bytes (";
206   if (t > 1000000000) {
207     t /= 1000000000;
208     result += QString::number(t);
209     result += " GB)";
210   } else if (t > 1000000) {
211     t /= 1000000;
212     result += QString::number(t);
213     result += " MB)";
214   } else if (t > 1000) {
215     t /= 1000;
216     result += QString::number(t);
217     result += " KB)";
218   } else result += ")";
219   return result;
220 }
221 //------------------------------------------------------------------------------
222
223
224 //------------------------------------------------------------------------------
225 QString vvToolResample::GetVectorDoubleAsString(std::vector<double> vectorDouble)
226 {
227   QString result;
228   for (unsigned int i= 0; i<vectorDouble.size(); i++) {
229     if (i != 0)
230       result += " x ";
231     result += QString::number(vectorDouble[i]);
232   }
233   return result;
234 }
235 //------------------------------------------------------------------------------
236
237
238 //------------------------------------------------------------------------------
239 QString vvToolResample::GetVectorIntAsString(std::vector<int> vectorInt)
240 {
241   QString result;
242   for (unsigned int i= 0; i<vectorInt.size(); i++) {
243     if (i != 0)
244       result += " x ";
245     result += QString::number(vectorInt[i]);
246   }
247   return result;
248 }
249 //------------------------------------------------------------------------------
250
251
252 //------------------------------------------------------------------------------
253 void vvToolResample::FillSizeEdit(std::vector<int> size)
254 {
255   xSizeLineEdit->setText(QString::number(size[0]));
256   ySizeLineEdit->setText(QString::number(size[1]));
257   if (size.size() > 2)
258     zSizeLineEdit->setText(QString::number(size[2]));
259 }
260 //------------------------------------------------------------------------------
261
262
263 //------------------------------------------------------------------------------
264 void vvToolResample::FillSpacingEdit(std::vector<double> spacing)
265 {
266   xSpacingLineEdit->setText(QString::number(spacing[0]));
267   ySpacingLineEdit->setText(QString::number(spacing[1]));
268   if (spacing.size() > 2)
269     zSpacingLineEdit->setText(QString::number(spacing[2]));
270 }
271 //------------------------------------------------------------------------------
272
273
274 //------------------------------------------------------------------------------
275 void vvToolResample::UpdateOutputSizeAndSpacing()
276 {
277   mOutputSize.resize(mDimension);
278   mOutputSize = mInputSize;
279   mOutputSpacing.resize(mDimension);
280   mOutputSpacing = mInputSpacing;
281   mOutputSize[0] = (int)xSizeLineEdit->text().toDouble();
282   mOutputSize[1] = (int)ySizeLineEdit->text().toDouble();
283   if (mDimension > 2)
284     mOutputSize[2] = (int)zSizeLineEdit->text().toDouble();
285
286   mOutputSpacing[0] = xSpacingLineEdit->text().toDouble();
287   mOutputSpacing[1] = ySpacingLineEdit->text().toDouble();
288   if (mDimension > 2)
289     mOutputSpacing[2] = zSpacingLineEdit->text().toDouble();
290
291   UpdateOutputInfo();
292 }
293 //------------------------------------------------------------------------------
294
295
296 //------------------------------------------------------------------------------
297 void vvToolResample::UpdateControlSizeAndSpacing()
298 {
299   scaleSizeLineEdit->setText("");
300   scaleSpacingLineEdit->setText("");
301   isoSizeLineEdit->setText("");
302   isoSpacingLineEdit->setText("");
303
304   xSizeLineEdit->setReadOnly(1);
305   ySizeLineEdit->setReadOnly(1);
306   zSizeLineEdit->setReadOnly(1);
307   scaleSizeLineEdit->setReadOnly(1);
308   isoSizeLineEdit->setReadOnly(1);
309
310   xSpacingLineEdit->setReadOnly(1);
311   ySpacingLineEdit->setReadOnly(1);
312   zSpacingLineEdit->setReadOnly(1);
313   scaleSpacingLineEdit->setReadOnly(1);
314   isoSpacingLineEdit->setReadOnly(1);
315
316   if (sizeRadioButton->isChecked()) {
317     xSizeLineEdit->setReadOnly(0);
318     ySizeLineEdit->setReadOnly(0);
319     if (mDimension > 2)
320       zSizeLineEdit->setReadOnly(0);
321   } else {
322     if (spacingRadioButton->isChecked()) {
323       xSpacingLineEdit->setReadOnly(0);
324       ySpacingLineEdit->setReadOnly(0);
325       if (mDimension > 2)
326         zSpacingLineEdit->setReadOnly(0);
327     } else if (scaleSizeRadioButton->isChecked())
328       scaleSizeLineEdit->setReadOnly(0);
329     else if (scaleSpacingRadioButton->isChecked())
330       scaleSpacingLineEdit->setReadOnly(0);
331     else if (isoSizeRadioButton->isChecked())
332       isoSizeLineEdit->setReadOnly(0);
333     else if (isoSpacingRadioButton->isChecked())
334       isoSpacingLineEdit->setReadOnly(0);
335   }
336 }
337 //------------------------------------------------------------------------------
338
339
340 //------------------------------------------------------------------------------
341 void vvToolResample::ComputeNewSpacingFromSize()
342 {
343   double newSpacing = mInputSpacing[0]*mInputSize[0];
344   xSpacingLineEdit->setText(QString::number(newSpacing/xSizeLineEdit->text().toDouble()));
345   newSpacing = mInputSpacing[1]*mInputSize[1];
346   ySpacingLineEdit->setText(QString::number(newSpacing/ySizeLineEdit->text().toDouble()));
347   if (mDimension > 2) {
348     newSpacing = mInputSpacing[2]*mInputSize[2];
349     zSpacingLineEdit->setText(QString::number(newSpacing/zSizeLineEdit->text().toDouble()));
350   }
351   UpdateOutputSizeAndSpacing();
352 }
353 //------------------------------------------------------------------------------
354
355
356 //------------------------------------------------------------------------------
357 void vvToolResample::ComputeNewSizeFromSpacing()
358 {
359   double newSize = mInputSpacing[0]*mInputSize[0];
360   xSizeLineEdit->setText(QString::number(newSize/xSpacingLineEdit->text().toDouble()));
361   newSize = mInputSpacing[1]*mInputSize[1];
362   ySizeLineEdit->setText(QString::number(newSize/ySpacingLineEdit->text().toDouble()));
363   if (mDimension > 2) {
364     newSize = mInputSpacing[2]*mInputSize[2];
365     zSizeLineEdit->setText(QString::number(newSize/zSpacingLineEdit->text().toDouble()));
366   }
367   UpdateOutputSizeAndSpacing();
368 }
369 //------------------------------------------------------------------------------
370
371
372 //------------------------------------------------------------------------------
373 void vvToolResample::ComputeNewSpacingFromScale()
374 {
375   xSpacingLineEdit->setText(QString::number(mInputSpacing[0]*scaleSpacingLineEdit->text().toDouble()/100));
376   ySpacingLineEdit->setText(QString::number(mInputSpacing[1]*scaleSpacingLineEdit->text().toDouble()/100));
377   if (mDimension > 2)
378     zSpacingLineEdit->setText(QString::number(mInputSpacing[2]*scaleSpacingLineEdit->text().toDouble()/100));
379   ComputeNewSizeFromSpacing();
380 }
381 //------------------------------------------------------------------------------
382
383
384 //------------------------------------------------------------------------------
385 void vvToolResample::ComputeNewSizeFromScale()
386 {
387   xSizeLineEdit->setText(QString::number(mInputSize[0]*scaleSizeLineEdit->text().toDouble()/100));
388   ySizeLineEdit->setText(QString::number(mInputSize[1]*scaleSizeLineEdit->text().toDouble()/100));
389   if (mDimension > 2)
390     zSizeLineEdit->setText(QString::number(mInputSize[2]*scaleSizeLineEdit->text().toDouble()/100));
391   ComputeNewSpacingFromSize();
392 }
393 //------------------------------------------------------------------------------
394
395
396 //------------------------------------------------------------------------------
397 void vvToolResample::ComputeNewSpacingFromIso()
398 {
399   xSpacingLineEdit->setText(QString::number(isoSpacingLineEdit->text().toDouble()));
400   ySpacingLineEdit->setText(QString::number(isoSpacingLineEdit->text().toDouble()));
401   if (mDimension > 2)
402     zSpacingLineEdit->setText(QString::number(isoSpacingLineEdit->text().toDouble()));
403   ComputeNewSizeFromSpacing();
404 }
405 //------------------------------------------------------------------------------
406
407
408 //------------------------------------------------------------------------------
409 void vvToolResample::ComputeNewSizeFromIso()
410 {
411   xSizeLineEdit->setText(QString::number(isoSizeLineEdit->text().toDouble()));
412   ySizeLineEdit->setText(QString::number(isoSizeLineEdit->text().toDouble()));
413   if (mDimension > 2)
414     zSizeLineEdit->setText(QString::number(isoSizeLineEdit->text().toDouble()));
415   ComputeNewSpacingFromSize();
416 }
417 //------------------------------------------------------------------------------
418
419
420 //------------------------------------------------------------------------------
421 void vvToolResample::UpdateInterpolation()
422 {
423   if (interpolationComboBox->currentText() == "BSpline") {
424     bSplineLabel->show();
425     bSplineOrderSpinBox->show();
426     bLUTFactorLabel->hide();
427     bLUTSpinBox->hide();
428   } else if (interpolationComboBox->currentText() == "Blut (faster BSpline)")   {
429     bSplineLabel->show();
430     bSplineOrderSpinBox->show();
431     bLUTFactorLabel->show();
432     bLUTSpinBox->show();
433   } else {
434     bSplineLabel->hide();
435     bSplineOrderSpinBox->hide();
436     bLUTFactorLabel->hide();
437     bLUTSpinBox->hide();
438   }
439 }
440 //------------------------------------------------------------------------------
441
442
443 //------------------------------------------------------------------------------
444 void vvToolResample::UpdateGaussianFilter()
445 {
446   if (gaussianFilterCheckBox->isChecked()) {
447     gaussianFilterLabel->show();
448     xGaussianLineEdit->show();
449     yGaussianLineEdit->show();
450     if (mDimension > 2)
451       zGaussianLineEdit->show();
452   } else {
453     gaussianFilterLabel->hide();
454     xGaussianLineEdit->hide();
455     yGaussianLineEdit->hide();
456     zGaussianLineEdit->hide();
457   }
458 }
459 //------------------------------------------------------------------------------
460
461
462 //------------------------------------------------------------------------------
463 void vvToolResample::apply()
464 {
465
466   // Get resampler options
467   std::vector<double> sigma;
468   sigma.push_back(xGaussianLineEdit->text().toDouble());
469   sigma.push_back(yGaussianLineEdit->text().toDouble());
470   if (mDimension > 2) sigma.push_back(zGaussianLineEdit->text().toDouble());
471   if (mDimension == 4) sigma.push_back(0.01); //FIXME Don't filter along the temporal direction
472
473    // Build ArgsInfo
474   clitk::ResampleImageGenericFilter::ArgsInfoType mArgsInfo;
475
476   // Initialisation to default
477   cmdline_parser_clitkResampleImage_init(&mArgsInfo);
478   mArgsInfo.input_given = 0;
479   mArgsInfo.output_given = 0;
480   
481   // Size and spacing options
482   mArgsInfo.size_given = mDimension;
483   mArgsInfo.spacing_given = mDimension;
484   mArgsInfo.size_arg = new int[mDimension];
485   mArgsInfo.spacing_arg = new float[mDimension];
486   for(int i=0; i<mDimension; i++) {
487     mArgsInfo.size_arg[i] = mOutputSize[i];
488     mArgsInfo.spacing_arg[i] = mOutputSpacing[i];
489   }
490   
491   if (sizeRadioButton->isChecked() || 
492       scaleSizeRadioButton->isChecked() || 
493       isoSizeRadioButton->isChecked()) {
494     mArgsInfo.spacing_given=0;
495   }
496   if (spacingRadioButton->isChecked() || 
497       scaleSpacingRadioButton->isChecked() || 
498       isoSpacingRadioButton->isChecked()) {
499     mArgsInfo.size_given=0;
500   }
501  
502   // Interpolation options
503   std::string interp = interpolationComboBox->currentText().toLower().toStdString();
504   if (interp == "nn") SetArgOptionString(mArgsInfo.interp, std::string("nn"));
505   if (interp == "linear") SetArgOptionString(mArgsInfo.interp, std::string("linear"));
506   if (interp == "bspline") SetArgOptionString(mArgsInfo.interp, std::string("bspline"));
507   if (interp == "blut (faster bspline)") SetArgOptionString(mArgsInfo.interp, std::string("blut"));
508   if (interp == "windowed sinc") SetArgOptionString(mArgsInfo.interp, std::string("windowed sinc"));
509
510   if (interp == "bspline") {
511     mArgsInfo.order_arg = bSplineOrderSpinBox->value();
512   }
513   else {
514     if (interp == "blut (faster bspline)")  {
515       mArgsInfo.order_arg = bSplineOrderSpinBox->value();
516       mArgsInfo.sampling_arg = bLUTSpinBox->value();
517     }
518   }
519   
520   // Gauss
521   if (gaussianFilterCheckBox->isChecked()) {
522     mArgsInfo.gauss_given = mDimension;
523     mArgsInfo.gauss_arg = new float[mDimension];
524     for(int i=0; i<mDimension; i++) {
525       mArgsInfo.gauss_arg[i] = sigma[i];
526     }
527   }
528   mArgsInfo.default_arg = defaultPixelValueLineEdit->text().toDouble();
529
530   // Thread
531   mArgsInfo.thread_arg = QThread::idealThreadCount();
532   mArgsInfo.thread_given = 1;
533
534   // Set options to filter
535   mFilter->SetArgsInfo(mArgsInfo);
536   mFilter->SetInputVVImage(mCurrentImage);
537
538   // Go !
539   mFilter->Update();
540   mOutput = mFilter->GetOutputVVImage();
541   AddImage(mOutput,GetOutputFileName());
542   close();
543 }
544 //------------------------------------------------------------------------------
545
546
547 //------------------------------------------------------------------------------
548 std::string vvToolResample::GetOutputFileName()
549 {
550   QFileInfo info(QString(mCurrentSlicerManager->GetFileName().c_str()));
551   return (info.path().toStdString() + "/resampled_" + info.fileName().toStdString());
552 }
553 //------------------------------------------------------------------------------
554