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