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