1 /*# ---------------------------------------------------------------------
3 # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
5 # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
6 # Previous Authors : Laurent Guigues, Jean-Pierre Roux
7 # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
9 # This software is governed by the CeCILL-B license under French law and
10 # abiding by the rules of distribution of free software. You can use,
11 # modify and/ or redistribute the software under the terms of the CeCILL-B
12 # license as circulated by CEA, CNRS and INRIA at the following URL
13 # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
14 # or in the file LICENSE.txt.
16 # As a counterpart to the access to the source code and rights to copy,
17 # modify and redistribute granted by the license, users are provided only
18 # with a limited warranty and the software's author, the holder of the
19 # economic rights, and the successive licensors have only limited
22 # The fact that you are presently reading this means that you have had
23 # knowledge of the CeCILL-B license and that you accept its terms.
24 # ------------------------------------------------------------------------ */
26 #include "FillFilter.h"
27 #include "creaVtk_MACROS.h"
33 FillFilter::FillFilter()
36 _GeneralAuxImageFill = NULL;
37 //EED 2020-04-28 BORRAME Change to local variables to use with openmp
38 // _auxImageFill = NULL;
45 //---------------------------------------------------------------------------
46 FillFilter::~FillFilter()
48 /*//EED 2020-04-28 BORRAME Change to local variables to use with openmp
49 if (_auxImageFill != NULL)
51 _auxImageFill->Delete();
56 //---------------------------------------------------------------------------
57 void FillFilter::SetImages(vtkImageData *image,vtkImageData *image2) // virtual
59 baseFilterManualPaint::SetImages(image,image2);
61 /* //EED 2020-04-28 BORRAME Change to local variables to use with openmp
62 if ((_maxX!=_maxXback) || (_maxY!=_maxYback) || (_maxZ!=_maxZback))
64 if (_auxImageFill != NULL)
66 _auxImageFill->Delete();
68 _auxImageFill = vtkImageData::New();
69 _auxImageFill->SetDimensions(_maxX + 1, _maxY + 1, _maxZ + 1);
70 _auxImageFill->SetOrigin(0, 0, 0);
71 _auxImageFill->SetExtent(0, _maxX, 0, _maxY, 0, _maxZ);
72 //EED 2017-01-01 Migration VTK7
73 #if VTK_MAJOR_VERSION <= 5
74 _auxImageFill->SetWholeExtent(0, _maxX, 0, _maxY, 0, _maxZ);
75 _auxImageFill->SetScalarTypeToUnsignedChar();
76 _auxImageFill->AllocateScalars();
78 _auxImageFill->AllocateScalars(VTK_UNSIGNED_CHAR,1);
81 unsigned char * ptrAuxImageFill = (unsigned char *)_auxImageFill->GetScalarPointer();
82 memset(ptrAuxImageFill, 0, (_maxX+1) * (_maxY+1) * (_maxZ+1) );
88 if (_GeneralAuxImageFill != NULL)
90 _GeneralAuxImageFill->Delete();
92 _GeneralAuxImageFill = vtkImageData::New();
93 _GeneralAuxImageFill->SetDimensions(_dimX,_dimY,_dimZ );
94 _GeneralAuxImageFill->SetOrigin(0, 0, 0);
95 _GeneralAuxImageFill->SetExtent(0, _dimX-1, 0, _dimY-1, 0, _dimZ-1);
96 _GeneralAuxImageFill->AllocateScalars(VTK_UNSIGNED_CHAR,1);
97 unsigned char *ptrAuxImageFill = (unsigned char*)_GeneralAuxImageFill->GetScalarPointer();
98 memset(ptrAuxImageFill, 0, _dimX*_dimY*_dimZ*sizeof(unsigned char) );
101 //---------------------------------------------------------------------------
102 void FillFilter::Run(int px, int py, int pz) // virtual
105 if ((_px >= _minX) && (_px < _dimX) && (_py >= _minY) && (_py < _dimY)
106 && (_pz >= _minZ) && (_pz < _dimZ))
108 this->_IMManager->BaseInitialPoint(_px, _py ,_pz);
109 // FillToolLoop(_px, _py, _pz);
110 FillToolLoop(px, py, pz);
114 } //if _minX _maxX _minY _maxY _minZ _maxZ
118 //---------------------------------------------------------------------------
119 vtkImageData* FillFilter::CreateAuxImageFill( long int &OneColumnAux, long int &OneLineAux , long int &OnePlaneAux,
120 int px, int py, int pz,
121 int &pxAux, int &pyAux, int &pzAux,
122 int &minXAux, int &minYAux, int &minZAux )
126 minXAux = px-_distancefill; if (minXAux>=0) { pxAux=px-minXAux; } else { pxAux=px; minXAux=0; }
127 minYAux = py-_distancefill; if (minYAux>=0) { pyAux=py-minYAux; } else { pyAux=py; minYAux=0; }
128 minZAux = pz-_distancefill; if (minZAux>=0) { pzAux=pz-minZAux; } else { pzAux=pz; minZAux=0; }
130 int maxXAux = px+_distancefill; if (maxXAux>_dimX) { maxXAux=_dimX; }
131 int maxYAux = py+_distancefill; if (maxYAux>_dimY) { maxYAux=_dimY; }
132 int maxZAux = pz+_distancefill; if (maxZAux>_dimZ) { maxZAux=_dimZ; }
135 int auxDimX = maxXAux-minXAux+1;
136 int auxDimY = maxYAux-minYAux+1;
137 int auxDimZ = maxZAux-minZAux+1;
142 if (_direction==0) // YZ
146 if (_direction==1) // XZ
150 if (_direction==2) // XY
157 OneLineAux = auxDimX;
158 OnePlaneAux = auxDimX*auxDimY;
160 vtkImageData *auxImageFill;
161 auxImageFill = vtkImageData::New();
162 auxImageFill->SetDimensions(auxDimX, auxDimY, auxDimZ);
163 auxImageFill->SetOrigin(0, 0, 0);
164 auxImageFill->SetExtent(0, auxDimX-1, 0, auxDimY-1, 0, auxDimZ-1);
165 auxImageFill->AllocateScalars(VTK_UNSIGNED_CHAR,1);
166 unsigned char * ptrAuxImageFill = (unsigned char *)auxImageFill->GetScalarPointer();
167 memset( ptrAuxImageFill, 0, auxDimX*auxDimY*auxDimZ );
171 void FillFilter::Copy_AuxImageFill_To_GeneralAuxFill(int minXAux, int minYAux, int minZAux, vtkImageData *auxImageFill)
173 // copy information from the litle image auxImageFill to the big image _GeneralAuxImageFill
174 DEF_POINTER_IMAGE_VTK_CREA(vAuxImageFill,ssAuxImageFill,pAuxImageFill,stAuxImageFill,auxImageFill)
175 DEF_POINTER_IMAGE_VTK_CREA(v_GeneralAuxImageFill,ss_GeneralAuxImageFill,p_GeneralAuxImageFill,st_GeneralAuxImageFill,_GeneralAuxImageFill)
177 auxImageFill->GetExtent(ext);
178 int auxDimX = ext[1]-ext[0]+1;
179 int auxDimY = ext[3]-ext[2]+1;
180 int auxDimZ = ext[5]-ext[4]+1;
183 long int indexGeneralAux;
184 for (k=0;k<auxDimZ;k++)
186 for (j=0;j<auxDimY;j++)
188 indexGeneralAux=minXAux + (minYAux+j)*_OneLine + (minZAux+k)*_OnePlane;
189 // indexAux = j*OneLineAux + k*OnePlaneAux;
190 for (i=0;i<auxDimX;i++)
192 GETVALUE2_VTK_CREA(vAuxImageFill,pAuxImageFill,stAuxImageFill,indexAux)
194 if (vAuxImageFill==1)
196 SETVALUE2_VTK_CREA(vAuxImageFill,p_GeneralAuxImageFill,st_GeneralAuxImageFill,indexGeneralAux)
197 } // if vAuxImageFill
198 indexGeneralAux = indexGeneralAux+_OneColumn;
204 void FillFilter::Copy_GeneralAuxFill_to_Results()
206 DEF_POINTER_IMAGE_VTK_CREA(v_GeneralAuxImageFill,ss_GeneralAuxImageFill,p_GeneralAuxImageFill,st_GeneralAuxImageFill,_GeneralAuxImageFill)
207 long int i,size = _dimX*_dimY*_dimZ;
210 DEF_POINTER_IMAGE_VTK_CREA(v_image,ss_image,p_image,st_image,_image)
211 // DEF_POINTER_IMAGE_VTK_CREA_set(v_image,ss_image,p_image,st_image,_image)
212 #pragma omp parallel for
216 GETVALUE2_VTK_CREA(value,p_GeneralAuxImageFill,st_GeneralAuxImageFill,i)
219 SETVALUE2_VTK_CREA(_graylevel,p_image,st_image,i)
220 } // if v_GeneralAuxImageFill
223 DEF_POINTER_IMAGE_VTK_CREA(v_image2,ss_image2,p_image2,st_image2,_image2)
224 // DEF_POINTER_IMAGE_VTK_CREA_set(v_image2,ss_image2,p_image2,st_image2,_image2)
225 #pragma omp parallel for
229 GETVALUE2_VTK_CREA(value,p_GeneralAuxImageFill,st_GeneralAuxImageFill,i)
232 SETVALUE2_VTK_CREA(_graylevel,p_image2,st_image2,i)
233 } // if v_GeneralAuxImageFill
242 //---------------------------------------------------------------------------
243 void FillFilter::FillToolLoop(int px, int py, int pz)
246 double graylevelbasefill;
249 bool auxGrayLevelValidationFill;
253 distbasefill = _distancefill * _distancefill;
254 double difX,difY,difZ,_tmpDistfill;
255 std::vector<int> lstX;
256 std::vector<int> lstY;
257 std::vector<int> lstZ;
261 std::vector<long long int> lstivi;
262 lstivi.push_back( px + py*_OneLine+ pz*_OnePlane );
264 long int OneColumnAux, OneLineAux, OnePlaneAux; // how to jump in the little image auxImageFill
265 int pxAux, pyAux, pzAux; // position inside little image auxImageFill
266 int minXAux, minYAux, minZAux; // Where start the little image auxImageFill in the big image
267 vtkImageData* auxImageFill = CreateAuxImageFill( OneColumnAux,OneLineAux,OnePlaneAux,
270 minXAux,minYAux,minZAux );
271 std::vector<long long int> lstiviAux;
272 lstiviAux.push_back( pxAux + pyAux*OneLineAux + pzAux*OnePlaneAux );
274 DEF_POINTER_IMAGE_VTK_CREA(v_image,ss_image,p_image,st_image,_image)
275 // DEF_POINTER_IMAGE_VTK_CREA_set(v_image,ss_image,p_image,st_image,_image)
285 // DEF_POINTER_IMAGE_VTK_CREA(v_image2,ss_image2,p_image2,st_image2,_image2)
286 DEF_POINTER_IMAGE_VTK_CREA_set(v_image2,ss_image2,p_image2,st_image2,_image2)
289 GETVALUE2_VTK_CREA(graylevelbasefill,p_image,st_image,lstivi[0])
291 //EED 2020-04-28 BORRAME Change to local variables to use with openmp
292 // DEF_POINTER_IMAGE_VTK_CREA(v_auxImageFill,ss_auxImageFill,p_auxImageFill,st_auxImageFill,_auxImageFill)
293 DEF_POINTER_IMAGE_VTK_CREA(vAuxImageFill,ssAuxImageFill,pAuxImageFill,stAuxImageFill,auxImageFill)
295 while ( lstX.size()!=0 )
297 // if point inside image
298 if ((lstX[0] >= _minX) && (lstX[0] < _dimX) && (lstY[0] >= _minY) && (lstY[0] < _dimY) && (lstZ[0] >= _minZ) && (lstZ[0] < _dimZ))
303 _tmpDistfill = difX*difX + difY*difY + difZ*difZ;
304 // if distance of center point
305 if (_tmpDistfill<=distbasefill)
307 // if point not visited
308 GETVALUE2_VTK_CREA(vAuxImageFill,pAuxImageFill,stAuxImageFill,lstiviAux[0] );
309 if (vAuxImageFill==0)
311 // If Gray Level valid
314 // tmpiglfill = _image->GetScalarComponentAsDouble(px, py, pz, 0);
315 GETVALUE2_VTK_CREA(tmpiglfill,p_image,st_image,lstivi[0])
320 // tmpiglfill2 = _image2->GetScalarComponentAsDouble(px, py, pz, 0);
321 GETVALUE2_VTK_CREA(tmpiglfill2,p_image2,st_image2,lstivi[0])
323 tmpiglfill2 = tmpiglfill;
326 float grayLBFMTOL = graylevelbasefill - _tolerancefill;
327 float grayLBFPTOL = graylevelbasefill + _tolerancefill;
328 bool isInRange = false;
330 if (_RangeMin <= grayLBFMTOL && _RangeMax >= grayLBFPTOL) {
333 else if (_RangeMin > grayLBFMTOL && _RangeMax >= grayLBFPTOL) {
334 grayLBFMTOL = _RangeMin;
337 else if (_RangeMin <= grayLBFMTOL && _RangeMax < grayLBFPTOL) {
338 grayLBFPTOL = _RangeMax;
341 else if ((_RangeMin <= graylevelbasefill) && (graylevelbasefill <= _RangeMax)) {
342 grayLBFMTOL = _RangeMin;
343 grayLBFPTOL = _RangeMax;
349 auxGrayLevelValidationFill = (tmpiglfill != _graylevel) &&
350 (tmpiglfill2 != _graylevel) &&
351 (tmpiglfill >= grayLBFMTOL) &&
352 (tmpiglfill <= grayLBFPTOL) &&
353 (_tmpDistfill <= distbasefill) ; //DFCH
355 auxGrayLevelValidationFill = false;
358 if (auxGrayLevelValidationFill==true)
360 this->_IMManager->AddModifiedPixel(lstX[0], lstY[0], lstZ[0]); //DFCH
365 // _image2->SetScalarComponentFromFloat(px, py, pz, 0,(float) _graylevel);
366 SETVALUE2_VTK_CREA(_graylevel,p_image2,st_image2,lstivi[0])
368 // _image->SetScalarComponentFromFloat(px, py, pz, 0,(float) _graylevel);
369 SETVALUE2_VTK_CREA(_graylevel,p_image,st_image,lstivi[0])
373 // Add point to already visited
374 SETVALUE2_VTK_CREA(1,pAuxImageFill,stAuxImageFill,lstiviAux[0]);
376 // Add neighborhood points in the list
381 if (_direction == 0) // YZ
383 //lstX.push_back(lstX[0]+1); lstY.push_back(lstY[0]); lstZ.push_back(lstZ[0]); lstivi.push_back(lstivi[0]+_OneColumn); lstiviAux.push_back(lstiviAux[0]+OneColumnAux);
384 //lstX.push_back(lstX[0]-1); lstY.push_back(lstY[0]); lstZ.push_back(lstZ[0]); lstivi.push_back(lstivi[0]-_OneColumn); lstiviAux.push_back(lstiviAux[0]-OneColumnAux);
385 lstX.push_back(lstX[0] ); lstY.push_back(lstY[0]+1); lstZ.push_back(lstZ[0] ); lstivi.push_back(lstivi[0]+_OneLine); lstiviAux.push_back(lstiviAux[0]+OneLineAux);
386 lstX.push_back(lstX[0] ); lstY.push_back(lstY[0]-1); lstZ.push_back(lstZ[0] ); lstivi.push_back(lstivi[0]-_OneLine); lstiviAux.push_back(lstiviAux[0]-OneLineAux);
387 lstX.push_back(lstX[0] ); lstY.push_back(lstY[0] ); lstZ.push_back(lstZ[0]+1); lstivi.push_back(lstivi[0]+_OnePlane); lstiviAux.push_back(lstiviAux[0]+OnePlaneAux);
388 lstX.push_back(lstX[0] ); lstY.push_back(lstY[0] ); lstZ.push_back(lstZ[0]-1); lstivi.push_back(lstivi[0]-_OnePlane); lstiviAux.push_back(lstiviAux[0]-OnePlaneAux);
390 if (_direction == 1) // XZ
392 lstX.push_back(lstX[0]+1); lstY.push_back(lstY[0]); lstZ.push_back(lstZ[0]); lstivi.push_back(lstivi[0]+_OneColumn); lstiviAux.push_back(lstiviAux[0]+OneColumnAux);
393 lstX.push_back(lstX[0]-1); lstY.push_back(lstY[0]); lstZ.push_back(lstZ[0]); lstivi.push_back(lstivi[0]-_OneColumn); lstiviAux.push_back(lstiviAux[0]-OneColumnAux);
394 // lstX.push_back(lstX[0] ); lstY.push_back(lstY[0]+1); lstZ.push_back(lstZ[0] ); lstivi.push_back(lstivi[0]+_OneLine); lstiviAux.push_back(lstiviAux[0]+OneLineAux);
395 // lstX.push_back(lstX[0] ); lstY.push_back(lstY[0]-1); lstZ.push_back(lstZ[0] ); lstivi.push_back(lstivi[0]-_OneLine); lstiviAux.push_back(lstiviAux[0]-OneLineAux);
396 lstX.push_back(lstX[0] ); lstY.push_back(lstY[0] ); lstZ.push_back(lstZ[0]+1); lstivi.push_back(lstivi[0]+_OnePlane); lstiviAux.push_back(lstiviAux[0]+OnePlaneAux);
397 lstX.push_back(lstX[0] ); lstY.push_back(lstY[0] ); lstZ.push_back(lstZ[0]-1); lstivi.push_back(lstivi[0]-_OnePlane); lstiviAux.push_back(lstiviAux[0]-OnePlaneAux);
399 if (_direction == 2) // XY
401 lstX.push_back(lstX[0]+1); lstY.push_back(lstY[0]); lstZ.push_back(lstZ[0]); lstivi.push_back(lstivi[0]+_OneColumn); lstiviAux.push_back(lstiviAux[0]+OneColumnAux);
402 lstX.push_back(lstX[0]-1); lstY.push_back(lstY[0]); lstZ.push_back(lstZ[0]); lstivi.push_back(lstivi[0]-_OneColumn); lstiviAux.push_back(lstiviAux[0]-OneColumnAux);
403 lstX.push_back(lstX[0] ); lstY.push_back(lstY[0]+1); lstZ.push_back(lstZ[0] ); lstivi.push_back(lstivi[0]+_OneLine); lstiviAux.push_back(lstiviAux[0]+OneLineAux);
404 lstX.push_back(lstX[0] ); lstY.push_back(lstY[0]-1); lstZ.push_back(lstZ[0] ); lstivi.push_back(lstivi[0]-_OneLine); lstiviAux.push_back(lstiviAux[0]-OneLineAux);
405 //lstX.push_back(lstX[0] ); lstY.push_back(lstY[0] ); lstZ.push_back(lstZ[0]+1); lstivi.push_back(lstivi[0]+_OnePlane); lstiviAux.push_back(lstiviAux[0]+OnePlaneAux);
406 //lstX.push_back(lstX[0] ); lstY.push_back(lstY[0] ); lstZ.push_back(lstZ[0]-1); lstivi.push_back(lstivi[0]-_OnePlane); lstiviAux.push_back(lstiviAux[0]-OnePlaneAux);
409 lstX.push_back(lstX[0]+1); lstY.push_back(lstY[0]); lstZ.push_back(lstZ[0]); lstivi.push_back(lstivi[0]+_OneColumn); lstiviAux.push_back(lstiviAux[0]+OneColumnAux);
410 lstX.push_back(lstX[0]-1); lstY.push_back(lstY[0]); lstZ.push_back(lstZ[0]); lstivi.push_back(lstivi[0]-_OneColumn); lstiviAux.push_back(lstiviAux[0]-OneColumnAux);
411 lstX.push_back(lstX[0] ); lstY.push_back(lstY[0]+1); lstZ.push_back(lstZ[0] ); lstivi.push_back(lstivi[0]+_OneLine); lstiviAux.push_back(lstiviAux[0]+OneLineAux);
412 lstX.push_back(lstX[0] ); lstY.push_back(lstY[0]-1); lstZ.push_back(lstZ[0] ); lstivi.push_back(lstivi[0]-_OneLine); lstiviAux.push_back(lstiviAux[0]-OneLineAux);
413 lstX.push_back(lstX[0] ); lstY.push_back(lstY[0] ); lstZ.push_back(lstZ[0]+1); lstivi.push_back(lstivi[0]+_OnePlane); lstiviAux.push_back(lstiviAux[0]+OnePlaneAux);
414 lstX.push_back(lstX[0] ); lstY.push_back(lstY[0] ); lstZ.push_back(lstZ[0]-1); lstivi.push_back(lstivi[0]-_OnePlane); lstiviAux.push_back(lstiviAux[0]-OnePlaneAux);
416 } // if gray level valid auxGrayLevelValidationFill
417 } // if point not visited
418 } // if distance of center point
419 } // if point inside image
420 // Remove point from the list
421 lstX.erase( lstX.begin() );
422 lstY.erase( lstY.begin() );
423 lstZ.erase( lstZ.begin() );
424 lstivi.erase( lstivi.begin() );
425 lstiviAux.erase( lstiviAux.begin() );
426 } // while _lstX.size
428 Copy_AuxImageFill_To_GeneralAuxFill( minXAux, minYAux, minZAux, auxImageFill );
430 auxImageFill->Delete();
433 //---------------------------------------------------------------------------
434 void FillFilter::SetToleranceFill(double tolerancefill)
436 _tolerancefill = tolerancefill;
439 //---------------------------------------------------------------------------
440 void FillFilter::SetDistanceFill(int distancefill)
442 _distancefill = distancefill;
445 /*//EED 2020-04-28 BORRAME Change to local variables to use with openmp
446 //---------------------------------------------------------------------------
447 vtkImageData* FillFilter::GetAuxImageFill()
449 return _auxImageFill;