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