Fraxinus  18.10
An IGT application
cxMHDImageStreamer.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) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 #include "cxMHDImageStreamer.h"
13 
14 #include <QTimer>
15 #include <QDateTime>
16 #include "vtkImageData.h"
17 #include "vtkMetaImageReader.h"
18 #include "vtkLookupTable.h"
19 #include "vtkImageMapToColors.h"
20 #include "cxForwardDeclarations.h"
21 #include "cxImageDataContainer.h"
22 #include "cxTypeConversions.h"
23 
24 #include <vtkImageExtractComponents.h>
25 #include <vtkImageAppendComponents.h>
26 #include <vtkImageLuminance.h>
27 #include <QFileInfo>
28 
29 #include "cxStringProperty.h"
30 #include "cxDoubleProperty.h"
31 #include "cxBoolProperty.h"
32 #include "cxDataReaderWriter.h"
33 #include "cxSender.h"
34 #include "cxFilePathProperty.h"
35 #include "cxProfile.h"
36 #include "cxReporter.h"
37 
38 namespace cx
39 {
40 
41 std::vector<PropertyPtr> ImageStreamerDummyArguments::getSettings(QDomElement root)
42 {
43  std::vector<PropertyPtr> retval;
44  retval.push_back(this->getFilenameOption(root));
45  retval.push_back(this->getSecondaryOption(root));
46  return retval;
47 }
48 
50 {
51  FilePathPropertyPtr retval;
52  retval = FilePathProperty::initialize("filename", "Filename",
53  "Select a 3D image file to stream from",
54  "",
55  QStringList() << profile()->getSessionRootFolder(),
56  root);
57 
58  retval->setGroup("File");
59  return retval;
60 }
61 
63 {
64  BoolPropertyPtr retval;
65  bool defaultValue = false;
66  retval = BoolProperty::initialize("secondary", "Secondary",
67  "Create two streams, the second one a dummy color image",
68  defaultValue, root);
69  retval->setAdvanced(true);
70  retval->setGroup("File");
71  return retval;
72 }
73 
75 {
76  StringMap retval;
77  retval["--type"] = "MHDFile";
78  retval["--filename"] = this->getFilenameOption(root)->getValue();
79  if (this->getSecondaryOption(root)->getValue())
80  retval["--secondary"] = "1";
81  return retval;
82 }
83 
85 {
86  QStringList retval;
87  retval << "--filename: name of image file to stream from ";
88  retval << "--secondary: Create two streams, the second one a dummy color image";
89  return retval;
90 }
91 
92 } // namespace cx
93 
94 
98 
99 namespace cx
100 {
101 
102 vtkLookupTablePtr createLookupTable(int numberOfTableValues)
103 {
104  vtkLookupTablePtr lut = vtkLookupTablePtr::New();
105  lut->SetNumberOfTableValues(numberOfTableValues);
106  lut->SetTableRange(0, numberOfTableValues - 1);
107  lut->SetSaturationRange(0, 0.5);
108  lut->SetHueRange(0, 1);
109  lut->SetValueRange(0, 1);
110  lut->Build();
111  return lut;
112 }
113 
115 {
116  vtkImageMapToColorsPtr mapper = vtkImageMapToColorsPtr::New();
117  mapper->SetInputData(input);
118  mapper->SetLookupTable(lut);
119  mapper->Update();
120  vtkImageDataPtr retval = mapper->GetOutput();
121  return retval;
122 }
123 
125 {
126  int numberOfTableValues = 256;
127  vtkLookupTablePtr lut = createLookupTable(numberOfTableValues);
128  vtkImageDataPtr retval = applyLUTToImage(image, lut);
129  return retval;
130 }
131 
132 
134 {
135  ImageTestData retval;
136  QString colorFormat = "R";
137  if (source->GetNumberOfScalarComponents() == 3)
138  {
139  vtkImageAppendComponentsPtr merger = vtkImageAppendComponentsPtr::New();
140  vtkImageExtractComponentsPtr splitterRGB = vtkImageExtractComponentsPtr::New();
141  splitterRGB->SetInputData(source);
142  splitterRGB->SetComponents(0, 1, 2);
143 // merger->AddInputConnection(0, splitterRGB->GetOutputPort());
144  merger->AddInputConnection(splitterRGB->GetOutputPort());
145  vtkImageExtractComponentsPtr splitterA = vtkImageExtractComponentsPtr::New();
146  splitterA->SetInputData(source);
147  splitterA->SetComponents(0);
148  merger->AddInputConnection(splitterA->GetOutputPort());
149 // merger->AddInputConnection(1, splitterA->GetOutputPort());
150  merger->Update();
151  retval.mImageData = merger->GetOutput();
152  colorFormat = "RGBA";
153  }
154  else if (source->GetNumberOfScalarComponents() == 4)
155  {
156  retval.mImageData = source;
157  colorFormat = "RGBA";
158  }
159  else if (source->GetNumberOfScalarComponents() == 1)
160  {
161  retval.mImageData = source;
162  colorFormat = "R";
163  }
164 
165  retval.mRawUid = QString("%1 [%2]").arg(QFileInfo(filename).completeBaseName()).arg(colorFormat);
166  retval.mDataSource.reset(new SplitFramesContainer(retval.mImageData));
167  retval.mCurrentFrame = 0;
168  return retval;
169 }
170 
172 {
173  ImageTestData retval;
174  QString colorFormat = "R";
175  if (source->GetNumberOfScalarComponents() == 3)
176  {
177  vtkSmartPointer < vtkImageLuminance > luminance = vtkSmartPointer < vtkImageLuminance > ::New();
178  luminance->SetInputData(source);
179  luminance->Update();
180  vtkImageDataPtr outData = luminance->GetOutput();
181  retval.mImageData = outData;
182  colorFormat = "R";
183  }
184  else if (source->GetNumberOfScalarComponents() == 4)
185  {
186  retval.mImageData = source;
187  colorFormat = "RGBA";
188  }
189  else if (source->GetNumberOfScalarComponents() == 1)
190  {
191  retval.mImageData = source;
192  colorFormat = "R";
193  }
194 
195  retval.mRawUid = QString("uchar %1[%2]").arg(QFileInfo(filename).completeBaseName()).arg(colorFormat);
196  retval.mDataSource.reset(new SplitFramesContainer(retval.mImageData));
197  retval.mCurrentFrame = 0;
198  return retval;
199 }
200 
202 {
203  PackagePtr package(new Package());
204 
205  int frame = (data->mCurrentFrame++) % data->mDataSource->size();
206  QString uid = data->mRawUid;
207  vtkImageDataPtr copy = vtkImageDataPtr::New();
208  copy->DeepCopy(data->mDataSource->get(frame));
209  ImagePtr image(new Image(uid, copy));
210  image->setAcquisitionTime(QDateTime::currentDateTime());
211  package->mImage = image;
212  return package;
213 }
214 
216  mSendOnce(false),
217  mUseSecondaryStream(false),
218  mPrimaryDataSource(),
219  mSecondaryDataSource()
220 {
221  this->setSendInterval(40);
222 }
223 
225 {
226  return "MHDFile";
227 }
228 
229 vtkImageDataPtr DummyImageStreamer::internalLoadImage(QString filename)
230 {
231  vtkImageDataPtr source = MetaImageReader().loadVtkImageData(filename);
232 
233  if (source)
234  std::cout << "DummyImageStreamer: Initialized with source file: " << getFileName().toStdString() << std::endl;
235  else
236  std::cout << "DummyImageStreamer: Failed to initialize with source file: " << getFileName().toStdString() << std::endl;
237 
238  return source;
239 }
240 QString DummyImageStreamer::getFileName()
241 {
242  return mFilename;
243 }
244 
246 {
248 }
249 
250 
251 void DummyImageStreamer::createTestDataSource(vtkImageDataPtr source)
252 {
253  mPrimaryDataSource = ImageTestData::initializePrimaryData(source, getFileName());
254 
255  if (!this->shouldSetupSecondaryDataSource())
256  return;
257 
258  mSecondaryDataSource = ImageTestData::initializeSecondaryData(source, getFileName());
259  std::cout << "DummyImageStreamer: Initialized secondary data with uid=" << mSecondaryDataSource.mRawUid << std::endl;
260 }
261 
263 {
265 
266  QString filename = arguments["filename"];
267  bool secondary = arguments.count("secondary") ? true : false;
268  this->initialize(filename, secondary);
269 }
270 
271 void DummyImageStreamer::initialize(QString filename, bool secondaryStream, bool sendonce)
272 {
273  mUseSecondaryStream = secondaryStream;
274  mFilename = filename;
275  vtkImageDataPtr source = this->internalLoadImage(filename);
276  if (!source)
277  {
278  this->setInitialized(false);
279  return;
280  }
281  this->createTestDataSource(source);
282  this->setSendOnce(sendonce);
283  this->createSendTimer(sendonce);
284  this->setInitialized(true);
285 }
286 
288 {
289  if (!this->isInitialized())
290  {
291  reportError("DummyImageStreamer: Failed to start streaming: Not initialized.");
292  return;
293  }
294  mSender = sender;
295  mSendTimer->start(this->getSendInterval());
296 }
297 
299 {
300  mSendTimer->stop();
301 }
302 
304 {
305  return this->isInitialized();
306 }
307 
308 vtkSmartPointer<vtkImageData> DummyImageStreamer::hasSecondaryData()
309 {
310  return mSecondaryDataSource.mImageData;
311 }
312 
313 void DummyImageStreamer::sendTestDataFrames()
314 {
315  PackagePtr primaryPackage = ImageTestData::createPackage(&mPrimaryDataSource);
316  mSender->send(primaryPackage);
317 
318  if(!this->hasSecondaryData())
319  return;
320 
321  PackagePtr secondaryPackage = ImageTestData::createPackage(&mSecondaryDataSource);
322  mSender->send(secondaryPackage);
323 }
324 
325 void DummyImageStreamer::streamSlot()
326 {
327  if (!this->isReadyToSend())
328  return;
329 
330  this->sendTestDataFrames();
331 }
332 
333 void DummyImageStreamer::setSendOnce(bool sendonce)
334 {
335  mSendOnce = sendonce;
336 }
337 
338 bool DummyImageStreamer::shouldSetupSecondaryDataSource()
339 {
340  return mUseSecondaryStream;
341 }
342 
343 } //namespace cx
cxResource_EXPORT ProfilePtr profile()
Definition: cxProfile.cpp:160
static BoolPropertyPtr initialize(const QString &uid, QString name, QString help, bool value, QDomNode root=QDomNode())
void reportError(QString msg)
Definition: cxLogger.cpp:71
void createSendTimer(bool singleshot=false)
Definition: cxStreamer.cpp:42
static PackagePtr createPackage(ImageTestData *data)
static ImageTestData initializePrimaryData(vtkImageDataPtr source, QString filename)
FilePathPropertyPtr getFilenameOption(QDomElement root)
void setSendInterval(int milliseconds)
how often an image should be sent (in milliseconds)
Definition: cxStreamer.cpp:22
vtkLookupTablePtr createLookupTable(int numberOfTableValues)
vtkImageDataPtr mImageData
bool isReadyToSend()
Definition: cxStreamer.cpp:49
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:27
virtual std::vector< PropertyPtr > getSettings(QDomElement root)
virtual void initialize(QString filename, bool secondaryStream, bool sendonce=false)
virtual vtkImageDataPtr loadVtkImageData(QString filename)
vtkSmartPointer< class vtkImageMapToColors > vtkImageMapToColorsPtr
std::map< QString, QString > StringMap
vtkSmartPointer< class vtkImageAppendComponents > vtkImageAppendComponentsPtr
A volumetric data set.
Definition: cxImage.h:45
boost::shared_ptr< class BoolPropertyBase > BoolPropertyBasePtr
virtual void startStreaming(SenderPtr sender)
void setInitialized(bool initialized)
Definition: cxStreamer.cpp:32
vtkSmartPointer< class vtkLookupTable > vtkLookupTablePtr
vtkImageDataPtr applyLUTToImage(vtkImageDataPtr input, vtkLookupTablePtr lut)
virtual QStringList getArgumentDescription()
static FilePathPropertyPtr initialize(const QString &uid, QString name, QString help, QString value, QStringList paths, QDomNode root=QDomNode())
vtkSmartPointer< class vtkImageExtractComponents > vtkImageExtractComponentsPtr
boost::shared_ptr< struct Package > PackagePtr
bool isInitialized()
Definition: cxStreamer.cpp:37
boost::shared_ptr< class SplitFramesContainer > mDataSource
QTimer * mSendTimer
Definition: cxStreamer.h:66
vtkImageDataPtr convertToTestColorImage(vtkImageDataPtr image)
boost::shared_ptr< class FilePathProperty > FilePathPropertyPtr
StringMap convertToCommandLineArguments(QDomElement root)
boost::shared_ptr< class BoolProperty > BoolPropertyPtr
boost::shared_ptr< Sender > SenderPtr
Definition: cxSender.h:64
vtkSmartPointer< class vtkImageData > vtkImageDataPtr
Reader for metaheader .mhd files.
SenderPtr mSender
Definition: cxStreamer.h:65
static ImageTestData initializeSecondaryData(vtkImageDataPtr source, QString filename)
virtual void initialize(StringMap arguments)
Definition: cxStreamer.cpp:59
BoolPropertyBasePtr getSecondaryOption(QDomElement root)
int getSendInterval() const
how often an image should be sent (in milliseconds)
Definition: cxStreamer.cpp:27
Namespace for all CustusX production code.