MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
mitkIGTLMessageToUSImageFilter.cpp
Go to the documentation of this file.
1/*============================================================================
2
3The Medical Imaging Interaction Toolkit (MITK)
4
5Copyright (c) German Cancer Research Center (DKFZ)
6All rights reserved.
7
8Use of this source code is governed by a 3-clause BSD license that can be
9found in the LICENSE file.
10
11============================================================================*/
12
14#include <igtlImageMessage.h>
15#include <itkByteSwapper.h>
16
17#include <vtkSmartPointer.h>
18
20 std::vector<mitk::Image::Pointer>& imgVector)
21{
22 if (imgVector.size() != 1)
23 imgVector.resize(1);
24
25 mitk::Image::Pointer& img = imgVector[0];
26 m_upstream->Update();
27
28 mitk::IGTLMessage* msg = m_upstream->GetOutput();
29
30 if (msg != nullptr && (!msg->IsDataValid() || std::strcmp(msg->GetIGTLMessageType(), "IMAGE") != 0))
31 {
32 img = m_previousImage;
33 return;
34 }
35
36 igtl::MessageBase::Pointer msgBase = msg->GetMessage();
37 igtl::ImageMessage* imgMsg = (igtl::ImageMessage*)(msgBase.GetPointer());
38
39 bool big_endian = (imgMsg->GetEndian() == igtl::ImageMessage::ENDIAN_BIG);
40
41 if (imgMsg->GetCoordinateSystem() != igtl::ImageMessage::COORDINATE_RAS)
42 {
43 // TODO: Which coordinate system does MITK use?
44 mitkThrow() << "Can not handle messages with LPS coordinate system";
45 }
46
47 switch (imgMsg->GetScalarType())
48 {
49 case igtl::ImageMessage::TYPE_UINT8:
50 Initiate<unsigned char>(img, imgMsg, big_endian);
51 break;
52 case igtl::ImageMessage::TYPE_INT8:
53 Initiate<char>(img, imgMsg, big_endian);
54 break;
55 case igtl::ImageMessage::TYPE_UINT16:
56 Initiate<unsigned short>(img, imgMsg, big_endian);
57 break;
58 case igtl::ImageMessage::TYPE_INT16:
59 Initiate<short>(img, imgMsg, big_endian);
60 break;
61 case igtl::ImageMessage::TYPE_UINT32:
62 Initiate<unsigned int>(img, imgMsg, big_endian);
63 break;
64 case igtl::ImageMessage::TYPE_INT32:
65 Initiate<int>(img, imgMsg, big_endian);
66 break;
67 case igtl::ImageMessage::TYPE_FLOAT32:
68 Initiate<float>(img, imgMsg, big_endian);
69 break;
70 case igtl::ImageMessage::TYPE_FLOAT64:
71 Initiate<double>(img, imgMsg, big_endian);
72 break;
73 default:
74 mitkThrow() << "Incompatible PixelType " << imgMsg;
75 }
76}
77
78template <typename TPixel>
79void mitk::IGTLMessageToUSImageFilter::Initiate(mitk::Image::Pointer& img,
80 igtl::ImageMessage* msg,
81 bool big_endian)
82{
83 typedef itk::Image<TPixel, 3> ImageType;
84
85 typename ImageType::Pointer output = ImageType::New();
86 typename ImageType::RegionType region;
87 typename ImageType::RegionType::SizeType size;
88 typename ImageType::RegionType::IndexType index;
89 typename ImageType::SpacingType spacing;
90 typename ImageType::PointType origin;
91
92 // Copy dimensions
93 int dims[3];
94 msg->GetDimensions(dims);
95 size_t num_pixel = 1;
96 for (size_t i = 0; i < 3; i++)
97 {
98 size[i] = dims[i];
99 num_pixel *= dims[i];
100 }
101
102 // Handle subvolume information. We want the subvolume to be the whole image
103 // for now.
104 int sdims[3], offs[3];
105 msg->GetSubVolume(sdims, offs);
106 for (size_t i = 0; i < 3; i++)
107 {
108 if (offs[i] != 0 || sdims[i] != dims[i])
109 {
110 // TODO: Handle messages with smaller subvolume than whole image
111 throw("Can not handle message with smaller subvolume than whole image");
112 }
113 }
114
115 index.Fill(0);
116
117 float matF[4][4];
118 msg->GetMatrix(matF);
120
121 for (size_t i = 0; i < 4; ++i)
122 for (size_t j = 0; j < 4; ++j)
123 vtkMatrix->SetElement(i, j, matF[i][j]);
124
125 float spacingMsg[3];
126
127 msg->GetSpacing(spacingMsg);
128
129 for (int i = 0; i < 3; ++i)
130 spacing[i] = spacingMsg[i];
131
132 region.SetSize(size);
133 region.SetIndex(index);
134 output->SetRegions(region);
135 output->SetSpacing(spacing);
136 output->Allocate();
137
138 TPixel* in = (TPixel*)msg->GetScalarPointer();
139 TPixel* out = (TPixel*)output->GetBufferPointer();
140 memcpy(out, in, num_pixel * sizeof(TPixel));
141 if (big_endian)
142 {
143 // Even though this method is called "FromSystemToBigEndian", it also swaps
144 // "FromBigEndianToSystem".
145 // This makes sense, but might be confusing at first glance.
146 itk::ByteSwapper<TPixel>::SwapRangeFromSystemToBigEndian(out, num_pixel);
147 }
148 else
149 {
150 itk::ByteSwapper<TPixel>::SwapRangeFromSystemToLittleEndian(out, num_pixel);
151 }
152
153 img = mitk::Image::New();
154 img->InitializeByItk(output.GetPointer());
155 img->SetVolume(output->GetBufferPointer());
156 //img->GetGeometry()->SetIndexToWorldTransformByVtkMatrix(vtkMatrix);
157 m_previousImage = img;
158
159 float iorigin[3];
160 msg->GetOrigin(iorigin);
161 for (size_t i = 0; i < 3; i++)
162 {
163 origin[i] = iorigin[i];
164 }
165 output->SetOrigin(origin);
166}
167
169 : m_upstream(nullptr)
170{
171 MITK_DEBUG << "Instantiated this (" << this << ") mitkIGTMessageToUSImageFilter\n";
172}
173
175 unsigned int numOutputs)
176{
177 if (numOutputs > 1)
178 {
179 throw("Can only have 1 output for IGTLMessageToUSImageFilter.");
180 }
181}
182
184 mitk::IGTLMessageSource* UpstreamFilter)
185{
186 MITK_DEBUG << "Connected this (" << this << ") mitkIGTLMessageToUSImageFilter to MessageSource (" << UpstreamFilter << ")\n";
187 m_upstream = UpstreamFilter;
188}
itk::Image< int, 3 > ImageType
OpenIGTLink message source.
IGTLMessage * GetOutput(void)
return the output (output with id 0) of the filter
void GetNextRawImage(std::vector< mitk::Image::Pointer > &imgVector) override
Copies the data from the next OIGTL message to an mitk::Image.
void ConnectTo(mitk::IGTLMessageSource *UpstreamFilter)
Connects the input of this filter to the outputs of the given IGTLMessageSource.
void SetNumberOfExpectedOutputs(unsigned int numOutputs)
Sets the number of expected outputs.
A wrapper for the OpenIGTLink message type.
virtual bool IsDataValid() const
returns true if the object contains valid data
const char * GetIGTLMessageType() const
IGTLMessageType * GetMessage() const