PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/Modules/Scripted/EditorLib/Logic/vtkImageConnectivity.cxx

https://github.com/lorensen/Slicer
C++ | 890 lines | 645 code | 76 blank | 169 comment | 136 complexity | 193ef064e7def273af510124cd1ccdad MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
  1. /*=auto=========================================================================
  2. Portions (c) Copyright 2005 Brigham and Women's Hospital (BWH) All Rights Reserved.
  3. See COPYRIGHT.txt
  4. or http://www.slicer.org/copyright/copyright.txt for details.
  5. =========================================================================auto=*/
  6. #include "vtkImageConnectivity.h"
  7. #include "vtkObjectFactory.h"
  8. #include "vtkImageData.h"
  9. #include <vtkInformation.h>
  10. #include <vtkStreamingDemandDrivenPipeline.h>
  11. #include <limits.h>
  12. #include <assert.h>
  13. #include <stddef.h>
  14. //----------------------------------------------------------------------------
  15. vtkStandardNewMacro(vtkImageConnectivity);
  16. //----------------------------------------------------------------------------
  17. // Description:
  18. // Constructor sets default values
  19. vtkImageConnectivity::vtkImageConnectivity()
  20. {
  21. this->Background = 0;
  22. this->MinForeground = VTK_SHORT_MIN;
  23. this->MaxForeground = VTK_SHORT_MAX;
  24. this->MinSize = 10000;
  25. this->Function = CONNECTIVITY_MEASURE;
  26. this->OutputLabel = 1;
  27. this->SliceBySlice = 0;
  28. this->LargestIslandSize = this->IslandSize = 0;
  29. this->Seed[0] = this->Seed[1] = this->Seed[2] = 0;
  30. }
  31. //----------------------------------------------------------------------------
  32. const char* vtkImageConnectivity::GetFunctionString()
  33. {
  34. switch (this->Function)
  35. {
  36. case CONNECTIVITY_IDENTIFY:
  37. return "IdentifyIslands";
  38. case CONNECTIVITY_REMOVE:
  39. return "RemoveIslands";
  40. case CONNECTIVITY_CHANGE:
  41. return "ChangeIsland";
  42. case CONNECTIVITY_MEASURE:
  43. return "MeasureIsland";
  44. case CONNECTIVITY_SAVE:
  45. return "SaveIsland";
  46. default:
  47. return "ERROR: Unknown";
  48. }
  49. }
  50. //************************************************************************
  51. // The following procedures were written by Andre Robatino
  52. // in November, 1999
  53. //
  54. // connect
  55. // recursive_copy
  56. //************************************************************************
  57. int connect(unsigned int, size_t *, char *, char, size_t *, size_t *);
  58. static void recursive_copy(int, size_t);
  59. static size_t *g_axis_len, *g_outimagep, num_stride_index_bits;
  60. static char *g_inimagep, g_inbackground;
  61. int connect(
  62. unsigned int rank,
  63. size_t *axis_len,
  64. char *inimage,
  65. char inbackground,
  66. size_t *outimage,
  67. size_t *num_components) /* set to NULL if not interested */
  68. {
  69. unsigned int i;
  70. register unsigned int axisv;
  71. size_t data_len;
  72. register size_t label, *outimagep, *outimage_end, *imagep, *new_imagep, boundary_mask_start, component_mask, axis_mask;
  73. register ptrdiff_t *stride, stridev;
  74. //assert(rank >= 0); // Note: Always true !
  75. if (rank == 0) {
  76. *outimage = (*inimage != inbackground);
  77. if (num_components) *num_components = *outimage;
  78. return 0;
  79. }
  80. label = 2*rank;
  81. num_stride_index_bits = 1;
  82. while (label >>= 1) num_stride_index_bits++;
  83. assert(num_stride_index_bits + 2*rank + 1 <= CHAR_BIT*sizeof(size_t));
  84. boundary_mask_start = 1<<num_stride_index_bits;
  85. axis_mask = boundary_mask_start - 1;
  86. stride = (ptrdiff_t *)malloc((2*rank + 1)*sizeof(ptrdiff_t));
  87. assert(stride);
  88. data_len = 1;
  89. for (i=0; i<rank; i++) {
  90. assert(axis_len[i] > 1);
  91. stride[2*i + 1] = -(stride[2*i] = data_len);
  92. data_len *= axis_len[i];
  93. }
  94. stride[2*rank] = 0;
  95. g_axis_len = axis_len;
  96. g_inimagep = inimage;
  97. g_inbackground = inbackground;
  98. g_outimagep = outimage;
  99. component_mask = 0;
  100. component_mask = ~(~component_mask>>1);
  101. recursive_copy(rank-1, component_mask);
  102. outimagep = outimage;
  103. outimage_end = outimage + data_len;
  104. label = 0;
  105. do {
  106. if (!(*outimagep & component_mask)) continue;
  107. imagep = outimagep;
  108. *imagep ^= component_mask;
  109. axisv = 0;
  110. label++;
  111. while (1) {
  112. while ( (stridev = stride[axisv]) ) {
  113. if ((*imagep & boundary_mask_start<<axisv) && (*(new_imagep = imagep + stridev) & component_mask)) {
  114. imagep = new_imagep;
  115. *imagep ^= component_mask;
  116. *imagep |= axisv;
  117. axisv = 0;
  118. continue;
  119. }
  120. axisv++;
  121. }
  122. if (imagep == outimagep) break;
  123. axisv = *imagep & axis_mask;
  124. *imagep = label;
  125. imagep -= stride[axisv++];
  126. }
  127. *outimagep = label;
  128. } while (++outimagep < outimage_end);
  129. if (num_components) *num_components = label;
  130. free(stride);
  131. return 0;
  132. }
  133. static void recursive_copy(
  134. int axis,
  135. register size_t mask)
  136. {
  137. register size_t len = g_axis_len[axis] - 2;
  138. if (axis == 0) {
  139. register size_t *outimagep;
  140. register char *inimagep, inbackground;
  141. inimagep = g_inimagep;
  142. inbackground = g_inbackground;
  143. outimagep = g_outimagep;
  144. mask |= 1<<num_stride_index_bits;
  145. *outimagep++ = (*inimagep++ == inbackground)? 0 : mask;
  146. mask |= 2<<num_stride_index_bits;
  147. while (len--) *outimagep++ = (*inimagep++ == inbackground)? 0 : mask;
  148. mask ^= 1<<num_stride_index_bits;
  149. *outimagep++ = (*inimagep++ == inbackground)? 0 : mask;
  150. g_outimagep = outimagep;
  151. g_inimagep = inimagep;
  152. } else {
  153. mask |= 1<<(num_stride_index_bits + 2*axis);
  154. recursive_copy(axis-1, mask);
  155. mask |= 2<<(num_stride_index_bits + 2*axis);
  156. while (len--) recursive_copy(axis-1, mask);
  157. mask ^= 1<<(num_stride_index_bits + 2*axis);
  158. recursive_copy(axis-1, mask);
  159. }
  160. return;
  161. }
  162. //***********************************************************************
  163. // End Andre's cool routines.
  164. //************************************************************************
  165. static void vtkImageConnectivityExecute(vtkImageConnectivity *self,
  166. vtkImageData *inData, short *inPtr,
  167. vtkImageData *outData, short *outPtr,
  168. int outExt[6])
  169. {
  170. // For looping though output (and input) pixels.
  171. int outMin0, outMax0, outMin1, outMax1, outMin2, outMax2;
  172. int outIdx0, outIdx1, outIdx2;
  173. vtkIdType inInc0, inInc1, inInc2;
  174. vtkIdType outInc0, outInc1, outInc2;
  175. short *inPtr0, *outPtr0, *outPtr1;
  176. short minForegnd = (short)self->GetMinForeground();
  177. short maxForegnd = (short)self->GetMaxForeground();
  178. short newLabel = (short)self->GetOutputLabel();
  179. short seedLabel = 0;
  180. int largest, len=1, nxy, z, nz = 0, j;
  181. int *census = NULL;
  182. int seed[3];
  183. int minSize = self->GetMinSize();
  184. short pix;
  185. int identifyIslands = self->GetFunction() == CONNECTIVITY_IDENTIFY;
  186. int removeIslands = self->GetFunction() == CONNECTIVITY_REMOVE;
  187. int changeIsland = self->GetFunction() == CONNECTIVITY_CHANGE;
  188. int saveIsland = self->GetFunction() == CONNECTIVITY_SAVE;
  189. int measureIsland = self->GetFunction() == CONNECTIVITY_MEASURE;
  190. int sliceBySlice = self->GetSliceBySlice();
  191. // connect
  192. size_t conSeedLabel = 0, i, idx, dz;
  193. int rank;
  194. size_t *axis_len=NULL;
  195. unsigned short bg = self->GetBackground();
  196. short bgMask = 0;
  197. short fgMask = 1;
  198. char inbackground = (char)bgMask;
  199. char *conInput=NULL;
  200. size_t *conOutput=NULL;
  201. size_t *numIslands=NULL;
  202. // Image bounds
  203. outMin0 = outExt[0]; outMax0 = outExt[1];
  204. outMin1 = outExt[2]; outMax1 = outExt[3];
  205. outMin2 = outExt[4]; outMax2 = outExt[5];
  206. // Computer Parameters for connect().
  207. rank = (outExt[5]==outExt[4]) ? 2 : 3;
  208. axis_len = new size_t[rank+1];
  209. axis_len[0] = outExt[1]-outExt[0]+1;
  210. axis_len[1] = outExt[3]-outExt[2]+1;
  211. axis_len[2] = outExt[5]-outExt[4]+1;
  212. for (j=0; j<rank; j++)
  213. {
  214. len *= axis_len[j];
  215. }
  216. conInput = new char[len];
  217. conOutput = new size_t[len];
  218. numIslands = new size_t[axis_len[2]];
  219. // Get increments to march through data continuously
  220. outData->GetContinuousIncrements(outExt, outInc0, outInc1, outInc2);
  221. inData->GetContinuousIncrements(outExt, inInc0, inInc1, inInc2);
  222. ///////////////////////////////////////////////////////////////
  223. // Save, Change, Measure:
  224. // ----------------------
  225. // Get the seed
  226. //
  227. // seedLabel = inData[xSeed,ySeed,zSeed]
  228. //
  229. // If the seed is out of bounds, return the input
  230. //
  231. // outData[i] = inData[i]
  232. //
  233. ///////////////////////////////////////////////////////////////
  234. if (changeIsland || measureIsland || saveIsland)
  235. {
  236. self->GetSeed(seed);
  237. if (seed[0] < outMin0 || seed[0] > outMax0 ||
  238. seed[1] < outMin1 || seed[1] > outMax1 ||
  239. seed[2] < outMin2 || seed[2] > outMax2)
  240. {
  241. //
  242. // Out of bounds -- abort!
  243. //
  244. inPtr0 = inPtr;
  245. outPtr0 = outPtr;
  246. for (outIdx2 = outMin2; outIdx2 <= outMax2; outIdx2++)
  247. {
  248. for (outIdx1 = outMin1; outIdx1 <= outMax1; outIdx1++)
  249. {
  250. for (outIdx0 = outMin0; outIdx0 <= outMax0; outIdx0++)
  251. {
  252. *outPtr0 = *inPtr0;
  253. outPtr0++;
  254. inPtr0++;
  255. }//for0
  256. outPtr0 += outInc1;
  257. inPtr0 += inInc1;
  258. }//for1
  259. outPtr0 += outInc2;
  260. inPtr0 += inInc2;
  261. }//for2
  262. fprintf(stderr, "Seed %d,%d,%d out of bounds in CCA.\n",
  263. seed[0], seed[1], seed[2]);
  264. return;
  265. }
  266. //
  267. // In bounds!
  268. //
  269. outPtr1 = (short*)inData->GetScalarPointer(seed[0], seed[1], seed[2]);
  270. seedLabel = *outPtr1;
  271. }
  272. ///////////////////////////////////////////////////////////////
  273. // Remove, Identify:
  274. // ----------------------
  275. // Create a mask where everything outside [min,max] or in the
  276. // sea (bg) is in the background.
  277. //
  278. // conInput[i] = fgMask, inData[i] != bg
  279. // = bgMask, else
  280. //
  281. // conInput[i] = unchanged
  282. // = bgMask, where inData[i] not on [min,max]
  283. //
  284. ///////////////////////////////////////////////////////////////
  285. if (removeIslands || identifyIslands)
  286. {
  287. inPtr0 = inPtr;
  288. i = 0;
  289. for (outIdx2 = outMin2; outIdx2 <= outMax2; outIdx2++)
  290. {
  291. for (outIdx1 = outMin1; outIdx1 <= outMax1; outIdx1++)
  292. {
  293. for (outIdx0 = outMin0; outIdx0 <= outMax0; outIdx0++)
  294. {
  295. if (*inPtr0 != bg)
  296. {
  297. conInput[i] = fgMask;
  298. }
  299. else
  300. {
  301. conInput[i] = bgMask;
  302. }
  303. inPtr0++;
  304. i++;
  305. }//for0
  306. inPtr0 += inInc1;
  307. }//for1
  308. inPtr0 += inInc2;
  309. }//for2
  310. // Optionally threshold [min,max]
  311. if(minForegnd > VTK_SHORT_MIN || maxForegnd < VTK_SHORT_MAX)
  312. {
  313. inPtr0 = inPtr;
  314. i=0;
  315. for (outIdx2 = outMin2; outIdx2 <= outMax2; outIdx2++)
  316. {
  317. for (outIdx1 = outMin1; outIdx1 <= outMax1; outIdx1++)
  318. {
  319. for (outIdx0 = outMin0; outIdx0 <= outMax0; outIdx0++)
  320. {
  321. pix = *inPtr0;
  322. if (pix < minForegnd || pix > maxForegnd)
  323. {
  324. conInput[i] = bgMask;
  325. }
  326. i++;
  327. inPtr0++;
  328. }//for0
  329. inPtr0 += inInc1;
  330. }//for1
  331. inPtr0 += inInc2;
  332. }//for2
  333. }
  334. }
  335. ///////////////////////////////////////////////////////////////
  336. // Save, Change, Measure:
  337. // ----------------------
  338. //
  339. // Create a mask where everything not equal to seedLabel is
  340. // in the background.
  341. //
  342. // conInput[i] = fgMask, inData[i] == seedLabel
  343. // = bgMask, else
  344. //
  345. ///////////////////////////////////////////////////////////////
  346. if (saveIsland || changeIsland || measureIsland)
  347. {
  348. inPtr0 = inPtr;
  349. i = 0;
  350. for (outIdx2 = outMin2; outIdx2 <= outMax2; outIdx2++)
  351. {
  352. for (outIdx1 = outMin1; outIdx1 <= outMax1; outIdx1++)
  353. {
  354. for (outIdx0 = outMin0; outIdx0 <= outMax0; outIdx0++)
  355. {
  356. if (*inPtr0 == seedLabel)
  357. {
  358. conInput[i] = fgMask;
  359. }
  360. else
  361. {
  362. conInput[i] = bgMask;
  363. }
  364. inPtr0++;
  365. i++;
  366. }//for0
  367. inPtr0 += inInc1;
  368. }//for1
  369. inPtr0 += inInc2;
  370. }//for2
  371. }
  372. ///////////////////////////////////////////////////////////////
  373. // Save, Change, Measure, Remove, Identify
  374. // ---------------------------------------
  375. // Run Connectivity
  376. //
  377. ///////////////////////////////////////////////////////////////
  378. if (saveIsland || changeIsland || measureIsland || removeIslands || identifyIslands)
  379. {
  380. nz = 1;
  381. if (sliceBySlice && removeIslands)
  382. {
  383. // If SliceBySlice, then call connect() for each slice
  384. nxy = axis_len[0] * axis_len[1];
  385. nz = axis_len[2];
  386. rank = 2;
  387. int axis_len2 = axis_len[2];
  388. axis_len[2] = 1;
  389. for (z=0; z < nz; z++)
  390. {
  391. connect(rank, axis_len, &conInput[nxy*z], inbackground,
  392. &conOutput[nxy*z], &numIslands[z]);
  393. }
  394. axis_len[2] = axis_len2;
  395. }
  396. else
  397. {
  398. connect(rank, axis_len, conInput, inbackground, conOutput, &numIslands[0]);
  399. }
  400. }
  401. ///////////////////////////////////////////////////////////////
  402. // Save, Change, Measure
  403. // -----------------------------
  404. // Get conSeedLabel
  405. //
  406. // conSeedLabel = conOutput[xSeed,ySeed,zSeed]
  407. //
  408. ///////////////////////////////////////////////////////////////
  409. if (saveIsland || changeIsland || measureIsland)
  410. {
  411. i = seed[2]*axis_len[1]*axis_len[0] + seed[1]*axis_len[0] + seed[0];
  412. conSeedLabel = conOutput[i];
  413. }
  414. ///////////////////////////////////////////////////////////////
  415. // Measure, Remove
  416. // -----------------------------
  417. // Count size of each island in conOutput
  418. //
  419. // census[c] = COUNT(conOutput[c]), forall c on [0,numIslands]
  420. //
  421. ///////////////////////////////////////////////////////////////
  422. if (removeIslands || measureIsland)
  423. {
  424. // For each label value, count the number of pixels with that label
  425. // If SliceBySlice, then work on each slice one at a time
  426. len = 0;
  427. for (z=0; z<nz; z++)
  428. {
  429. len += numIslands[z] + 1;
  430. }
  431. census = new int[len];
  432. memset(census, 0, len*sizeof(int));
  433. if (nz == 1)
  434. {
  435. i = 0;
  436. for (outIdx2 = outMin2; outIdx2 <= outMax2; outIdx2++)
  437. {
  438. for (outIdx1 = outMin1; outIdx1 <= outMax1; outIdx1++)
  439. {
  440. for (outIdx0 = outMin0; outIdx0 <= outMax0; outIdx0++)
  441. {
  442. idx = conOutput[i];
  443. // Note: Since 'idx' is defined as 'size_t' it's of type 'unsigned'
  444. // It means 'idx >= 0' is always true.
  445. if (/*idx >= 0 && */idx <= numIslands[0])
  446. {
  447. census[idx] = census[idx] + 1;
  448. }
  449. i++;
  450. }//for0
  451. }//for1
  452. }//for2
  453. }
  454. else
  455. {
  456. dz = 0;
  457. i = 0;
  458. for (z=0; z < nz; z++)
  459. {
  460. for (outIdx1 = outMin1; outIdx1 <= outMax1; outIdx1++)
  461. {
  462. for (outIdx0 = outMin0; outIdx0 <= outMax0; outIdx0++)
  463. {
  464. idx = conOutput[i];
  465. // Note: Since 'idx' is defined as 'size_t' it's of type 'unsigned'
  466. // It means 'idx >= 0' is always true.
  467. if (/*idx >= 0 && */idx <= numIslands[z])
  468. {
  469. census[dz+idx] = census[dz+idx] + 1;
  470. }
  471. i++;
  472. }//for0
  473. }//for1
  474. dz += numIslands[z]+1;
  475. }//forz
  476. }
  477. }
  478. ///////////////////////////////////////////////////////////////
  479. // Remove
  480. // -----------------------------
  481. // Output gets input except where islands too small
  482. //
  483. // outData[i] = inData[i], census[conOutput[i]] >= minIslandSize
  484. // = bg, else
  485. //
  486. ///////////////////////////////////////////////////////////////
  487. if (removeIslands)
  488. {
  489. if (nz == 1)
  490. {
  491. inPtr0 = inPtr;
  492. outPtr0 = outPtr;
  493. i = 0;
  494. for (outIdx2 = outMin2; outIdx2 <= outMax2; outIdx2++)
  495. {
  496. for (outIdx1 = outMin1; outIdx1 <= outMax1; outIdx1++)
  497. {
  498. for (outIdx0 = outMin0; outIdx0 <= outMax0; outIdx0++)
  499. {
  500. if (census[conOutput[i]] >= minSize)
  501. {
  502. *outPtr0 = *inPtr0;
  503. }
  504. else
  505. {
  506. *outPtr0 = bg;
  507. }
  508. i++;
  509. outPtr0++;
  510. inPtr0++;
  511. }//for0
  512. outPtr0 += outInc1;
  513. inPtr0 += inInc1;
  514. }//for1
  515. outPtr0 += outInc2;
  516. inPtr0 += inInc2;
  517. }//for2
  518. }
  519. else
  520. {
  521. dz = 0;
  522. i = 0;
  523. inPtr0 = inPtr;
  524. outPtr0 = outPtr;
  525. for (z=0; z < nz; z++)
  526. {
  527. for (outIdx1 = outMin1; outIdx1 <= outMax1; outIdx1++)
  528. {
  529. for (outIdx0 = outMin0; outIdx0 <= outMax0; outIdx0++)
  530. {
  531. if (census[dz+conOutput[i]] >= minSize)
  532. {
  533. *outPtr0 = *inPtr0;
  534. }
  535. else
  536. {
  537. *outPtr0 = bg;
  538. }
  539. i++;
  540. outPtr0++;
  541. inPtr0++;
  542. }//for0
  543. outPtr0 += outInc1;
  544. inPtr0 += inInc1;
  545. }//for1
  546. outPtr0 += outInc2;
  547. inPtr0 += inInc2;
  548. dz += numIslands[z] + 1;
  549. }//z
  550. }//else
  551. }
  552. ///////////////////////////////////////////////////////////////
  553. // Measure
  554. // -----------------------------
  555. // Store statistics, and return output = input.
  556. //
  557. // islandSize = census[conSeedLabel]
  558. // largest = MAX(census[c])
  559. // outData[i] = inData[i]
  560. //
  561. ///////////////////////////////////////////////////////////////
  562. if (measureIsland)
  563. {
  564. // Find largest island
  565. largest = 0;
  566. for (i=0; i<=numIslands[0]; i++)
  567. {
  568. if (i != bg)
  569. {
  570. if (census[i] > largest)
  571. {
  572. largest = census[i];
  573. }
  574. }
  575. }
  576. self->SetLargestIslandSize(largest);
  577. // Measure island at seed
  578. self->SetIslandSize(census[conSeedLabel]);
  579. // Return output values to be the inputs
  580. inPtr0 = inPtr;
  581. outPtr0 = outPtr;
  582. for (outIdx2 = outMin2; outIdx2 <= outMax2; outIdx2++)
  583. {
  584. for (outIdx1 = outMin1; outIdx1 <= outMax1; outIdx1++)
  585. {
  586. for (outIdx0 = outMin0; outIdx0 <= outMax0; outIdx0++)
  587. {
  588. *outPtr0 = *inPtr0;
  589. outPtr0++;
  590. inPtr0++;
  591. }//for0
  592. outPtr0 += outInc1;
  593. inPtr0 += inInc1;
  594. }//for1
  595. outPtr0 += outInc2;
  596. inPtr0 += inInc2;
  597. }//for2
  598. }
  599. ///////////////////////////////////////////////////////////////
  600. // Identify
  601. // -----------------------------
  602. // Output gets the output of connect()
  603. //
  604. // outData[i] = conOutput[i]
  605. //
  606. ///////////////////////////////////////////////////////////////
  607. if (identifyIslands)
  608. {
  609. outPtr0 = outPtr;
  610. i = 0;
  611. for (outIdx2 = outMin2; outIdx2 <= outMax2; outIdx2++)
  612. {
  613. for (outIdx1 = outMin1; outIdx1 <= outMax1; outIdx1++)
  614. {
  615. for (outIdx0 = outMin0; outIdx0 <= outMax0; outIdx0++)
  616. {
  617. *outPtr0 = (short)conOutput[i];
  618. i++;
  619. outPtr0++;
  620. }//for0
  621. outPtr0 += outInc1;
  622. }//for1
  623. outPtr0 += outInc2;
  624. }//for2
  625. }
  626. ///////////////////////////////////////////////////////////////
  627. // Remove, Identify
  628. // -----------------------------
  629. // Output gets input where the input was thresholded away
  630. //
  631. // outData[i] = inData[i], inData[i] outside [min,max]
  632. // = do nothing, else
  633. //
  634. ///////////////////////////////////////////////////////////////
  635. if (removeIslands || identifyIslands)
  636. {
  637. if(minForegnd > VTK_SHORT_MIN || maxForegnd < VTK_SHORT_MAX)
  638. {
  639. inPtr0 = inPtr;
  640. outPtr0 = outPtr;
  641. for (outIdx2 = outMin2; outIdx2 <= outMax2; outIdx2++)
  642. {
  643. for (outIdx1 = outMin1; outIdx1 <= outMax1; outIdx1++)
  644. {
  645. for (outIdx0 = outMin0; outIdx0 <= outMax0; outIdx0++)
  646. {
  647. pix = *inPtr0;
  648. if (pix < minForegnd || pix > maxForegnd)
  649. {
  650. *outPtr0 = pix;
  651. }
  652. inPtr0++;
  653. outPtr0++;
  654. }//for0
  655. inPtr0 += inInc1;
  656. outPtr0 += outInc1;
  657. }//for1
  658. inPtr0 += inInc2;
  659. outPtr0 += outInc2;
  660. }//for2
  661. }
  662. }
  663. if (removeIslands || measureIsland)
  664. {
  665. delete [] census;
  666. }
  667. ///////////////////////////////////////////////////////////////
  668. // Save
  669. // -----------------------------
  670. // Output gets input where seedLabel, else bg
  671. //
  672. // outData[i] = inData[i], conOutput[i] == conSeedLabel
  673. // = bg, else
  674. //
  675. ///////////////////////////////////////////////////////////////
  676. if (saveIsland)
  677. {
  678. inPtr0 = inPtr;
  679. outPtr0 = outPtr;
  680. i = 0;
  681. for (outIdx2 = outMin2; outIdx2 <= outMax2; outIdx2++)
  682. {
  683. for (outIdx1 = outMin1; outIdx1 <= outMax1; outIdx1++)
  684. {
  685. for (outIdx0 = outMin0; outIdx0 <= outMax0; outIdx0++)
  686. {
  687. if (conOutput[i] == conSeedLabel)
  688. {
  689. *outPtr0 = *inPtr0;
  690. }
  691. else
  692. {
  693. *outPtr0 = bg;
  694. }
  695. i++;
  696. outPtr0++;
  697. inPtr0++;
  698. }//for0
  699. outPtr0 += outInc1;
  700. inPtr0 += inInc1;
  701. }//for1
  702. outPtr0 += outInc2;
  703. inPtr0 += inInc2;
  704. }//for2
  705. }
  706. ///////////////////////////////////////////////////////////////
  707. // Change
  708. // -----------------------------
  709. // Output gets newLabel where seedLabel, else input
  710. //
  711. // outData[i] = newLabel, conOutput[i] == conSeedLabel
  712. // = inData[i], else
  713. //
  714. ///////////////////////////////////////////////////////////////
  715. if (changeIsland)
  716. {
  717. inPtr0 = inPtr;
  718. outPtr0 = outPtr;
  719. i = 0;
  720. for (outIdx2 = outMin2; outIdx2 <= outMax2; outIdx2++)
  721. {
  722. for (outIdx1 = outMin1; outIdx1 <= outMax1; outIdx1++)
  723. {
  724. for (outIdx0 = outMin0; outIdx0 <= outMax0; outIdx0++)
  725. {
  726. if (conOutput[i] == conSeedLabel)
  727. {
  728. *outPtr0 = newLabel;
  729. }
  730. else
  731. {
  732. *outPtr0 = *inPtr0;
  733. }
  734. i++;
  735. outPtr0++;
  736. inPtr0++;
  737. }//for0
  738. outPtr0 += outInc1;
  739. inPtr0 += inInc1;
  740. }//for1
  741. outPtr0 += outInc2;
  742. inPtr0 += inInc2;
  743. }//for2
  744. }
  745. ///////////////////////////////////////////////////////////////
  746. // Cleanup
  747. ///////////////////////////////////////////////////////////////
  748. delete [] axis_len;
  749. delete [] numIslands;
  750. delete [] conInput;
  751. delete [] conOutput;
  752. }
  753. //----------------------------------------------------------------------------
  754. // Description:
  755. // This method is passed a input and output data, and executes the filter
  756. // algorithm to fill the output from the input.
  757. // It just executes a switch statement to call the correct function for
  758. // the datas data types.
  759. #if (VTK_MAJOR_VERSION <= 5)
  760. void vtkImageConnectivity::ExecuteData(vtkDataObject *)
  761. {
  762. vtkImageData *inData = this->GetImageDataInput(0);
  763. vtkImageData *outData = this->GetOutput();
  764. outData->SetExtent(outData->GetWholeExtent());
  765. outData->AllocateScalars();
  766. int outExt[6], s;
  767. outData->GetWholeExtent(outExt);
  768. #else
  769. void vtkImageConnectivity::ExecuteDataWithInformation(vtkDataObject *output, vtkInformation* outInfo)
  770. {
  771. vtkImageData *inData = vtkImageData::SafeDownCast(this->GetInput());
  772. vtkImageData *outData = this->AllocateOutputData(output, outInfo);
  773. int outExt[6], s;
  774. outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), outExt);
  775. #endif
  776. void *inPtr = inData->GetScalarPointerForExtent(outExt);
  777. void *outPtr = outData->GetScalarPointerForExtent(outExt);
  778. int x1;
  779. x1 = inData->GetNumberOfScalarComponents();
  780. if (x1 != 1)
  781. {
  782. vtkErrorMacro(<<"Input has "<<x1<<" instead of 1 scalar component.");
  783. return;
  784. }
  785. /* Need short data */
  786. s = inData->GetScalarType();
  787. if (s != VTK_SHORT)
  788. {
  789. vtkErrorMacro("Warning: Input scalars are type "<<s
  790. << " instead of "<<VTK_SHORT);
  791. return;
  792. }
  793. vtkImageConnectivityExecute(this, inData, (short *)inPtr,
  794. outData, (short *)(outPtr), outExt);
  795. }
  796. //----------------------------------------------------------------------------
  797. void vtkImageConnectivity::PrintSelf(ostream& os, vtkIndent indent)
  798. {
  799. this->Superclass::PrintSelf(os,indent);
  800. os << indent << "Background: " << this->Background << "\n";
  801. os << indent << "MinForeground: " << this->MinForeground << "\n";
  802. os << indent << "MaxForeground: " << this->MaxForeground << "\n";
  803. os << indent << "LargestIslandSize: " << this->LargestIslandSize << "\n";
  804. os << indent << "IslandSize: " << this->IslandSize << "\n";
  805. os << indent << "MinSize: " << this->MinSize << "\n";
  806. os << indent << "OutputLabel: " << this->OutputLabel << "\n";
  807. os << indent << "Seed[0]: " << this->Seed[0] << "\n";
  808. os << indent << "Seed[1]: " << this->Seed[1] << "\n";
  809. os << indent << "Seed[2]: " << this->Seed[2] << "\n";
  810. os << indent << "Function: " << this->Function << "\n";
  811. }