CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxSlicedImageProxy.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 
13 #include "cxSlicedImageProxy.h"
14 
15 #include <vtkImageReslice.h>
16 #include <vtkImageMapToWindowLevelColors.h>
17 #include <vtkWindowLevelLookupTable.h>
18 #include <vtkImageData.h>
19 #include <vtkMatrix4x4.h>
20 #include <vtkImageAlgorithm.h>
21 #include <vtkImageChangeInformation.h>
22 #include <vtkImageExtractComponents.h>
23 #include <vtkImageAppendComponents.h>
24 
25 #include "cxImage.h"
26 #include "cxSliceProxy.h"
27 #include "cxImageLUT2D.h"
28 #include "cxTypeConversions.h"
29 
30 
31 namespace cx
32 {
33 
34 
36 {
37  mDummyImage = Image::createDummyImageData(1, 0);
38 
39  mRedirecter = vtkSmartPointer<vtkImageChangeInformation>::New(); // used for forwarding only.
40  mRedirecter->SetInputData(mDummyImage);
41 }
42 
44 {
45 
46 }
47 
49 {
50  vtkImageChangeInformationPtr redirecter = vtkImageChangeInformationPtr::New();
51  redirecter->SetInputData(image);
52  redirecter->Update();
53  this->setInput(redirecter, lut);
54 }
55 
57 {
58  input->Update();
59 
60  if (input->GetOutput())
61  {
62  int numScalarComponents = input->GetOutput()->GetNumberOfScalarComponents();
63  if ( numScalarComponents >= 3) // color
64  {
65  // split the image into the components, apply the lut, then merge.
66 
67  vtkImageAppendComponentsPtr merger = vtkImageAppendComponentsPtr::New();
68 
69  for (int i = 0; i < numScalarComponents; ++i)
70  {
71  vtkImageMapToColorsPtr compWindowLevel = vtkImageMapToColorsPtr::New();
72  compWindowLevel->SetInputConnection(input->GetOutputPort());
73  compWindowLevel->SetActiveComponent(i);
74  compWindowLevel->SetLookupTable(lut);
75 
76  if (i==2 && numScalarComponents==3)
77  {
78  compWindowLevel->SetOutputFormatToLuminanceAlpha();
79  }
80  else
81  {
82  compWindowLevel->SetOutputFormatToLuminance();
83  }
84 
85  merger->AddInputConnection(compWindowLevel->GetOutputPort());
86  }
87 
88  mRedirecter->SetInputConnection(merger->GetOutputPort());
89  }
90  else // grayscale
91  {
92  vtkImageMapToColorsPtr windowLevel = vtkImageMapToColorsPtr::New();
93  windowLevel->SetOutputFormatToRGBA();
94  windowLevel->SetInputConnection(input->GetOutputPort());
95  windowLevel->SetLookupTable(lut);
96  mRedirecter->SetInputConnection(windowLevel->GetOutputPort());
97  }
98  }
99  else // no image
100  {
101  mRedirecter->SetInputData(mDummyImage);
102  }
103 
104  mRedirecter->Update();
105 }
106 
108 {
109  return mRedirecter;
110 }
111 
113 {
114  return mRedirecter->GetOutput();
115 }
116 
121 
122 
124 {
125  mMatrixAxes = vtkMatrix4x4Ptr::New();
126 
127  mReslicer = vtkImageReslicePtr::New();
128  mReslicer->SetInterpolationModeToLinear();
129  mReslicer->SetOutputDimensionality(2);
130  mReslicer->SetResliceAxes(mMatrixAxes);
131  //mReslicer->SetAutoCropOutput(false); //faster update rate
132  mReslicer->AutoCropOutputOn(); // fix used in 2.0.9, but slower update rate
133 
134  mImageWithLUTProxy.reset(new ApplyLUTToImage2DProxy());
135 
136  mRedirecter = vtkImageChangeInformationPtr::New();
137 }
138 
140 {
141 }
142 
143 void SlicedImageProxy::setOutputFormat(Vector3D origin, Eigen::Array3i dim, Vector3D spacing)
144 {
145  mReslicer->SetOutputOrigin(origin.data());
146  mReslicer->SetOutputExtent(0, dim[0], 0, dim[1], 0, 0);
147  // this looks like the correct way, but gives incorrect output (the way it is used)
148  // TODO investigate
149 // mReslicer->SetOutputExtent(0, dim[0]-1, 0, dim[1]-1, 0, 0);
150  mReslicer->SetOutputSpacing(spacing.data());
151 }
152 
154 {
155  if (mSlicer)
156  {
157  disconnect(mSlicer.get(), SIGNAL(transformChanged(Transform3D)), this, SLOT(transformChangedSlot()));
158  }
159  mSlicer = slicer;
160  if (mSlicer)
161  {
162  connect(mSlicer.get(), SIGNAL(transformChanged(Transform3D)), this, SLOT(transformChangedSlot()));
163  update();
164  }
165 }
166 
167 void SlicedImageProxy::transferFunctionsChangedSlot()
168 {
169  mReslicer->SetInputData(mImage->getBaseVtkImageData());
170  mReslicer->SetBackgroundLevel(mImage->getMin());
171  mImageWithLUTProxy->setInput(mRedirecter, mImage->getLookupTable2D()->getOutputLookupTable());
172 }
173 
174 void SlicedImageProxy::updateRedirecterSlot()
175 {
176  mRedirecter->SetInputConnection(mReslicer->GetOutputPort());
177  update();
178 }
179 
181 {
182  if (mImage)
183  {
184  disconnect(mImage.get(), SIGNAL(transferFunctionsChanged()), this, SLOT(transferFunctionsChangedSlot()));
185  disconnect(mImage.get(), SIGNAL(transformChanged()), this, SLOT(transformChangedSlot()));
186  disconnect(mImage.get(), SIGNAL(vtkImageDataChanged()), this, SLOT(updateRedirecterSlot()));
187  }
188 
189  mImage = image;
190 
191  if (mImage)
192  {
193  connect(mImage.get(), SIGNAL(transferFunctionsChanged()), this, SLOT(transferFunctionsChangedSlot()));
194  connect(mImage.get(), SIGNAL(transformChanged()), this, SLOT(transformChangedSlot()));
195  connect(mImage.get(), SIGNAL(vtkImageDataChanged()), this, SLOT(updateRedirecterSlot()));
196  }
197 
198  if (mImage)
199  {
200  this->updateRedirecterSlot();
201  this->transferFunctionsChangedSlot();
202  }
203  else // no image
204  {
205  mImageWithLUTProxy->setInput(vtkImageAlgorithmPtr(), vtkLookupTablePtr());
206  }
207 
208  this->update();
209 }
210 
212 {
213  return mImage;
214 }
215 
217 {
218  return mImageWithLUTProxy->getOutput();
219 }
220 
222 {
223  return mImageWithLUTProxy->getOutputPort();
224 }
225 
227 {
228  return mRedirecter->GetOutput();
229 }
230 
232 {
233  return mRedirecter;
234 }
235 
237 {
238  if (!mImage)
239  return;
240 
241  Transform3D rMs = Transform3D::Identity();
242  if (mSlicer)
243  rMs = mSlicer->get_sMr().inv();
244  Transform3D iMr = mImage->get_rMd().inv();
245  Transform3D M = iMr * rMs;
246 
247  mMatrixAxes->DeepCopy(M.getVtkMatrix());
248 }
249 
250 void SlicedImageProxy::transformChangedSlot()
251 {
252  update();
253 }
254 
255 void SlicedImageProxy::printSelf(std::ostream & os, Indent indent)
256 {
257  //os << indent << "PlaneType: " << mType << std::endl;
258  os << indent << "mImage: " << (mImage ? mImage->getUid() : "NULL") << std::endl;
259  os << indent << "mSlicer: " << (mSlicer ? mSlicer.get() : 0) << std::endl;
260  if (mSlicer)
261  {
262  mSlicer->printSelf(os, indent.stepDown());
263  }
264  os << indent << "mReslicer->GetOutput(): " << mReslicer->GetOutput() << std::endl;
265  os << indent << "mReslicer->GetInput() : " << mReslicer->GetInput() << std::endl;
266  Transform3D test(mReslicer->GetResliceAxes());
267  os << indent << "resliceaxes: " << std::endl;
268  test.put(os, indent.getIndent() + 3);
269  os << std::endl;
270  //os << indent << "rMs_debug: " << std::endl;
271  //rMs_debug.put(os, indent.getIndent()+3);
272 
273 }
274 
275 //---------------------------------------------------------
276 }//end namespace
277 //---------------------------------------------------------
static vtkImageDataPtr createDummyImageData(int axisSize, int maxVoxelValue)
Create a moc object of vtkImageData.
Definition: cxImage.cpp:827
int getIndent() const
Definition: cxIndent.cpp:23
vtkImageDataPtr getOutput()
output 2D sliced image
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:27
void setOutputFormat(Vector3D origin, Eigen::Array3i dim, Vector3D spacing)
vtkSmartPointer< vtkImageChangeInformation > vtkImageChangeInformationPtr
Definition: cxImage.cpp:46
vtkImageAlgorithmPtr getOutputPort()
output 2D sliced image
void printSelf(std::ostream &os, Indent indent)
vtkImageAlgorithmPtr getOutputPortWithoutLUT()
vtkSmartPointer< class vtkImageMapToColors > vtkImageMapToColorsPtr
ImagePtr getImage() const
vtkSmartPointer< class vtkImageAlgorithm > vtkImageAlgorithmPtr
vtkSmartPointer< class vtkImageAppendComponents > vtkImageAppendComponentsPtr
void setInput(vtkImageAlgorithmPtr input, vtkLookupTablePtr lut)
Formatting class for debug printing of the ssc library.
Definition: cxIndent.h:28
void setSliceProxy(SliceProxyInterfacePtr slicer)
vtkSmartPointer< class vtkLookupTable > vtkLookupTablePtr
void setImage(ImagePtr image)
Indent stepDown() const
Definition: cxIndent.cpp:27
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:42
vtkImageAlgorithmPtr getOutputPort()
output 2D sliced image
vtkImageDataPtr getOutputWithoutLUT()
vtkSmartPointer< class vtkImageData > vtkImageDataPtr
boost::shared_ptr< class SliceProxyInterface > SliceProxyInterfacePtr
void setInputData(vtkImageDataPtr image, vtkLookupTablePtr lut)
Namespace for all CustusX production code.