Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkIGTLMessageToUSImageFilter.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found 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 
78 template <typename TPixel>
79 void 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);
119  vtkSmartPointer<vtkMatrix4x4> vtkMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
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 }
void ConnectTo(mitk::IGTLMessageSource *UpstreamFilter)
Connects the input of this filter to the outputs of the given IGTLMessageSource.
itk::Image< unsigned char, 3 > ImageType
#define MITK_DEBUG
Definition: mitkLogMacros.h:22
virtual bool IsDataValid() const
returns true if the object contains valid data
void GetNextRawImage(std::vector< mitk::Image::Pointer > &imgVector) override
Copies the data from the next OIGTL message to an mitk::Image.
void SetNumberOfExpectedOutputs(unsigned int numOutputs)
Sets the number of expected outputs.
IGTLMessage * GetOutput(void)
return the output (output with id 0) of the filter
A wrapper for the OpenIGTLink message type.
#define mitkThrow()
const char * GetIGTLMessageType() const
OpenIGTLink message source.
static Pointer New()
virtual igtl::MessageBase::Pointer GetMessage() const
returns the OpenIGTLink message
static bool in(Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4)
Definition: jsoncpp.cpp:244