1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkImageConnector.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkImageConnector.h"
16 
17 #include "vtkImageData.h"
18 #include "vtkObjectFactory.h"
19 
20 vtkStandardNewMacro(vtkImageConnector);
21 
22 //------------------------------------------------------------------------------
vtkImageConnector()23 vtkImageConnector::vtkImageConnector()
24 {
25   this->Seeds = nullptr;
26   this->LastSeed = nullptr;
27   this->ConnectedValue = 255;
28   this->UnconnectedValue = 128;
29 }
30 
31 //------------------------------------------------------------------------------
~vtkImageConnector()32 vtkImageConnector::~vtkImageConnector()
33 {
34   this->RemoveAllSeeds();
35 }
36 
37 //------------------------------------------------------------------------------
RemoveAllSeeds()38 void vtkImageConnector::RemoveAllSeeds()
39 {
40   vtkImageConnectorSeed* temp;
41 
42   while (this->Seeds)
43   {
44     temp = this->Seeds;
45     this->Seeds = temp->Next;
46     delete temp;
47   }
48   this->LastSeed = nullptr;
49 }
50 
51 //------------------------------------------------------------------------------
NewSeed(int index[3],void * ptr)52 vtkImageConnectorSeed* vtkImageConnector::NewSeed(int index[3], void* ptr)
53 {
54   vtkImageConnectorSeed* seed = vtkImageConnectorSeed::New();
55   int idx;
56 
57   for (idx = 0; idx < 3; ++idx)
58   {
59     seed->Index[idx] = index[idx];
60   }
61   seed->Pointer = ptr;
62   seed->Next = nullptr;
63 
64   return seed;
65 }
66 
67 //------------------------------------------------------------------------------
68 // Add a new seed to the end of the seed list.
AddSeedToEnd(vtkImageConnectorSeed * seed)69 void vtkImageConnector::AddSeedToEnd(vtkImageConnectorSeed* seed)
70 {
71   // Add the seed to the end of the list
72   if (this->LastSeed == nullptr)
73   { // no seeds yet
74     this->LastSeed = this->Seeds = seed;
75   }
76   else
77   {
78     this->LastSeed->Next = seed;
79     this->LastSeed = seed;
80   }
81 }
82 
83 //------------------------------------------------------------------------------
84 // Add a new seed to the start of the seed list.
AddSeed(vtkImageConnectorSeed * seed)85 void vtkImageConnector::AddSeed(vtkImageConnectorSeed* seed)
86 {
87   seed->Next = this->Seeds;
88   this->Seeds = seed;
89   if (!this->LastSeed)
90   {
91     this->LastSeed = seed;
92   }
93 }
94 
95 //------------------------------------------------------------------------------
96 // Removes a seed from the start of the seed list, and returns the seed.
PopSeed()97 vtkImageConnectorSeed* vtkImageConnector::PopSeed()
98 {
99   vtkImageConnectorSeed* seed;
100 
101   seed = this->Seeds;
102   this->Seeds = seed->Next;
103   if (this->Seeds == nullptr)
104   {
105     this->LastSeed = nullptr;
106   }
107   return seed;
108 }
109 
110 //------------------------------------------------------------------------------
111 // Input a data of 0's and "UnconnectedValue"s. Seeds of this object are
112 // used to find connected pixels.
113 // All pixels connected to seeds are set to ConnectedValue.
114 // The data has to be unsigned char.
MarkData(vtkImageData * data,int numberOfAxes,int extent[6])115 void vtkImageConnector::MarkData(vtkImageData* data, int numberOfAxes, int extent[6])
116 {
117   vtkIdType incs[3], *pIncs;
118   int* pExtent;
119   vtkImageConnectorSeed* seed;
120   unsigned char* ptr;
121   int newIndex[3], *pIndex, idx;
122   long count = 0;
123 
124   data->GetIncrements(incs);
125   while (this->Seeds)
126   {
127     ++count;
128     seed = this->PopSeed();
129     // just in case the seed has not been marked visited.
130     *(static_cast<unsigned char*>(seed->Pointer)) = this->ConnectedValue;
131     // Add neighbors
132     newIndex[0] = seed->Index[0];
133     newIndex[1] = seed->Index[1];
134     newIndex[2] = seed->Index[2];
135     pExtent = extent;
136     pIncs = incs;
137     pIndex = newIndex;
138     for (idx = 0; idx < numberOfAxes; ++idx)
139     {
140       // check pixel below
141       if (*pExtent < *pIndex)
142       {
143         ptr = static_cast<unsigned char*>(seed->Pointer) - *pIncs;
144         if (*ptr == this->UnconnectedValue)
145         { // add a new seed
146           --(*pIndex);
147           *ptr = this->ConnectedValue;
148           this->AddSeedToEnd(this->NewSeed(newIndex, ptr));
149           ++(*pIndex);
150         }
151       }
152       ++pExtent;
153       // check above pixel
154       if (*pExtent > *pIndex)
155       {
156         ptr = static_cast<unsigned char*>(seed->Pointer) + *pIncs;
157         if (*ptr == this->UnconnectedValue)
158         { // add a new seed
159           ++(*pIndex);
160           *ptr = this->ConnectedValue;
161           this->AddSeedToEnd(this->NewSeed(newIndex, ptr));
162           --(*pIndex);
163         }
164       }
165       ++pExtent;
166       // move to next axis
167       ++pIncs;
168       ++pIndex;
169     }
170 
171     // Delete seed
172     delete seed;
173   }
174   vtkDebugMacro("Marked " << count << " pixels");
175 }
176 
PrintSelf(ostream & os,vtkIndent indent)177 void vtkImageConnector::PrintSelf(ostream& os, vtkIndent indent)
178 {
179   this->Superclass::PrintSelf(os, indent);
180 
181   os << indent << "ConnectedValue: " << this->ConnectedValue << "\n";
182   os << indent << "UnconnectedValue: " << this->UnconnectedValue << "\n";
183 }
184