Fraxinus  16.5.0-fx-rc9
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxIGTLinkConversionSonixCXLegacy.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) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
33 
34 #include <vtkImageImport.h>
35 #include <vtkImageData.h>
36 #include <vtkImageExtractComponents.h>
37 #include <vtkImageAppendComponents.h>
38 
39 #include "igtl_status.h"
40 
41 #include "cxLog.h"
42 #include "cxProbeDefinition.h"
43 #include "cxTypeConversions.h"
46 
47 typedef vtkSmartPointer<vtkImageImport> vtkImageImportPtr;
48 
49 namespace {
50 void GetIdentityMatrix(igtl::Matrix4x4& matrix)
51 {
52  matrix[0][0] = 1.0; matrix[1][0] = 0.0; matrix[2][0] = 0.0; matrix[3][0] = 0.0;
53  matrix[0][1] = 0.0; matrix[1][1] = 1.0; matrix[2][1] = 0.0; matrix[3][1] = 0.0;
54  matrix[0][2] = 0.0; matrix[1][2] = 0.0; matrix[2][2] = 1.0; matrix[3][2] = 0.0;
55  matrix[0][3] = 0.0; matrix[1][3] = 0.0; matrix[2][3] = 0.0; matrix[3][3] = 1.0;
56 }
57 }
58 
59 namespace cx
60 {
61 
63 {
64  QString newUid = msg->getUid();
65  QString format = this->extractColorFormat(msg->getUid(), &newUid);
66  msg->setUid(newUid);
67 
68  return msg;
69 }
70 
71 ImagePtr IGTLinkConversionSonixCXLegacy::decode(igtl::ImageMessage::Pointer message)
72 {
73  vtkImageImportPtr imageImport = vtkImageImportPtr::New();
74 
75  // Retrive the image data
76  float spacing[3]; // spacing (mm/pixel)
77  int svsize[3]; // sub-volume size
78  int svoffset[3]; // sub-volume offset
79  int scalarType; // scalar type
80  int size[3]; // image dimension
81 
82  // Note: subvolumes is not supported. Implement when needed.
83 
84  scalarType = message->GetScalarType();
85  message->GetDimensions(size);
86  message->GetSpacing(spacing);
87  message->GetSubVolume(svsize, svoffset);
88  QString deviceName = message->GetDeviceName();
89 
90  imageImport->SetNumberOfScalarComponents(1);
91 
92  switch (scalarType)
93  {
94  case igtl::ImageMessage::TYPE_INT8:
95  CX_LOG_WARNING() << "signed char is not supported. Falling back to unsigned char.";
96  imageImport->SetDataScalarTypeToUnsignedChar();
97  break;
98  case igtl::ImageMessage::TYPE_UINT8:
99  imageImport->SetDataScalarTypeToUnsignedChar();
100  break;
101  case igtl::ImageMessage::TYPE_INT16:
102  imageImport->SetDataScalarTypeToShort();
103  break;
104  case igtl::ImageMessage::TYPE_UINT16:
105  imageImport->SetNumberOfScalarComponents(2);
106  imageImport->SetDataScalarTypeToUnsignedChar();
107  break;
108  case igtl::ImageMessage::TYPE_INT32:
109  case igtl::ImageMessage::TYPE_UINT32:
110  imageImport->SetNumberOfScalarComponents(4);
111  imageImport->SetDataScalarTypeToUnsignedChar();
112  break;
113  case igtl::ImageMessage::TYPE_FLOAT32:
114  imageImport->SetDataScalarTypeToFloat();
115  break;
116  case igtl::ImageMessage::TYPE_FLOAT64:
117  imageImport->SetDataScalarTypeToDouble();
118  break;
119  default:
120  CX_LOG_WARNING() << "Unknown image type. Falling back to unsigned char.";
121  imageImport->SetDataScalarTypeToUnsignedChar();
122  }
123 
124  imageImport->SetDataOrigin(0, 0, 0);
125  imageImport->SetDataSpacing(spacing[0], spacing[1], spacing[2]);
126  imageImport->SetWholeExtent(0, size[0] - 1, 0, size[1] - 1, 0, size[2] - 1);
127  imageImport->SetDataExtentToWholeExtent();
128  imageImport->SetImportVoidPointer(message->GetScalarPointer());
129 
130  imageImport->Modified();
131  imageImport->Update();
132 
133  ImagePtr retval(new Image(deviceName, imageImport->GetOutput()));
134  IGTLinkConversionBase baseConverter;
135  retval->setAcquisitionTime(baseConverter.decode_timestamp(message));
136  retval = this->decode(retval);
137 
138  return retval;
139 }
140 
141 igtl::ImageMessage::Pointer IGTLinkConversionSonixCXLegacy::encode(ImagePtr image)
142 {
143  vtkImageDataPtr rawImage = image->getBaseVtkImageData();
144 
145  int size[] = {256, 256, 1}; // image dimension
146  rawImage->GetDimensions(size);
147 
148  double spacingD[3];
149  float spacingF[3];
150  rawImage->GetSpacing(spacingD);
151  spacingF[0] = spacingD[0];
152  spacingF[1] = spacingD[1];
153  spacingF[2] = spacingD[2];
154  int* svsize = size;
155  int svoffset[] = {0, 0, 0}; // sub-volume offset
156  int scalarType = -1;
157 
158  if (rawImage->GetNumberOfScalarComponents()==4)
159  {
160  if (rawImage->GetScalarType()==VTK_UNSIGNED_CHAR)
161  {
162  scalarType = igtl::ImageMessage::TYPE_UINT32;// scalar type
163  }
164  }
165 
166  if (rawImage->GetNumberOfScalarComponents()==1)
167  {
168  if (rawImage->GetScalarType()==VTK_UNSIGNED_SHORT)
169  {
170  scalarType = igtl::ImageMessage::TYPE_UINT16;// scalar type
171  }
172  else if (rawImage->GetScalarType()==VTK_UNSIGNED_CHAR)
173  {
174  scalarType = igtl::ImageMessage::TYPE_UINT8;// scalar type
175  }
176  }
177 
178  if (scalarType==-1)
179  {
180  std::cerr << "Unsupported file type based on vtk " << rawImage->GetScalarTypeAsString() << std::endl;
181  return igtl::ImageMessage::Pointer();
182  }
183 
184  //------------------------------------------------------------
185  // Create a new IMAGE type message
186  igtl::ImageMessage::Pointer imgMsg = igtl::ImageMessage::New();
187  imgMsg->SetDimensions(size);
188  imgMsg->SetSpacing(spacingF);
189  imgMsg->SetScalarType(scalarType);
190  imgMsg->SetDeviceName(cstring_cast(image->getUid()));
191  imgMsg->SetSubVolume(svsize, svoffset);
192  imgMsg->AllocateScalars();
193 
194  IGTLinkConversionBase baseConverter;
195  baseConverter.encode_timestamp(image->getAcquisitionTime(), imgMsg);
196 
197  int fsize = imgMsg->GetImageSize();
198  memcpy(imgMsg->GetScalarPointer(), rawImage->GetScalarPointer(0,0,0), fsize); // not sure if we need to copy
199 
200  igtl::Matrix4x4 matrix;
201  GetIdentityMatrix(matrix);
202  imgMsg->SetMatrix(matrix);
203 
204  return imgMsg;
205 }
206 
207 
209 {
210  QString newUid = msg->getUid();
211  QString format = this->extractColorFormat(msg->getUid(), &newUid);
212  vtkImageDataPtr imageRGB = this->createFilterFormat2RGB(format, msg->getBaseVtkImageData());
213 
214  // copy because the image will eventually be passed to another thread, and we cannot have the entire pipeline dragged along.
215  vtkImageDataPtr copy = vtkImageDataPtr::New();
216  copy->DeepCopy(imageRGB);
217 
218  ImagePtr retval(new Image(newUid, copy));
219  retval->setAcquisitionTime(msg->getAcquisitionTime());
220  return retval;
221 }
222 
224 {
225  QString dummy;
226  QString format = this->extractColorFormat(deviceName, &dummy);
227  return !format.isEmpty();
228 }
229 
230 QString IGTLinkConversionSonixCXLegacy::extractColorFormat(QString deviceName, QString* cleanedDeviceName)
231 {
232  QString format = "";
233  QRegExp colorFormat("\\[[A-Za-z]{1,4}\\]");
234  if (colorFormat.indexIn(deviceName) > 0)
235  {
236  format = colorFormat.cap(0).remove("[").remove("]");
237  }
238 
239  if (cleanedDeviceName)
240  {
241  *cleanedDeviceName = deviceName.remove(colorFormat).trimmed();
242  }
243 
244  return format;
245 }
246 
247 vtkImageDataPtr IGTLinkConversionSonixCXLegacy::createFilterFormat2RGB(QString format, vtkImageDataPtr input)
248 {
249  int R = format.indexOf('R', 0, Qt::CaseInsensitive);
250  int G = format.indexOf('G', 0, Qt::CaseInsensitive);
251  int B = format.indexOf('B', 0, Qt::CaseInsensitive);
252  if (R<0 || G<0 || B<0 || format.size()>4)
253  {
254  R = 0;
255  G = 1;
256  B = 2;
257  }
258 
259  return this->createFilterAny2RGB(R, G, B, input);
260 }
261 
262 vtkImageDataPtr IGTLinkConversionSonixCXLegacy::createFilterAny2RGB(int R, int G, int B, vtkImageDataPtr input)
263 {
264  if (input->GetNumberOfScalarComponents() == 1)
265  return input;
266  if (( input->GetNumberOfScalarComponents()==3 )&&( R==0 )&&( G==1 )&&( B==2 ))
267  return input;
268 
269  vtkImageAppendComponentsPtr merger = vtkImageAppendComponentsPtr::New();
270  vtkImageExtractComponentsPtr splitterRGB = vtkImageExtractComponentsPtr::New();
271  splitterRGB->SetInputData(input);
272  splitterRGB->SetComponents(R, G, B);
273  merger->AddInputConnection(splitterRGB->GetOutputPort());
274  merger->Update();
275  return merger->GetOutput();
276 }
277 
278 } //namespace cx
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:48
cstring_cast_Placeholder cstring_cast(const T &val)
vtkSmartPointer< class vtkImageAppendComponents > vtkImageAppendComponentsPtr
A volumetric data set.
Definition: cxImage.h:66
vtkSmartPointer< class vtkImageExtractComponents > vtkImageExtractComponentsPtr
vtkSmartPointer< class vtkImageImport > vtkImageImportPtr
#define CX_LOG_WARNING
Definition: cxLogger.h:113
vtkSmartPointer< class vtkImageData > vtkImageDataPtr
boost::shared_ptr< class ProbeDefinition > ProbeDefinitionPtr