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
106 /* //EED 2020-04-28 BORRAME Change to local variables to use with openmp
107 if ( (_px >= _minX) && (_px < _dimX) &&
108 (_py >= _minY) && (_py < _dimY) &&
109 (_pz >= _minZ) && (_pz < _dimZ) )
111 this->_IMManager->BaseInitialPoint(_px, _py ,_pz);
112 FillToolLoop(_px, _py, _pz);
113 } //if _minX _maxX _minY _maxY _minZ _maxZ
116 if ( (px >= _minX) && (px < _dimX) &&
117 (py >= _minY) && (py < _dimY) &&
118 (pz >= _minZ) && (pz < _dimZ) )
120 this->_IMManager->BaseInitialPoint(px, py ,pz);
121 FillToolLoop(px, py, pz);
122 } //if _minX _maxX _minY _maxY _minZ _maxZ
129 //---------------------------------------------------------------------------
130 vtkImageData* FillFilter::CreateAuxImageFill( long int &OneColumnAux, long int &OneLineAux , long int &OnePlaneAux,
131 int px, int py, int pz,
132 int &pxAux, int &pyAux, int &pzAux,
133 int &minXAux, int &minYAux, int &minZAux )
137 minXAux = px-_distancefill; if (minXAux>=0) { pxAux=px-minXAux; } else { pxAux=px; minXAux=0; }
138 minYAux = py-_distancefill; if (minYAux>=0) { pyAux=py-minYAux; } else { pyAux=py; minYAux=0; }
139 minZAux = pz-_distancefill; if (minZAux>=0) { pzAux=pz-minZAux; } else { pzAux=pz; minZAux=0; }
141 int maxXAux = px+_distancefill; if (maxXAux>_dimX) { maxXAux=_dimX; }
142 int maxYAux = py+_distancefill; if (maxYAux>_dimY) { maxYAux=_dimY; }
143 int maxZAux = pz+_distancefill; if (maxZAux>_dimZ) { maxZAux=_dimZ; }
146 int auxDimX = maxXAux-minXAux+1;
147 int auxDimY = maxYAux-minYAux+1;
148 int auxDimZ = maxZAux-minZAux+1;
153 if (_direction==0) // YZ
157 if (_direction==1) // XZ
161 if (_direction==2) // XY
168 OneLineAux = auxDimX;
169 OnePlaneAux = auxDimX*auxDimY;
171 vtkImageData *auxImageFill;
172 auxImageFill = vtkImageData::New();
173 auxImageFill->SetDimensions(auxDimX, auxDimY, auxDimZ);
174 auxImageFill->SetOrigin(0, 0, 0);
175 auxImageFill->SetExtent(0, auxDimX-1, 0, auxDimY-1, 0, auxDimZ-1);
176 auxImageFill->AllocateScalars(VTK_UNSIGNED_CHAR,1);
177 unsigned char * ptrAuxImageFill = (unsigned char *)auxImageFill->GetScalarPointer();
178 memset( ptrAuxImageFill, 0, auxDimX*auxDimY*auxDimZ );
182 void FillFilter::Copy_AuxImageFill_To_GeneralAuxFill(int minXAux, int minYAux, int minZAux, vtkImageData *auxImageFill)
184 // copy information from the litle image auxImageFill to the big image _GeneralAuxImageFill
185 DEF_POINTER_IMAGE_VTK_CREA(vAuxImageFill,ssAuxImageFill,pAuxImageFill,stAuxImageFill,auxImageFill)
186 DEF_POINTER_IMAGE_VTK_CREA(v_GeneralAuxImageFill,ss_GeneralAuxImageFill,p_GeneralAuxImageFill,st_GeneralAuxImageFill,_GeneralAuxImageFill)
188 auxImageFill->GetExtent(ext);
189 int auxDimX = ext[1]-ext[0]+1;
190 int auxDimY = ext[3]-ext[2]+1;
191 int auxDimZ = ext[5]-ext[4]+1;
194 long int indexGeneralAux;
195 for (k=0;k<auxDimZ;k++)
197 for (j=0;j<auxDimY;j++)
199 indexGeneralAux=minXAux + (minYAux+j)*_OneLine + (minZAux+k)*_OnePlane;
200 // indexAux = j*OneLineAux + k*OnePlaneAux;
201 for (i=0;i<auxDimX;i++)
203 GETVALUE2_VTK_CREA(vAuxImageFill,pAuxImageFill,stAuxImageFill,indexAux)
205 if (vAuxImageFill==1)
207 SETVALUE2_VTK_CREA(vAuxImageFill,p_GeneralAuxImageFill,st_GeneralAuxImageFill,indexGeneralAux)
208 } // if vAuxImageFill
209 indexGeneralAux = indexGeneralAux+_OneColumn;
215 void FillFilter::Copy_GeneralAuxFill_to_Results()
217 DEF_POINTER_IMAGE_VTK_CREA(v_GeneralAuxImageFill,ss_GeneralAuxImageFill,p_GeneralAuxImageFill,st_GeneralAuxImageFill,_GeneralAuxImageFill)
218 long int i,size = _dimX*_dimY*_dimZ;
221 DEF_POINTER_IMAGE_VTK_CREA(v_image,ss_image,p_image,st_image,_image)
222 // DEF_POINTER_IMAGE_VTK_CREA_set(v_image,ss_image,p_image,st_image,_image)
223 #pragma omp parallel for
227 GETVALUE2_VTK_CREA(value,p_GeneralAuxImageFill,st_GeneralAuxImageFill,i)
230 SETVALUE2_VTK_CREA(_graylevel,p_image,st_image,i)
231 } // if v_GeneralAuxImageFill
234 DEF_POINTER_IMAGE_VTK_CREA(v_image2,ss_image2,p_image2,st_image2,_image2)
235 // DEF_POINTER_IMAGE_VTK_CREA_set(v_image2,ss_image2,p_image2,st_image2,_image2)
236 #pragma omp parallel for
240 GETVALUE2_VTK_CREA(value,p_GeneralAuxImageFill,st_GeneralAuxImageFill,i)
243 SETVALUE2_VTK_CREA(_graylevel,p_image2,st_image2,i)
244 } // if v_GeneralAuxImageFill
253 //---------------------------------------------------------------------------
254 void FillFilter::FillToolLoop(int px, int py, int pz)
257 double graylevelbasefill;
260 bool auxGrayLevelValidationFill;
264 distbasefill = _distancefill * _distancefill;
265 double difX,difY,difZ,_tmpDistfill;
266 std::vector<int> lstX;
267 std::vector<int> lstY;
268 std::vector<int> lstZ;
272 std::vector<long long int> lstivi;
273 lstivi.push_back( px + py*_OneLine+ pz*_OnePlane );
275 long int OneColumnAux, OneLineAux, OnePlaneAux; // how to jump in the little image auxImageFill
276 int pxAux, pyAux, pzAux; // position inside little image auxImageFill
277 int minXAux, minYAux, minZAux; // Where start the little image auxImageFill in the big image
278 vtkImageData* auxImageFill = CreateAuxImageFill( OneColumnAux,OneLineAux,OnePlaneAux,
281 minXAux,minYAux,minZAux );
282 std::vector<long long int> lstiviAux;
283 lstiviAux.push_back( pxAux + pyAux*OneLineAux + pzAux*OnePlaneAux );
285 DEF_POINTER_IMAGE_VTK_CREA(v_image,ss_image,p_image,st_image,_image)
286 // DEF_POINTER_IMAGE_VTK_CREA_set(v_image,ss_image,p_image,st_image,_image)
296 // DEF_POINTER_IMAGE_VTK_CREA(v_image2,ss_image2,p_image2,st_image2,_image2)
297 DEF_POINTER_IMAGE_VTK_CREA_set(v_image2,ss_image2,p_image2,st_image2,_image2)
300 GETVALUE2_VTK_CREA(graylevelbasefill,p_image,st_image,lstivi[0])
302 //EED 2020-04-28 BORRAME Change to local variables to use with openmp
303 // DEF_POINTER_IMAGE_VTK_CREA(v_auxImageFill,ss_auxImageFill,p_auxImageFill,st_auxImageFill,_auxImageFill)
304 DEF_POINTER_IMAGE_VTK_CREA(vAuxImageFill,ssAuxImageFill,pAuxImageFill,stAuxImageFill,auxImageFill)
306 while ( lstX.size()!=0 )
308 // if point inside image
309 if ((lstX[0] >= _minX) && (lstX[0] < _dimX) && (lstY[0] >= _minY) && (lstY[0] < _dimY) && (lstZ[0] >= _minZ) && (lstZ[0] < _dimZ))
314 _tmpDistfill = difX*difX + difY*difY + difZ*difZ;
315 // if distance of center point
316 if (_tmpDistfill<=distbasefill)
318 // if point not visited
319 GETVALUE2_VTK_CREA(vAuxImageFill,pAuxImageFill,stAuxImageFill,lstiviAux[0] );
320 if (vAuxImageFill==0)
322 // If Gray Level valid
325 // tmpiglfill = _image->GetScalarComponentAsDouble(px, py, pz, 0);
326 GETVALUE2_VTK_CREA(tmpiglfill,p_image,st_image,lstivi[0])
331 // tmpiglfill2 = _image2->GetScalarComponentAsDouble(px, py, pz, 0);
332 GETVALUE2_VTK_CREA(tmpiglfill2,p_image2,st_image2,lstivi[0])
334 tmpiglfill2 = tmpiglfill;
337 float grayLBFMTOL = graylevelbasefill - _tolerancefill;
338 float grayLBFPTOL = graylevelbasefill + _tolerancefill;
339 bool isInRange = false;
341 if (_RangeMin <= grayLBFMTOL && _RangeMax >= grayLBFPTOL) {
344 else if (_RangeMin > grayLBFMTOL && _RangeMax >= grayLBFPTOL) {
345 grayLBFMTOL = _RangeMin;
348 else if (_RangeMin <= grayLBFMTOL && _RangeMax < grayLBFPTOL) {
349 grayLBFPTOL = _RangeMax;
352 else if ((_RangeMin <= graylevelbasefill) && (graylevelbasefill <= _RangeMax)) {
353 grayLBFMTOL = _RangeMin;
354 grayLBFPTOL = _RangeMax;
360 auxGrayLevelValidationFill = (tmpiglfill != _graylevel) &&
361 (tmpiglfill2 != _graylevel) && // <<<<<<<<< xxxxxxxxxxxxxxxxxxxxxx
362 (tmpiglfill >= grayLBFMTOL) &&
363 (tmpiglfill <= grayLBFPTOL) &&
364 (_tmpDistfill <= distbasefill) ; //DFCH
366 auxGrayLevelValidationFill = false;
369 if (auxGrayLevelValidationFill==true)
371 this->_IMManager->AddModifiedPixel(lstX[0], lstY[0], lstZ[0]); //DFCH
376 // _image2->SetScalarComponentFromFloat(px, py, pz, 0,(float) _graylevel);
377 SETVALUE2_VTK_CREA(_graylevel,p_image2,st_image2,lstivi[0])
379 // _image->SetScalarComponentFromFloat(px, py, pz, 0,(float) _graylevel);
380 SETVALUE2_VTK_CREA(_graylevel,p_image,st_image,lstivi[0])
384 // Add point to already visited
385 SETVALUE2_VTK_CREA(1,pAuxImageFill,stAuxImageFill,lstiviAux[0]);
387 // Add neighborhood points in the list
392 if (_direction == 0) // YZ
394 //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);
395 //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);
396 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);
397 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);
398 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 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);
401 if (_direction == 1) // XZ
403 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);
404 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);
405 // 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);
406 // 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);
407 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);
408 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);
410 if (_direction == 2) // XY
412 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);
413 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);
414 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);
415 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);
416 //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);
417 //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);
420 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);
421 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);
422 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);
423 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);
424 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);
425 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);
427 } // if gray level valid auxGrayLevelValidationFill
428 } // if point not visited
429 } // if distance of center point
430 } // if point inside image
431 // Remove point from the list
432 lstX.erase( lstX.begin() );
433 lstY.erase( lstY.begin() );
434 lstZ.erase( lstZ.begin() );
435 lstivi.erase( lstivi.begin() );
436 lstiviAux.erase( lstiviAux.begin() );
437 } // while _lstX.size
439 Copy_AuxImageFill_To_GeneralAuxFill( minXAux, minYAux, minZAux, auxImageFill );
441 auxImageFill->Delete();
444 //---------------------------------------------------------------------------
445 void FillFilter::SetToleranceFill(double tolerancefill)
447 _tolerancefill = tolerancefill;
450 //---------------------------------------------------------------------------
451 void FillFilter::SetDistanceFill(int distancefill)
453 _distancefill = distancefill;
456 /*//EED 2020-04-28 BORRAME Change to local variables to use with openmp
457 //---------------------------------------------------------------------------
458 vtkImageData* FillFilter::GetAuxImageFill()
460 return _auxImageFill;