Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkImageToIGTLMessageFilter.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 "mitkImageReadAccessor.h"
19 #include "itkByteSwapper.h"
20 #include "igtlImageMessage.h"
21 
23 {
25  this->SetNumberOfRequiredOutputs(1);
26  this->SetNthOutput(0, output.GetPointer());
27  this->SetNumberOfRequiredInputs(1);
28 }
29 
31 {
32  // MITK_INFO << "ImageToIGTLMessageFilter.GenerateData()";
33  for (unsigned int i = 0; i < this->GetNumberOfIndexedOutputs(); ++i)
34  {
35  mitk::IGTLMessage* output = this->GetOutput(i);
36  assert(output);
37 
38  const mitk::Image* img = this->GetInput(i);
39 
40  int dims = img->GetDimension();
41  int chn = img->GetNumberOfChannels();
42 
43  MITK_INFO << "Sending image. Dimensions: " << dims << " Channels: " << chn << "\n";
44 
45  if (dims < 1)
46  {
47  MITK_ERROR << "Can not handle dimensionless images";
48  }
49  if (dims > 3)
50  {
51  MITK_ERROR << "Can not handle more than three dimensions";
52  continue;
53  }
54 
55  if (chn != 1)
56  {
57  MITK_ERROR << "Can not handle anything but one channel. Image contained " << chn;
58  continue;
59  }
60 
62 
63  // TODO: Which kind of coordinate system does MITK really use?
64  imgMsg->SetCoordinateSystem(igtl::ImageMessage::COORDINATE_RAS);
65 
66  // We could do this based on the host endiannes, but that's weird.
67  // We instead use little endian, as most modern systems are little endian,
68  // so there will probably not be an endian swap involved.
69  imgMsg->SetEndian(igtl::ImageMessage::ENDIAN_LITTLE);
70 
71  // Set number of components.
72  mitk::PixelType type = img->GetPixelType();
73  imgMsg->SetNumComponents(type.GetNumberOfComponents());
74 
75  // Set scalar type.
76  switch (type.GetComponentType())
77  {
78  case itk::ImageIOBase::CHAR:
79  imgMsg->SetScalarTypeToInt8();
80  break;
81  case itk::ImageIOBase::UCHAR:
82  imgMsg->SetScalarTypeToUint8();
83  break;
84  case itk::ImageIOBase::SHORT:
85  imgMsg->SetScalarTypeToInt16();
86  break;
87  case itk::ImageIOBase::USHORT:
88  imgMsg->SetScalarTypeToUint16();
89  break;
90  case itk::ImageIOBase::INT:
91  imgMsg->SetScalarTypeToInt32();
92  break;
93  case itk::ImageIOBase::UINT:
94  imgMsg->SetScalarTypeToUint32();
95  break;
96  case itk::ImageIOBase::LONG:
97  // OIGTL doesn't formally support 64bit int scalars, but if they are
98  // ever added,
99  // they will have the identifier 8 assigned.
100  imgMsg->SetScalarType(8);
101  break;
102  case itk::ImageIOBase::ULONG:
103  // OIGTL doesn't formally support 64bit uint scalars, but if they are
104  // ever added,
105  // they will have the identifier 9 assigned.
106  imgMsg->SetScalarType(9);
107  break;
108  case itk::ImageIOBase::FLOAT:
109  // The igtl library has no method for this. Correct type is 10.
110  imgMsg->SetScalarType(10);
111  break;
112  case itk::ImageIOBase::DOUBLE:
113  // The igtl library has no method for this. Correct type is 11.
114  imgMsg->SetScalarType(11);
115  break;
116  default:
117  MITK_ERROR << "Can not handle pixel component type "
118  << type.GetComponentType();
119  return;
120  }
121 
122  // Set transformation matrix.
123  vtkMatrix4x4* matrix = img->GetGeometry()->GetVtkMatrix();
124 
125  float matF[4][4];
126  for (size_t i = 0; i < 4; ++i)
127  {
128  for (size_t j = 0; j < 4; ++j)
129  {
130  matF[i][j] = matrix->GetElement(i, j);
131  }
132  }
133  imgMsg->SetMatrix(matF);
134 
135  float spacing[3];
136  auto spacingImg = img->GetGeometry()->GetSpacing();
137 
138  for (int i = 0; i < 3; ++i)
139  spacing[i] = spacingImg[i];
140 
141  imgMsg->SetSpacing(spacing);
142 
143  // Set dimensions.
144  int sizes[3];
145  for (size_t j = 0; j < 3; ++j)
146  {
147  sizes[j] = img->GetDimension(j);
148  }
149  imgMsg->SetDimensions(sizes);
150 
151  // Allocate and copy data.
152  imgMsg->AllocatePack();
153  imgMsg->AllocateScalars();
154 
155  size_t num_pixel = sizes[0] * sizes[1] * sizes[2];
156  void* out = imgMsg->GetScalarPointer();
157  {
158  // Scoped, so that readAccess will be released ASAP.
159  mitk::ImageReadAccessor readAccess(img, img->GetChannelData(0));
160  const void* in = readAccess.GetData();
161 
162  memcpy(out, in, num_pixel * type.GetSize());
163  }
164 
165  // We want to byte swap to little endian. We would like to just
166  // swap by number of bytes for each component, but itk::ByteSwapper
167  // is templated over element type, not over element size. So we need to
168  // switch on the size and use types of the same size.
169  size_t num_scalars = num_pixel * type.GetNumberOfComponents();
170  switch (type.GetComponentType())
171  {
172  case itk::ImageIOBase::CHAR:
173  case itk::ImageIOBase::UCHAR:
174  // No endian conversion necessary, because a char is exactly one byte!
175  break;
176  case itk::ImageIOBase::SHORT:
177  case itk::ImageIOBase::USHORT:
178  itk::ByteSwapper<short>::SwapRangeFromSystemToLittleEndian((short*)out,
179  num_scalars);
180  break;
181  case itk::ImageIOBase::INT:
182  case itk::ImageIOBase::UINT:
183  itk::ByteSwapper<int>::SwapRangeFromSystemToLittleEndian((int*)out,
184  num_scalars);
185  break;
186  case itk::ImageIOBase::LONG:
187  case itk::ImageIOBase::ULONG:
188  itk::ByteSwapper<long>::SwapRangeFromSystemToLittleEndian((long*)out,
189  num_scalars);
190  break;
191  case itk::ImageIOBase::FLOAT:
192  itk::ByteSwapper<float>::SwapRangeFromSystemToLittleEndian((float*)out,
193  num_scalars);
194  break;
195  case itk::ImageIOBase::DOUBLE:
196  itk::ByteSwapper<double>::SwapRangeFromSystemToLittleEndian(
197  (double*)out, num_scalars);
198  break;
199  }
200 
201  imgMsg->Pack();
202 
203  output->SetMessage(imgMsg.GetPointer());
204  }
205 }
206 
208 {
209  this->ProcessObject::SetNthInput(0, const_cast<mitk::Image*>(img));
210  this->CreateOutputsForAllInputs();
211 }
212 
214  const Image* img)
215 {
216  this->ProcessObject::SetNthInput(idx, const_cast<mitk::Image*>(img));
217  this->CreateOutputsForAllInputs();
218 }
219 
221 {
222  if (this->GetNumberOfInputs() < 1)
223  return NULL;
224  return static_cast<const mitk::Image*>(this->ProcessObject::GetInput(0));
225 }
226 
228 {
229  if (this->GetNumberOfInputs() < idx + 1)
230  {
231  return NULL;
232  }
233  return static_cast<const mitk::Image*>(this->ProcessObject::GetInput(idx));
234 }
235 
237 {
238  MITK_INFO << "Image source for this (" << this << ") mitkImageToIGTLMessageFilter is " << upstream;
239  for (DataObjectPointerArraySizeType i = 0; i < upstream->GetNumberOfOutputs();
240  i++)
241  {
242  this->SetInput(i, upstream->GetOutput(i));
243  }
244 }
245 
247 {
248  // create one message output for all image inputs
249  this->SetNumberOfIndexedOutputs(this->GetNumberOfIndexedInputs());
250 
251  for (size_t idx = 0; idx < this->GetNumberOfIndexedOutputs(); ++idx)
252  {
253  if (this->GetOutput(idx) == NULL)
254  {
255  this->SetNthOutput(idx, this->MakeOutput(idx));
256  }
257  this->Modified();
258  }
259 }
Superclass of all classes generating Images (instances of class Image) as output. ...
itk::SmartPointer< Self > Pointer
virtual void ConnectTo(mitk::ImageSource *UpstreamFilter)
Connects the input of this filter to the outputs of the given ImageSource.
vtkMatrix4x4 * GetVtkMatrix()
#define MITK_INFO
Definition: mitkLogMacros.h:22
void SetMessage(igtl::MessageBase::Pointer msg)
Sets the OpenIGTLink message.
#define MITK_ERROR
Definition: mitkLogMacros.h:24
const mitk::Image * GetInput()
Returns the input of this filter.
const mitk::Vector3D GetSpacing() const
Get the spacing (size of a pixel).
virtual ImageDataItemPointer GetChannelData(int n=0, void *data=nullptr, ImportMemoryManagementType importMemoryManagement=CopyMemory) const
Definition: mitkImage.cpp:461
vcl_size_t GetSize() const
Get size of the PixelType in bytes.
A wrapper for the OpenIGTLink message type.
Image class for storing images.
Definition: mitkImage.h:76
virtual void GenerateData() override
filter execute method
virtual void CreateOutputsForAllInputs()
create output objects for all inputs
int GetComponentType() const
Get the component type (the scalar (!) type). Each element may contain m_NumberOfComponents (more tha...
const mitk::PixelType GetPixelType(int n=0) const
Returns the PixelType of channel n.
Definition: mitkImage.cpp:105
static bool in(Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4)
Definition: jsoncpp.cpp:244
vcl_size_t GetNumberOfComponents() const
Get the number of components of which each element consists.
static Pointer New()
unsigned int GetNumberOfChannels() const
Get the number of channels.
virtual void SetInput(const mitk::Image *img)
Sets one input Image.
unsigned int GetDimension() const
Get dimension of the image.
Definition: mitkImage.cpp:110
ImageReadAccessor class to get locked read access for a particular image part.
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
Definition: mitkBaseData.h:129
Class for defining the data type of pixels.
Definition: mitkPixelType.h:55
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.