Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
18 #include <igtlImageMessage.h>
19 #include <itkByteSwapper.h>
20 
23 {
24  m_upstream->Update();
25 
26  mitk::IGTLMessage* msg = m_upstream->GetOutput();
27 
28  if (msg != nullptr && (!msg->IsDataValid() || std::strcmp(msg->GetIGTLMessageType(), "IMAGE") != 0))
29  {
30  img = m_previousImage;
31  return;
32  }
33 
34  igtl::MessageBase::Pointer msgBase = msg->GetMessage();
35  igtl::ImageMessage* imgMsg = (igtl::ImageMessage*)(msgBase.GetPointer());
36 
37  bool big_endian = (imgMsg->GetEndian() == igtl::ImageMessage::ENDIAN_BIG);
38 
39  if (imgMsg->GetCoordinateSystem() != igtl::ImageMessage::COORDINATE_RAS)
40  {
41  // TODO: Which coordinate system does MITK use?
42  mitkThrow() << "Can not handle messages with LPS coordinate system";
43  }
44 
45  switch (imgMsg->GetScalarType())
46  {
47  case igtl::ImageMessage::TYPE_UINT8:
48  Initiate<unsigned char>(img, imgMsg, big_endian);
49  break;
50  case igtl::ImageMessage::TYPE_INT8:
51  Initiate<char>(img, imgMsg, big_endian);
52  break;
53  case igtl::ImageMessage::TYPE_UINT16:
54  Initiate<unsigned short>(img, imgMsg, big_endian);
55  break;
56  case igtl::ImageMessage::TYPE_INT16:
57  Initiate<short>(img, imgMsg, big_endian);
58  break;
59  case igtl::ImageMessage::TYPE_UINT32:
60  Initiate<unsigned int>(img, imgMsg, big_endian);
61  break;
62  case igtl::ImageMessage::TYPE_INT32:
63  Initiate<int>(img, imgMsg, big_endian);
64  break;
65  case igtl::ImageMessage::TYPE_FLOAT32:
66  Initiate<float>(img, imgMsg, big_endian);
67  break;
68  case igtl::ImageMessage::TYPE_FLOAT64:
69  Initiate<double>(img, imgMsg, big_endian);
70  break;
71  default:
72  mitkThrow() << "Incompatible PixelType " << imgMsg;
73  }
74 }
75 
76 template <typename TPixel>
77 void mitk::IGTLMessageToUSImageFilter::Initiate(mitk::Image::Pointer& img,
78  igtl::ImageMessage* msg,
79  bool big_endian)
80 {
81  typedef itk::Image<TPixel, 3> ImageType;
82 
83  typename ImageType::Pointer output = ImageType::New();
84  typename ImageType::RegionType region;
85  typename ImageType::RegionType::SizeType size;
86  typename ImageType::RegionType::IndexType index;
87  typename ImageType::SpacingType spacing;
88  typename ImageType::PointType origin;
89 
90  // Copy dimensions
91  int dims[3];
92  msg->GetDimensions(dims);
93  size_t num_pixel = 1;
94  for (size_t i = 0; i < 3; i++)
95  {
96  size[i] = dims[i];
97  num_pixel *= dims[i];
98  }
99 
100  // Handle subvolume information. We want the subvolume to be the whole image
101  // for now.
102  int sdims[3], offs[3];
103  msg->GetSubVolume(sdims, offs);
104  for (size_t i = 0; i < 3; i++)
105  {
106  if (offs[i] != 0 || sdims[i] != dims[i])
107  {
108  // TODO: Handle messages with smaller subvolume than whole image
109  throw("Can not handle message with smaller subvolume than whole image");
110  }
111  }
112 
113  index.Fill(0);
114 
115  float matF[4][4];
116  msg->GetMatrix(matF);
117  vtkMatrix4x4* vtkMatrix = vtkMatrix4x4::New();
118 
119  for (size_t i = 0; i < 4; ++i)
120  for (size_t j = 0; j < 4; ++j)
121  vtkMatrix->SetElement(i, j, matF[i][j]);
122 
123  float spacingMsg[3];
124 
125  msg->GetSpacing(spacingMsg);
126 
127  for (int i = 0; i < 3; ++i)
128  spacing[i] = spacingMsg[i];
129 
130  region.SetSize(size);
131  region.SetIndex(index);
132  output->SetRegions(region);
133  output->SetSpacing(spacing);
134  output->Allocate();
135 
136  TPixel* in = (TPixel*)msg->GetScalarPointer();
137  TPixel* out = (TPixel*)output->GetBufferPointer();
138  memcpy(out, in, num_pixel * sizeof(TPixel));
139  if (big_endian)
140  {
141  // Even though this method is called "FromSystemToBigEndian", it also swaps
142  // "FromBigEndianToSystem".
143  // This makes sense, but might be confusing at first glance.
144  itk::ByteSwapper<TPixel>::SwapRangeFromSystemToBigEndian(out, num_pixel);
145  }
146  else
147  {
148  itk::ByteSwapper<TPixel>::SwapRangeFromSystemToLittleEndian(out, num_pixel);
149  }
150 
151  img = mitk::Image::New();
152  img->InitializeByItk(output.GetPointer());
153  img->SetVolume(output->GetBufferPointer());
154  //img->GetGeometry()->SetIndexToWorldTransformByVtkMatrix(vtkMatrix);
155  m_previousImage = img;
156  vtkMatrix->Delete();
157 
158  float iorigin[3];
159  msg->GetOrigin(iorigin);
160  for (size_t i = 0; i < 3; i++)
161  {
162  origin[i] = iorigin[i];
163  }
164  output->SetOrigin(origin);
165 }
166 
168  : m_upstream(nullptr)
169 {
170  MITK_DEBUG << "Instantiated this (" << this << ") mitkIGTMessageToUSImageFilter\n";
171 }
172 
174  unsigned int numOutputs)
175 {
176  if (numOutputs > 1)
177  {
178  throw("Can only have 1 output for IGTLMessageToUSImageFilter.");
179  }
180 }
181 
183  mitk::IGTLMessageSource* UpstreamFilter)
184 {
185  MITK_DEBUG << "Connected this (" << this << ") mitkIGTLMessageToUSImageFilter to MessageSource (" << UpstreamFilter << ")\n";
186  m_upstream = UpstreamFilter;
187 }
virtual bool IsDataValid() const
returns true if the object contains valid data
virtual igtl::MessageBase::Pointer GetMessage() const
returns the OpenIGTLink message
void ConnectTo(mitk::IGTLMessageSource *UpstreamFilter)
Connects the input of this filter to the outputs of the given IGTLMessageSource.
mitk::Point3D PointType
itk::SmartPointer< Self > Pointer
#define MITK_DEBUG
Definition: mitkLogMacros.h:26
const char * GetIGTLMessageType() const
map::core::discrete::Elements< 3 >::InternalImageType ImageType
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()
OpenIGTLink message source.
static Pointer New()
static bool in(Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4)
Definition: jsoncpp.cpp:244
virtual void GetNextRawImage(mitk::Image::Pointer &img)
Copies the data from the next OIGTL message to an mitk::Image.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.