1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkImageAppendComponents.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 "vtkImageAppendComponents.h"
16 
17 #include "vtkAlgorithmOutput.h"
18 #include "vtkDataSetAttributes.h"
19 #include "vtkImageData.h"
20 #include "vtkImageProgressIterator.h"
21 #include "vtkInformation.h"
22 #include "vtkInformationVector.h"
23 #include "vtkObjectFactory.h"
24 #include "vtkStreamingDemandDrivenPipeline.h"
25 
26 vtkStandardNewMacro(vtkImageAppendComponents);
27 
28 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)29 void vtkImageAppendComponents::PrintSelf(ostream& os, vtkIndent indent)
30 {
31   this->Superclass::PrintSelf(os, indent);
32 }
33 
34 //------------------------------------------------------------------------------
ReplaceNthInputConnection(int idx,vtkAlgorithmOutput * input)35 void vtkImageAppendComponents::ReplaceNthInputConnection(int idx, vtkAlgorithmOutput* input)
36 {
37   if (idx < 0 || idx >= this->GetNumberOfInputConnections(0))
38   {
39     vtkErrorMacro("Attempt to replace connection idx "
40       << idx << " of input port " << 0 << ", which has only "
41       << this->GetNumberOfInputConnections(0) << " connections.");
42     return;
43   }
44 
45   if (!input || !input->GetProducer())
46   {
47     vtkErrorMacro("Attempt to replace connection index "
48       << idx << " for input port " << 0 << " with "
49       << (!input ? "a null input." : "an input with no producer."));
50     return;
51   }
52 
53   this->SetNthInputConnection(0, idx, input);
54 }
55 
56 //------------------------------------------------------------------------------
57 // The default vtkImageAlgorithm semantics are that SetInput() puts
58 // each input on a different port, we want all the image inputs to
59 // go on the first port.
SetInputData(int idx,vtkDataObject * input)60 void vtkImageAppendComponents::SetInputData(int idx, vtkDataObject* input)
61 {
62   this->SetInputDataInternal(idx, input);
63 }
64 
65 //------------------------------------------------------------------------------
GetInput(int idx)66 vtkDataObject* vtkImageAppendComponents::GetInput(int idx)
67 {
68   if (this->GetNumberOfInputConnections(0) <= idx)
69   {
70     return nullptr;
71   }
72   return vtkImageData::SafeDownCast(this->GetExecutive()->GetInputData(0, idx));
73 }
74 
75 //------------------------------------------------------------------------------
76 // This method tells the output it will have more components
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)77 int vtkImageAppendComponents::RequestInformation(vtkInformation* vtkNotUsed(request),
78   vtkInformationVector** inputVector, vtkInformationVector* outputVector)
79 {
80   // get the info objects
81   vtkInformation* outInfo = outputVector->GetInformationObject(0);
82   vtkInformation* inScalarInfo;
83 
84   int idx1, num;
85   num = 0;
86   for (idx1 = 0; idx1 < this->GetNumberOfInputConnections(0); ++idx1)
87   {
88     inScalarInfo =
89       vtkDataObject::GetActiveFieldInformation(inputVector[0]->GetInformationObject(idx1),
90         vtkDataObject::FIELD_ASSOCIATION_POINTS, vtkDataSetAttributes::SCALARS);
91     if (inScalarInfo && inScalarInfo->Has(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS()))
92     {
93       num += inScalarInfo->Get(vtkDataObject::FIELD_NUMBER_OF_COMPONENTS());
94     }
95   }
96 
97   vtkDataObject::SetPointDataActiveScalarInfo(outInfo, -1, num);
98   return 1;
99 }
100 
101 //------------------------------------------------------------------------------
102 // This templated function executes the filter for any type of data.
103 template <class T>
vtkImageAppendComponentsExecute(vtkImageAppendComponents * self,vtkImageData * inData,vtkImageData * outData,int outComp,int outExt[6],int id,T *)104 void vtkImageAppendComponentsExecute(vtkImageAppendComponents* self, vtkImageData* inData,
105   vtkImageData* outData, int outComp, int outExt[6], int id, T*)
106 {
107   vtkImageIterator<T> inIt(inData, outExt);
108   vtkImageProgressIterator<T> outIt(outData, outExt, self, id);
109   int numIn = inData->GetNumberOfScalarComponents();
110   int numSkip = outData->GetNumberOfScalarComponents() - numIn;
111   int i;
112 
113   // Loop through output pixels
114   while (!outIt.IsAtEnd())
115   {
116     T* inSI = inIt.BeginSpan();
117     T* outSI = outIt.BeginSpan() + outComp;
118     T* outSIEnd = outIt.EndSpan();
119     while (outSI < outSIEnd)
120     {
121       // now process the components
122       for (i = 0; i < numIn; ++i)
123       {
124         *outSI = *inSI;
125         ++outSI;
126         ++inSI;
127       }
128       outSI = outSI + numSkip;
129     }
130     inIt.NextSpan();
131     outIt.NextSpan();
132   }
133 }
134 
135 //------------------------------------------------------------------------------
FillInputPortInformation(int i,vtkInformation * info)136 int vtkImageAppendComponents::FillInputPortInformation(int i, vtkInformation* info)
137 {
138   info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1);
139   return this->Superclass::FillInputPortInformation(i, info);
140 }
141 
142 //------------------------------------------------------------------------------
143 // This method is passed a input and output regions, and executes the filter
144 // algorithm to fill the output from the inputs.
145 // It just executes a switch statement to call the correct function for
146 // the regions data types.
ThreadedRequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * vtkNotUsed (outputVector),vtkImageData *** inData,vtkImageData ** outData,int outExt[6],int id)147 void vtkImageAppendComponents::ThreadedRequestData(vtkInformation* vtkNotUsed(request),
148   vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* vtkNotUsed(outputVector),
149   vtkImageData*** inData, vtkImageData** outData, int outExt[6], int id)
150 {
151   int idx1, outComp;
152 
153   outComp = 0;
154   for (idx1 = 0; idx1 < this->GetNumberOfInputConnections(0); ++idx1)
155   {
156     if (inData[0][idx1] != nullptr)
157     {
158       // this filter expects that input is the same type as output.
159       if (inData[0][idx1]->GetScalarType() != outData[0]->GetScalarType())
160       {
161         vtkErrorMacro(<< "Execute: input" << idx1 << " ScalarType ("
162                       << inData[0][idx1]->GetScalarType() << "), must match output ScalarType ("
163                       << outData[0]->GetScalarType() << ")");
164         return;
165       }
166       switch (inData[0][idx1]->GetScalarType())
167       {
168         vtkTemplateMacro(vtkImageAppendComponentsExecute(
169           this, inData[0][idx1], outData[0], outComp, outExt, id, static_cast<VTK_TT*>(nullptr)));
170         default:
171           vtkErrorMacro(<< "Execute: Unknown ScalarType");
172           return;
173       }
174       outComp += inData[0][idx1]->GetNumberOfScalarComponents();
175     }
176   }
177 }
178