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