CustusX  2023.01.05-dev+develop.0da12
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 <vtkImageChangeInformation.h>
21 #include "cxForwardDeclarations.h"
22 #include "cxImageDataContainer.h"
23 #include "cxTypeConversions.h"
24 
25 #include <vtkImageExtractComponents.h>
26 #include <vtkImageAppendComponents.h>
27 #include <vtkImageLuminance.h>
28 #include <QFileInfo>
29 
30 #include "cxStringProperty.h"
31 #include "cxDoubleProperty.h"
32 #include "cxBoolProperty.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 = mFileManagerService->loadVtkImageData(filename);
232 
233  vtkMetaImageReaderPtr reader = vtkMetaImageReaderPtr::New();
234  reader->SetFileName(cstring_cast(filename));
235  reader->ReleaseDataFlagOn();
236 
237  //if (!ErrorObserver::checkedRead(reader, filename))
238  // return vtkImageDataPtr();
239 
240  vtkImageChangeInformationPtr zeroer = vtkImageChangeInformationPtr::New();
241  zeroer->SetInputConnection(reader->GetOutputPort());
242  zeroer->SetOutputOrigin(0, 0, 0);
243  CX_LOG_DEBUG() << "DummyImageStreamer::internalLoadImage. Initialized vtkImageChangeInformation";
244  zeroer->Update();//Test "VideoConnectionWidget can stream" freeze at this point on Ubuntu 16.04
245  CX_LOG_DEBUG() << "DummyImageStreamer::internalLoadImage. updated VTK pipeline";
246  vtkImageDataPtr source = zeroer->GetOutput();
247 
248  if (source)
249  std::cout << "DummyImageStreamer: Initialized with source file: " << getFileName().toStdString() << std::endl;
250  else
251  std::cout << "DummyImageStreamer: Failed to initialize with source file: " << getFileName().toStdString() << std::endl;
252 
253  return source;
254 }
255 QString DummyImageStreamer::getFileName()
256 {
257  return mFilename;
258 }
259 
261 {
263 }
264 
265 
266 void DummyImageStreamer::createTestDataSource(vtkImageDataPtr source)
267 {
268  mPrimaryDataSource = ImageTestData::initializePrimaryData(source, getFileName());
269 
270  if (!this->shouldSetupSecondaryDataSource())
271  return;
272 
273  mSecondaryDataSource = ImageTestData::initializeSecondaryData(source, getFileName());
274  std::cout << "DummyImageStreamer: Initialized secondary data with uid=" << mSecondaryDataSource.mRawUid << std::endl;
275 }
276 
278 {
280 
281  QString filename = arguments["filename"];
282  bool secondary = arguments.count("secondary") ? true : false;
283  this->initialize(filename, secondary);
284 }
285 
286 void DummyImageStreamer::initialize(QString filename, bool secondaryStream, bool sendonce)
287 {
288  mUseSecondaryStream = secondaryStream;
289  mFilename = filename;
290  vtkImageDataPtr source = this->internalLoadImage(filename);
291  if (!source)
292  {
293  this->setInitialized(false);
294  return;
295  }
296  this->createTestDataSource(source);
297  this->setSendOnce(sendonce);
298  this->createSendTimer(sendonce);
299  this->setInitialized(true);
300 }
301 
303 {
304  if (!this->isInitialized())
305  {
306  reportError("DummyImageStreamer: Failed to start streaming: Not initialized.");
307  return;
308  }
309  mSender = sender;
310  mSendTimer->start(this->getSendInterval());
311 }
312 
314 {
315  mSendTimer->stop();
316 }
317 
319 {
320  return this->isInitialized();
321 }
322 
323 vtkSmartPointer<vtkImageData> DummyImageStreamer::hasSecondaryData()
324 {
325  return mSecondaryDataSource.mImageData;
326 }
327 
328 void DummyImageStreamer::sendTestDataFrames()
329 {
330  PackagePtr primaryPackage = ImageTestData::createPackage(&mPrimaryDataSource);
331  mSender->send(primaryPackage);
332 
333  if(!this->hasSecondaryData())
334  return;
335 
336  PackagePtr secondaryPackage = ImageTestData::createPackage(&mSecondaryDataSource);
337  mSender->send(secondaryPackage);
338 }
339 
340 void DummyImageStreamer::streamSlot()
341 {
342  if (!this->isReadyToSend())
343  return;
344 
345  this->sendTestDataFrames();
346 }
347 
348 void DummyImageStreamer::setSendOnce(bool sendonce)
349 {
350  mSendOnce = sendonce;
351 }
352 
353 bool DummyImageStreamer::shouldSetupSecondaryDataSource()
354 {
355  return mUseSecondaryStream;
356 }
357 
358 } //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)
vtkSmartPointer< vtkImageChangeInformation > vtkImageChangeInformationPtr
Definition: cxImage.cpp:46
virtual void initialize(QString filename, bool secondaryStream, bool sendonce=false)
cstring_cast_Placeholder cstring_cast(const T &val)
vtkSmartPointer< class vtkImageMapToColors > vtkImageMapToColorsPtr
vtkSmartPointer< class vtkMetaImageReader > vtkMetaImageReaderPtr
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
#define CX_LOG_DEBUG
Definition: cxLogger.h:95
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
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.