TTK
Loading...
Searching...
No Matches
ttkCinemaDarkroomCompositing.cpp
Go to the documentation of this file.
2
3#include <vtkImageData.h>
4#include <vtkInformation.h>
5#include <vtkInformationVector.h>
6#include <vtkMultiBlockDataSet.h>
7#include <vtkObjectFactory.h>
8#include <vtkPointData.h>
9#include <vtkUnsignedCharArray.h>
10
11#include <ttkMacros.h>
12#include <ttkUtils.h>
13
15
17 this->setDebugMsgPrefix("CinemaDarkroomCompositing");
18
19 this->SetNumberOfInputPorts(1);
20 this->SetNumberOfOutputPorts(1);
21}
22
24
26 int port, vtkInformation *info) {
27 if(port == 0) {
28 info->Remove(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE());
29 info->Append(
30 vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkMultiBlockDataSet");
31 info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData");
32 info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1);
33 return 1;
34 }
35 return 0;
36}
37
38template <typename DT>
39int computeMask(unsigned char *mask,
40 const DT *depth0,
41 const DT *depth1,
42 const size_t nPixels) {
43 for(size_t i = 0; i < nPixels; i++) {
44 mask[i] = depth0[i] > depth1[i] ? 1 : 0;
45 }
46 return 1;
47};
48
49template <typename DT>
50int compositeArray(DT *array0,
51 const unsigned char *mask,
52 const DT *array1,
53 const size_t nPixels,
54 const size_t nComponents) {
55 for(size_t i = 0; i < nPixels; i++) {
56 if(mask[i] == 1) {
57 for(size_t j = i * nComponents, k = j + nComponents; j < k; j++)
58 array0[j] = array1[j];
59 }
60 }
61 return 1;
62};
63
65 vtkInformation *ttkNotUsed(request),
66 vtkInformationVector **inputVector,
67 vtkInformationVector *outputVector) {
68
69 const size_t nInputs = inputVector[0]->GetNumberOfInformationObjects();
70
73
74 if(nInputs < 1) {
75 this->printWrn("Empty Input");
76 return 1;
77 }
78
79 auto firstInput = vtkDataObject::GetData(inputVector[0], 0);
80
81 if(firstInput->IsA("vtkImageData")) {
82 // if input are repeated vtkImageData objects
83 for(size_t i = 0; i < nInputs; i++) {
85 auto image = vtkImageData::GetData(inputVector[0], i);
86 if(!image) {
87 this->printErr("Input is not a list of vtkImageData objects.");
88 return 0;
89 }
90 collection->SetBlock(0, image);
91 inputAsMB->SetBlock(i, collection);
92 }
93 } else if(nInputs == 1 && firstInput->IsA("vtkMultiBlockDataSet")) {
94 // if input is a single list of vtkImageData objects
95 auto temp = vtkMultiBlockDataSet::SafeDownCast(firstInput);
96 auto nBlocks = temp->GetNumberOfBlocks();
97
98 if(nBlocks > 0) {
99 if(vtkMultiBlockDataSet::SafeDownCast(temp->GetBlock(0))) {
100 inputAsMB->ShallowCopy(firstInput);
101 } else {
102 // check if all blocks are images
103 for(size_t i = 0; i < nBlocks; i++) {
105 auto image = vtkImageData::SafeDownCast(temp->GetBlock(i));
106 if(!image) {
107 this->printErr(
108 "Input is not a single list of vtkImageData objects.");
109 return 0;
110 }
111 collection->SetBlock(0, image);
112 inputAsMB->SetBlock(i, collection);
113 }
114 }
115 }
116 } else if(firstInput->IsA("vtkMultiBlockDataSet")) {
117 // inputs are multiple lists of vtkImageData objects
118 for(size_t i = 0; i < nInputs; i++) {
119 auto list = vtkMultiBlockDataSet::GetData(inputVector[0], i);
120 if(!list) {
121 this->printErr(
122 "Inputs are not multiple lists of vtkImageData objects.");
123 return 0;
124 }
125 inputAsMB->SetBlock(i, list);
126 }
127 } else {
128 this->printErr("Unsupported input data structure.");
129 return 0;
130 }
131
132 const size_t nImagesPerCompositingStep = inputAsMB->GetNumberOfBlocks();
133 const size_t nCompositingSteps
134 = vtkMultiBlockDataSet::SafeDownCast(inputAsMB->GetBlock(0))
135 ->GetNumberOfBlocks();
136
137 ttk::Timer timer;
138 this->printMsg("Compositing " + std::to_string(nCompositingSteps) + "x"
139 + std::to_string(nImagesPerCompositingStep) + " Images",
141
142 auto getImage = [](vtkMultiBlockDataSet *root, int i, int j) {
143 return (vtkImageData *)((vtkMultiBlockDataSet *)root->GetBlock(i))
144 ->GetBlock(j);
145 };
146
147 for(size_t i = 0; i < nCompositingSteps; i++) {
148
149 auto firstImage = getImage(inputAsMB, 0, i);
150
152 output->DeepCopy(firstImage);
153
154 for(size_t j = 1; j < nImagesPerCompositingStep; j++) {
155 auto image = getImage(inputAsMB, j, i);
156 if(!image) {
157 this->printErr("Unsupported input data structure.");
158 return 0;
159 }
160
161 // get depth arrays
162 auto depth0Array = this->GetInputArrayToProcess(0, output);
163 auto depth1Array = this->GetInputArrayToProcess(0, image);
164 if(!depth0Array || !depth1Array) {
165 this->printErr("Unable to retrieve depth arrays.");
166 return 0;
167 }
168
169 const size_t nPixels = depth0Array->GetNumberOfTuples();
170
171 // compute mask
173 mask->SetNumberOfTuples(nPixels);
174 switch(depth0Array->GetDataType()) {
175 vtkTemplateMacro(computeMask<VTK_TT>(
176 static_cast<unsigned char *>(ttkUtils::GetVoidPointer(mask)),
177 static_cast<VTK_TT *>(ttkUtils::GetVoidPointer(depth0Array)),
178 static_cast<VTK_TT *>(ttkUtils::GetVoidPointer(depth1Array)),
179 nPixels));
180 }
181
182 auto outputPD = output->GetPointData();
183 auto inputPD = image->GetPointData();
184
185 for(int a = 0; a < outputPD->GetNumberOfArrays(); a++) {
186 auto outputArray = outputPD->GetArray(a);
187 if(!outputArray)
188 continue;
189 auto inputArray = inputPD->GetArray(outputArray->GetName());
190 if(!inputArray)
191 continue;
192
193 switch(outputArray->GetDataType()) {
194 vtkTemplateMacro(compositeArray<VTK_TT>(
195 static_cast<VTK_TT *>(ttkUtils::GetVoidPointer(outputArray)),
196 static_cast<unsigned char *>(ttkUtils::GetVoidPointer(mask)),
197 static_cast<VTK_TT *>(ttkUtils::GetVoidPointer(inputArray)),
198 nPixels, outputArray->GetNumberOfComponents()));
199 }
200 }
201 }
202
203 outputAsMB->SetBlock(i, output);
204
205 // perform compositing
206 this->printMsg("Compositing " + std::to_string(nCompositingSteps) + "x"
207 + std::to_string(nImagesPerCompositingStep) + " Images",
208 (float)(i + 1) / (float)nInputs, timer.getElapsedTime(),
209 this->threadNumber_, ttk::debug::LineMode::REPLACE);
210 }
211
212 this->printMsg("Compositing " + std::to_string(nCompositingSteps) + "x"
213 + std::to_string(nImagesPerCompositingStep) + " Images",
214 1, timer.getElapsedTime(), this->threadNumber_);
215
216 auto output = vtkDataObject::GetData(outputVector);
217 if(firstInput->IsA("vtkImageData")) {
218 output->ShallowCopy(outputAsMB->GetBlock(0));
219 } else {
220 output->ShallowCopy(outputAsMB);
221 }
222
223 return 1;
224}
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition BaseClass.h:47
Composites multiple vtkImageData objects base on depth values.
~ttkCinemaDarkroomCompositing() override
int FillInputPortInformation(int port, vtkInformation *info) override
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
static void * GetVoidPointer(vtkDataArray *array, vtkIdType start=0)
Definition ttkUtils.cpp:226
int printWrn(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:159
void setDebugMsgPrefix(const std::string &prefix)
Definition Debug.h:364
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:149
double getElapsedTime()
Definition Timer.h:15
vtkStandardNewMacro(ttkCinemaDarkroomCompositing)
int computeMask(unsigned char *mask, const DT *depth0, const DT *depth1, const size_t nPixels)
int compositeArray(DT *array0, const unsigned char *mask, const DT *array1, const size_t nPixels, const size_t nComponents)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)