]> Creatis software - clitk.git/blob - vv/vvSegmentationDialog.cxx
Merge branch 'master' of git://git.creatis.insa-lyon.fr/clitk
[clitk.git] / vv / vvSegmentationDialog.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 #ifndef _vvSegmentationDialog_CXX
19 #define _vvSegmentationDialog_CXX
20 #include <QtGui>
21 #include <Qt>
22
23 #include "vvSegmentationDialog.h"
24 #include "vvProgressDialog.h"
25 #include "vvImageWriter.h"
26 #include "vvLandmarks.h"
27 #include "vvInteractorStyleNavigator.h"
28 #include "vvSlicer.h"
29
30 #include "vtkMarchingCubes.h"
31 #include "vtkMarchingSquares.h"
32 #include "vtkImageClip.h"
33 #include "vtkCamera.h"
34 #include "vtkRenderer.h"
35 #include "vtkProperty.h"
36 #include "vtkLookupTable.h"
37 #include "vtkClipPolyData.h"
38 #include "vtkImageToPolyDataFilter.h"
39 #include "vtkLookupTable.h"
40 #include "vtkDoubleArray.h"
41 #include "vtkPointData.h"
42 #include "vtkCellData.h"
43 #include "vtkImageMapToWindowLevelColors.h"
44 #include "vtkImageContinuousErode3D.h"
45 #include "vtkImageContinuousDilate3D.h"
46 #include "vtkImageLogic.h"
47 #include "vtkInteractorStyleTrackballCamera.h"
48 #include "vtkImageSeedConnectivity.h"
49 #include "vtkConnectivityFilter.h"
50 #include "vtkPolyData.h"
51 #include <vtkPolyDataMapper.h>
52 #include <vtkImageData.h>
53 #include "vtkInformation.h"
54 #include "vtkInformationVector.h"
55 #include "vtkStreamingDemandDrivenPipeline.h"
56 #include <vtkPolyDataWriter.h>
57
58 #include <QMessageBox>
59
60 //====================================================================
61 vvSegmentationDialog::vvSegmentationDialog(QWidget * parent, Qt::WindowFlags f)
62   :QDialog(parent,f), Ui::vvSegmentationDialog()
63 {
64
65   // initialization
66   setupUi(this);
67   mManager = new vvSlicerManager(1);
68
69   mClipper = vtkImageClip::New();
70   mSquares1 = vtkMarchingSquares::New();
71   mSquaresMapper1 = vtkPolyDataMapper::New();
72   mSquaresActor1 = vtkActor::New();
73
74   mSquares2 = vtkMarchingSquares::New();
75   mSquaresMapper2 = vtkPolyDataMapper::New();
76   mSquaresActor2 = vtkActor::New();
77
78   //m3DMapper = vtkPolyDataMapper::New();
79   //m3DActor = vtkActor::New();
80   m3DExtractor = vtkMarchingCubes::New();
81   m3DExtractor->ComputeScalarsOff();
82   m3DMappers.clear();
83   m3DActors.clear();
84
85   mBinaireImages.clear();
86   mKernelValue = 2;
87
88   connect(clipping1Slider,SIGNAL(valueChanged(int)),this,SLOT(clippingvaluechanged(int)));
89   connect(clipping2Slider,SIGNAL(valueChanged(int)),this,SLOT(clippingvaluechanged(int)));
90   connect(binaryButton,SIGNAL(clicked()),this,SLOT(BinariseSurface()));
91   connect(saveButton,SIGNAL(clicked()),this,SLOT(Save()));
92   connect(erodeButton,SIGNAL(clicked()),this,SLOT(Erode()));
93   connect(dilateButton,SIGNAL(clicked()),this,SLOT(Dilate()));
94   connect(dimButton,SIGNAL(clicked()),this,SLOT(ChangeDimRendering()));
95   connect(kernelSpinBox,SIGNAL(valueChanged(int)),this,SLOT(KernelValueChanged(int)));
96
97   binaryButton->setEnabled(0);
98   erodeButton->setEnabled(0);
99   dilateButton->setEnabled(0);
100   infoLabel->setText("Select Up and Down threshold before clicking binarise !");
101 }
102
103 vvSegmentationDialog::~vvSegmentationDialog()
104 {
105   mClipper->Delete();
106
107   mSquaresActor1->Delete();
108   mSquaresMapper1->Delete();
109   mSquares1->Delete();
110
111   mSquaresActor2->Delete();
112   mSquaresMapper2->Delete();
113   mSquares2->Delete();
114
115   //m3DMapper->Delete();
116   //m3DActor->Delete();
117   m3DExtractor->Delete();
118
119   for (unsigned int i = 0; i < mBinaireImages.size(); i++)
120     mBinaireImages[i]->Delete();
121
122   for (unsigned int i = 0; i < m3DActors.size(); i++)
123     m3DActors[i]->Delete();
124
125   for (unsigned int i = 0; i < m3DMappers.size(); i++)
126     m3DMappers[i]->Delete();
127
128   delete mManager;
129 }
130
131 //----------------------------------------------------------------------------
132 // This templated function executes the filter for any type of data.
133 // Handles the one input operations
134 template <class T>
135 void vvImageBinarize(vtkImageData *in1Data, T *in1Ptr,
136                      int outExt[6],int clampMin, int clampMax)
137 {
138   int idxR, idxY, idxZ;
139   int maxY, maxZ;
140   vtkIdType inIncX, inIncY, inIncZ;
141   int rowLength;
142
143   // find the region to loop over
144   rowLength =
145     (outExt[1] - outExt[0]+1)*in1Data->GetNumberOfScalarComponents();
146   // What a pain. Maybe I should just make another filter.
147
148   maxY = outExt[3] - outExt[2];
149   maxZ = outExt[5] - outExt[4];
150
151   // Get increments to march through data
152   in1Data->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ);
153
154   for (idxZ = 0; idxZ <= maxZ; idxZ++) {
155     for (idxY = 0; idxY <= maxY; idxY++) {
156       for (idxR = 0; idxR < rowLength; idxR++) {
157         if (static_cast<double>(*in1Ptr) > clampMin && static_cast<double>(*in1Ptr) <= clampMax)
158           *in1Ptr = static_cast<T>(1);
159         else
160           *in1Ptr = static_cast<T>(0);
161         in1Ptr++;
162       }
163       in1Ptr += inIncY;
164     }
165     in1Ptr += inIncZ;
166   }
167 }
168
169 void vvSegmentationDialog::SetImage(vvImage::Pointer image)
170 {
171
172   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
173   mManager->SetImage(image);
174   mManager->SetSlicerWindow(0,viewWidget->GetRenderWindow());
175   vvInteractorStyleNavigator* style = vvInteractorStyleNavigator::New();
176   mManager->SetInteractorStyleNavigator(0,style);
177   style->Delete();
178
179   double range[2];
180   mManager->GetImage()->GetScalarRange(range);
181   mManager->GetSlicer(0)->SetColorWindow(range[1]-range[0]);
182   mManager->GetSlicer(0)->SetColorLevel((range[1]+range[0])/2);
183
184   clipping1Slider->setMinimum(range[0]);
185   clipping1Slider->setMaximum(range[1]);
186   clipping2Slider->setMinimum(range[0]);
187   clipping2Slider->setMaximum(range[1]);
188   clipping1Slider->setValue(range[0]);
189   clipping2Slider->setValue(range[1]);
190
191   mClipper->SetInput(mManager->GetSlicer(0)->GetInput());
192   mSquares1->SetValue(0,clipping1Slider->value());
193   mSquares2->SetValue(0,clipping2Slider->value());
194   mSquares1->SetInput(mClipper->GetOutput());
195   mSquares2->SetInput(mClipper->GetOutput());
196
197   mSquaresMapper1->SetInput(mSquares1->GetOutput());
198   mSquaresMapper2->SetInput(mSquares2->GetOutput());
199   mSquaresMapper1->ScalarVisibilityOff();
200   mSquaresMapper2->ScalarVisibilityOff();
201
202   mSquaresActor1->SetMapper(mSquaresMapper1);
203   mSquaresActor2->SetMapper(mSquaresMapper2);
204   mSquaresActor1->GetProperty()->SetColor(1.0,0,0);
205   mSquaresActor2->GetProperty()->SetColor(0,0,1.0);
206   mSquaresActor1->SetPickable(0);
207   mSquaresActor2->SetPickable(0);
208
209   mManager->GetSlicer(0)->GetRenderer()->AddActor(mSquaresActor1);
210   mManager->GetSlicer(0)->GetRenderer()->AddActor(mSquaresActor2);
211
212   mSquares1->Update();
213   mSquares2->Update();
214
215   UpdateSlice(0,mManager->GetSlicer(0)->GetSlice());
216
217   connect(mManager,SIGNAL(UpdateTSlice(int,int)),this,SLOT(UpdateSlice(int, int)));
218   connect(mManager,SIGNAL(UpdateSlice(int,int)),this,SLOT(UpdateSlice(int, int)));
219   connect(mManager,SIGNAL(UpdateSliceRange(int,int,int,int,int)),this,SLOT(UpdateSlice(int, int)));
220   connect(mManager,SIGNAL(LandmarkAdded()),this,SLOT(InsertSeed()));
221   QApplication::restoreOverrideCursor();
222 }
223
224 void vvSegmentationDialog::UpdateSlice(int slicer,int slices)
225 {
226   int slice = mManager->GetSlicer(0)->GetSlice();
227   int tslice = mManager->GetSlicer(0)->GetTSlice();
228   mClipper->SetInput(mManager->GetSlicer(0)->GetInput());
229   int* extent = mManager->GetSlicer(0)->GetImageActor()->GetDisplayExtent();
230   mClipper->SetOutputWholeExtent(extent[0],extent[1],extent[2],extent[3],extent[4],extent[5]);
231   int i;
232   for (i = 0; i < 6; i = i+2) {
233     if (extent[i] == extent[i+1]) {
234       break;
235     }
236   }
237
238   switch (i) {
239   case 0:
240     if (mManager->GetSlicer(0)->GetRenderer()->GetActiveCamera()->GetPosition()[0] > slice) {
241       mSquaresActor1->SetPosition(1,0,0);
242       mSquaresActor2->SetPosition(1,0,0);
243     } else {
244       mSquaresActor1->SetPosition(-1,0,0);
245       mSquaresActor2->SetPosition(-1,0,0);
246     }
247     break;
248   case 2:
249     if (mManager->GetSlicer(0)->GetRenderer()->GetActiveCamera()->GetPosition()[1] > slice) {
250       mSquaresActor1->SetPosition(0,1,0);
251       mSquaresActor2->SetPosition(0,1,0);
252     } else {
253       mSquaresActor1->SetPosition(0,-1,0);
254       mSquaresActor2->SetPosition(0,-1,0);
255     }
256     break;
257   case 4:
258     if (mManager->GetSlicer(0)->GetRenderer()->GetActiveCamera()->GetPosition()[2] > slice) {
259       mSquaresActor1->SetPosition(0,0,1);
260       mSquaresActor2->SetPosition(0,0,1);
261     } else {
262       mSquaresActor1->SetPosition(0,0,-1);
263       mSquaresActor2->SetPosition(0,0,-1);
264     }
265     break;
266   }
267   mSquares1->Update();
268   mSquares2->Update();
269
270   if (m3DActors.size()) {
271     for (unsigned int i =0; i < m3DActors.size(); i++) {
272       if (m3DActors[i]->GetVisibility()) {
273         m3DActors[i]->VisibilityOff();
274       }
275     }
276     std::cout << "display " << tslice << " on " << m3DActors.size()  << std::endl;
277     m3DActors[tslice]->VisibilityOn();
278   }
279
280   mManager->Render();
281 }
282
283
284 void vvSegmentationDialog::clippingvaluechanged(int value)
285 {
286   binaryButton->setEnabled(1);
287   int min = (clipping1Slider->value() < clipping2Slider->value() ) ?
288             clipping1Slider->value():clipping2Slider->value();
289   int max = (clipping1Slider->value() > clipping2Slider->value() ) ?
290             clipping1Slider->value():clipping2Slider->value();
291   mSquares1->SetValue(0,min);
292   mSquares2->SetValue(0,max);
293
294   QString textMin = "<b> Min : </b>";
295   textMin += QString::number(min);
296   QString textMax = "\n <b> Max : </b>";
297   textMax += QString::number(max);
298   minLabel->setText(textMin);
299   maxLabel->setText(textMax);
300
301   if (mSquares1->GetInput()) {
302     mSquares1->Update();
303     mSquares2->Update();
304     mManager->Render();
305   }
306 }
307
308
309 void vvSegmentationDialog::BinariseSurface()
310 {
311   infoLabel->setText("Click erode then space on desired organ !");
312
313   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
314   int clampMin = (clipping1Slider->value() < clipping2Slider->value() ) ?
315                  clipping1Slider->value():clipping2Slider->value();
316   int clampMax = (clipping1Slider->value() > clipping2Slider->value() ) ?
317                  clipping1Slider->value():clipping2Slider->value();
318   vtkImageData* outputImage = vtkImageData::New();
319
320   for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++) {
321     vtkImageData* image = mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage];
322     int ext[6];
323     image->GetWholeExtent(ext);
324     void *in1Ptr;
325     in1Ptr = image->GetScalarPointerForExtent(ext);
326
327     switch (image->GetScalarType()) {
328       vtkTemplateMacro(
329         vvImageBinarize(image, static_cast<VTK_TT *>(in1Ptr),
330                         ext,clampMin,clampMax));
331     default:
332       std::cerr << "Error, unknown pixel format : " << image->GetScalarTypeAsString() << std::endl;
333       return;
334     }
335
336     outputImage->Initialize();
337     outputImage->SetExtent(ext);
338     outputImage->SetOrigin(image->GetOrigin());
339     outputImage->SetSpacing(image->GetSpacing());
340     outputImage->SetScalarTypeToUnsignedChar();
341     outputImage->CopyAndCastFrom(image,ext);
342     outputImage->Update();
343
344     image->DeepCopy(outputImage);
345     image->UpdateInformation();
346     image->PropagateUpdateExtent();
347
348     vtkImageData* imageBin = vtkImageData::New();
349     imageBin->DeepCopy(image);
350     imageBin->Update();
351     mBinaireImages.push_back(imageBin);
352   }
353
354   outputImage->Delete();
355   erodeButton->setEnabled(1);
356   QApplication::restoreOverrideCursor();
357   mManager->SetColorWindow(2);
358   mManager->SetColorLevel(0.5);
359   mManager->Render();
360 }
361
362 void vvSegmentationDialog::Erode()
363 {
364   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
365   vtkImageContinuousErode3D* erode = vtkImageContinuousErode3D::New();
366   erode->SetKernelSize(mKernelValue,mKernelValue,mKernelValue);
367   for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++) {
368     vtkImageData* image = mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage];
369     erode->SetInput(image);
370     erode->Update();
371     image->DeepCopy(erode->GetOutput());
372     image->Update();
373   }
374   erode->Delete();
375   dilateButton->setEnabled(1);
376   mManager->Render();
377   QApplication::restoreOverrideCursor();
378 }
379
380 void vvSegmentationDialog::Dilate()
381 {
382   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
383   vtkImageContinuousDilate3D* dilate = vtkImageContinuousDilate3D::New();
384   vtkImageLogic* And = vtkImageLogic::New();
385   And->SetOperationToAnd();
386   dilate->SetKernelSize(mKernelValue,mKernelValue,mKernelValue);
387   for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++) {
388     vtkImageData* image = mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage];
389     dilate->SetInput(image);
390     vtkImageData* mask = mBinaireImages[numImage];
391     And->SetInput1(dilate->GetOutput());
392     And->SetInput2(mask);
393     And->Update();
394     image->DeepCopy(And->GetOutput());
395     image->Update();
396   }
397   And->Delete();
398   dilate->Delete();
399   mManager->Render();
400   QApplication::restoreOverrideCursor();
401 }
402
403 void vvSegmentationDialog::InsertSeed()
404 {
405   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
406   int point4D[4];
407   point4D[0] = mManager->GetLandmarks()->GetCoordinates(
408                  mManager->GetLandmarks()->GetNumberOfPoints()-1)[0];
409   point4D[1] = mManager->GetLandmarks()->GetCoordinates(
410                  mManager->GetLandmarks()->GetNumberOfPoints()-1)[1];
411   point4D[2] = mManager->GetLandmarks()->GetCoordinates(
412                  mManager->GetLandmarks()->GetNumberOfPoints()-1)[2];
413   point4D[3] = mManager->GetLandmarks()->GetCoordinates(
414                  mManager->GetLandmarks()->GetNumberOfPoints()-1)[3];
415
416   point4D[0] = (point4D[0]-mManager->GetSlicer(0)->GetImage()->GetVTKImages()[0]->GetOrigin()[0])/mManager->GetSlicer(0)->GetImage()->GetVTKImages()[0]->GetSpacing()[0];
417   point4D[1] = (point4D[1]-mManager->GetSlicer(0)->GetImage()->GetVTKImages()[0]->GetOrigin()[1])/mManager->GetSlicer(0)->GetImage()->GetVTKImages()[0]->GetSpacing()[1];
418   point4D[2] = (point4D[2]-mManager->GetSlicer(0)->GetImage()->GetVTKImages()[0]->GetOrigin()[2])/mManager->GetSlicer(0)->GetImage()->GetVTKImages()[0]->GetSpacing()[2];
419
420   vtkImageSeedConnectivity* seed = vtkImageSeedConnectivity::New();
421   seed->SetInputConnectValue(1);
422   seed->SetOutputConnectedValue(1);
423   seed->SetOutputUnconnectedValue(0);
424   seed->AddSeed(point4D[0],point4D[1],point4D[2]);
425
426   for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++) {
427     vtkImageData* image = mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage];
428     seed->SetInput(image);
429     seed->Update();
430     image->DeepCopy(seed->GetOutput());
431     image->Update();
432   }
433
434   seed->Delete();
435   QApplication::restoreOverrideCursor();
436 }
437
438 void vvSegmentationDialog::ChangeDimRendering()
439 {
440   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
441
442   if (dimButton->text() == "3D") {
443     if (m3DActors.size() == 0) {
444       m3DExtractor->SetValue(0,0.5);
445       for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++) {
446         vtkActor* actor = vtkActor::New();
447         m3DExtractor->SetInput(mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage]);
448         m3DExtractor->Update();
449
450         vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
451         mapper->SetInput(m3DExtractor->GetOutput());
452         m3DMappers.push_back(mapper);
453
454         actor->SetMapper(mapper);
455         actor->GetProperty()->SetColor(1.0,0.7,0.2);
456         actor->VisibilityOff();
457
458         mManager->GetSlicer(0)->GetRenderer()->AddActor(actor);
459         m3DActors.push_back(actor);
460       }
461     }
462
463     mManager->GetSlicer(0)->GetRenderer()->SetBackground(0.5,0.6,0.9);
464     m3DActors[0]->VisibilityOn();
465
466     vtkInteractorStyleTrackballCamera* style = vtkInteractorStyleTrackballCamera::New();
467     mManager->SetInteractorStyleNavigator(0,style);
468     style->Delete();
469
470     mManager->GetSlicer(0)->GetImageActor()->VisibilityOff();
471     mSquaresActor1->VisibilityOff();
472     mSquaresActor2->VisibilityOff();
473     mManager->Render();
474     dimButton->setText("2D");
475   } else {
476     mManager->GetSlicer(0)->GetRenderer()->SetBackground(0.0,0.0,0.0);
477     vvInteractorStyleNavigator* style = vvInteractorStyleNavigator::New();
478     mManager->SetInteractorStyleNavigator(0,style);
479     style->Delete();
480
481     mManager->GetSlicer(0)->SetSliceOrientation(2);
482     m3DActors[mManager->GetSlicer(0)->GetTSlice()]->VisibilityOff();
483
484     mManager->GetSlicer(0)->GetImageActor()->VisibilityOn();
485     mSquaresActor1->VisibilityOn();
486     mSquaresActor2->VisibilityOn();
487     dimButton->setText("3D");
488   }
489   QApplication::restoreOverrideCursor();
490 }
491
492 void vvSegmentationDialog::KernelValueChanged(int kernel)
493 {
494   mKernelValue = kernel;
495 }
496
497 void vvSegmentationDialog::Save()
498 {
499   if (dimButton->text() == "2D") { //If in *3D* mode, save the mesh
500     QString fileName = QFileDialog::getSaveFileName(this,
501                        tr("Save Mesh As"),
502                        QDir::home().dirName(),
503                        "Mesh Files (*.vtk *.vtp)");
504     if (!fileName.isEmpty()) {
505       vtkSmartPointer<vtkPolyDataWriter> w = vtkSmartPointer<vtkPolyDataWriter>::New();
506       w->SetInput(m3DExtractor->GetOutput());
507       w->SetFileName(fileName.toStdString().c_str());
508       w->Write();
509     }
510   } else {
511     QStringList OutputListeFormat;
512     OutputListeFormat.clear();
513     int dimension = mManager->GetDimension();
514     if (dimension == 1) {
515       OutputListeFormat.push_back(".mhd");
516       OutputListeFormat.push_back(".mha");
517     }
518     if (dimension == 2) {
519       OutputListeFormat.push_back(".bmp");
520       OutputListeFormat.push_back(".png");
521       OutputListeFormat.push_back(".jpeg");
522       OutputListeFormat.push_back(".tif");
523       OutputListeFormat.push_back(".mha");
524       OutputListeFormat.push_back(".mhd");
525       OutputListeFormat.push_back(".hdr");
526       OutputListeFormat.push_back(".vox");
527     } else if (dimension == 3) {
528       OutputListeFormat.push_back(".mha");
529       OutputListeFormat.push_back(".mhd");
530       OutputListeFormat.push_back(".hdr");
531       OutputListeFormat.push_back(".vox");
532     } else if (dimension == 4) {
533       OutputListeFormat.push_back(".mha");
534       OutputListeFormat.push_back(".mhd");
535     }
536     QString Extensions = "AllFiles(*.*)";
537     for (int i = 0; i < OutputListeFormat.count(); i++) {
538       Extensions += ";;Images ( *";
539       Extensions += OutputListeFormat[i];
540       Extensions += ")";
541     }
542     QString fileName = QFileDialog::getSaveFileName(this,
543                        tr("Save As"),
544                        QDir::home().dirName(),
545                        Extensions);
546     if (!fileName.isEmpty()) {
547       std::string fileformat = vtksys::SystemTools::GetFilenameLastExtension(fileName.toStdString());
548       if (OutputListeFormat.contains(
549             fileformat.c_str())) {
550         QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
551         vvProgressDialog progress("Saving "+fileName.toStdString());
552         qApp->processEvents();
553         vvImageWriter::Pointer writer = vvImageWriter::New();
554         writer->SetOutputFileName(fileName.toStdString());
555         writer->SetInput(mManager->GetSlicer(0)->GetImage());
556         writer->Update(dimension,"unsigned_char");
557         QApplication::restoreOverrideCursor();
558         if (writer->GetLastError().size()) {
559           QString error = "Saving did not succeed\n";
560           error += writer->GetLastError().c_str();
561           QMessageBox::information(this,tr("Saving Problem"),error);
562           Save();
563         }
564       } else {
565         QString error = fileformat.c_str();
566         if (error.isEmpty())
567           error += "no file format specified !";
568         else
569           error += " format unknown !!!\n";
570         QMessageBox::information(this,tr("Saving Problem"),error);
571         Save();
572       }
573     }
574   }
575 }
576
577 #endif /* end #define _vvSegmentationDialog_CXX */
578