NorMIT-nav  2023.01.05-dev+develop.0da12
An IGT application
cxImageTFData.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 
13 /*
14  * sscImageTFData.cpp
15  *
16  * Created on: Mar 15, 2011
17  * Author: christiana
18  */
19 
20 #include "cxImageTFData.h"
21 #include <iostream>
22 #include <QDomDocument>
23 #include <QStringList>
24 #include <vtkColorTransferFunction.h>
25 #include <vtkPiecewiseFunction.h>
26 #include <vtkLookupTable.h>
27 #include <vtkImageData.h>
28 
29 #include "cxVector3D.h"
30 #include "cxImageTF3D.h"
31 
32 #include "cxTypeConversions.h"
33 #include "cxLogger.h"
34 
35 namespace cx
36 {
37 
39 {
40 }
41 
43 {
44 }
45 
47 {
48  mOpacityMap = source->mOpacityMap;
49  mColorMap = source->mColorMap;
50 }
51 
52 void ImageTFData::addXml(QDomNode dataNode)
53 {
54  QDomDocument doc = dataNode.ownerDocument();
55 
56  QDomElement alphaNode = doc.createElement("alpha");
57  // Use QStringList to put all points in the same string instead of storing
58  // the points as separate nodes.
59  QStringList pointStringList;
60  // Add alpha points
61  for (IntIntMap::iterator opPoint = mOpacityMap.begin(); opPoint != mOpacityMap.end(); ++opPoint)
62  pointStringList.append(QString("%1=%2").arg(opPoint->first). arg(opPoint->second));
63  alphaNode.appendChild(doc.createTextNode(pointStringList.join(" ")));
64 
65  pointStringList.clear();
66  QDomElement colorNode = doc.createElement("color");
67  // Add color points
68  for (ColorMap::iterator colorPoint = mColorMap.begin(); colorPoint != mColorMap.end(); ++colorPoint)
69  pointStringList.append(QString("%1=%2/%3/%4").arg(colorPoint->first). arg(colorPoint->second.red()). arg(
70  colorPoint->second.green()). arg(colorPoint->second.blue()));
71  colorNode.appendChild(doc.createTextNode(pointStringList.join(" ")));
72 
73  dataNode.appendChild(alphaNode);
74  dataNode.appendChild(colorNode);
75 
76  QDomElement elem = dataNode.toElement();
77 }
78 
79 void ImageTFData::parseXml(QDomNode dataNode)
80 {
81  if (dataNode.isNull())
82  {
83  CX_LOG_WARNING() << "ImageTFData::parseXml empty data node";
84  return;
85  }
86 
87  QDomNode alphaNode = dataNode.namedItem("alpha");
88  // Read alpha node if it exists
89  if (!alphaNode.isNull() && !alphaNode.toElement().text().isEmpty())
90  {
91  QString alphaString = alphaNode.toElement().text();
92  mOpacityMap.clear();
93  QStringList alphaStringList = alphaString.split(" ", QString::SkipEmptyParts);
94  for (int i = 0; i < alphaStringList.size(); i++)
95  {
96  QStringList pointStringList = alphaStringList[i].split("=");
97  if (pointStringList.size() < 2)
98  continue;
99  addAlphaPoint(pointStringList[0].toInt(), pointStringList[1].toInt());
100  }
101  }
102  else
103  {
104  CX_LOG_WARNING() << "ImageTF3D::parseXml() found no alpha transferfunction";
105  }
106 
107  QDomNode colorNode = dataNode.namedItem("color");
108  // Read color node if it exists
109  if (!colorNode.isNull() && !colorNode.toElement().text().isEmpty())
110  {
111  mColorMap.clear();
112  QStringList colorStringList = colorNode.toElement().text().split(" ", QString::SkipEmptyParts);
113  for (int i = 0; i < colorStringList.size(); i++)
114  {
115  QStringList pointStringList = colorStringList[i].split("=");
116  QStringList valueStringList = pointStringList[1].split("/");
117  addColorPoint(pointStringList[0].toInt(), QColor(valueStringList[0].toInt(), valueStringList[1].toInt(),
118  valueStringList[2].toInt()));
119  }
120  }
121  else
122  {
123  CX_LOG_WARNING() << "ImageTF3D::parseXml() found no color transferfunction";
124  }
125 
126  this->internalsHaveChanged();
127 }
128 
135 void ImageTFData::unsignedCT(bool onLoad)
136 {
137 // //Signed after all. Don't do anyting
138 // if (this->getScalarMin() < 0)
139 // return;
140 
141  int modify = -1024;
142  if(onLoad)
143  modify = 1024;
144 
145 // std::cout << "unsignedCT shift " << modify << std::endl;
146  this->shift(modify);
147 }
148 
149 void ImageTFData::shift(int val)
150 {
151  this->shiftOpacity(val);
152  this->shiftColor(val, 0, 1);
153 
154  this->internalsHaveChanged();
155 }
156 
157 void ImageTFData::shiftColor(int shift, double center, double scale)
158 {
159  ColorMap newColorMap;
160  for (ColorMap::iterator it = mColorMap.begin(); it != mColorMap.end(); ++it)
161  {
162  double newVal = (it->first-center)*scale+center + shift;
163  int roundedVal = floor(newVal + 0.5);
164  newColorMap[roundedVal] = it->second;
165  }
166  mColorMap = newColorMap;
167 }
168 
170 {
171  IntIntMap newOpacipyMap;
172  for (IntIntMap::iterator it = mOpacityMap.begin(); it != mOpacityMap.end(); ++it)
173  {
174  newOpacipyMap[it->first + shift] = it->second;
175  }
176  mOpacityMap = newOpacipyMap;
177 }
178 
182 void ImageTFData::setLLR(double val)
183 {
184  double old = this->getLLR();
185  if (similar(old, val))
186  return;
187 
188  this->shiftOpacity(val-old);
189  this->internalsHaveChanged();
190 }
191 
192 double ImageTFData::getLLR() const
193 {
194  if (mOpacityMap.empty())
195  return 0;
196 
197  for (IntIntMap::const_iterator it = mOpacityMap.begin(); it != mOpacityMap.end(); ++it)
198  {
199  if (!similar(it->second, 0.0))
200  return it->first;
201  }
202  return mOpacityMap.begin()->first;
203 }
204 
205 void ImageTFData::setAlpha(double val)
206 {
207  double old = this->getAlpha();
208  if (similar(old, val))
209  return;
210 
211  if (similar(old, 0.0))
212  {
213  // degenerate case: we have lost all info, simpl add input val to all but the first entry
214  for (IntIntMap::iterator it = mOpacityMap.begin(); it != mOpacityMap.end(); ++it)
215  {
216  if (it==mOpacityMap.begin() && mOpacityMap.size()>1)
217  continue; // heuristic: assume first entry should stay at zero
218  it->second += val*255;
219  }
220  }
221  else
222  {
223  double scale = val/old;
224  for (IntIntMap::iterator it = mOpacityMap.begin(); it != mOpacityMap.end(); ++it)
225  {
226  it->second *= scale;
227  }
228  }
229 
230  this->internalsHaveChanged();
231 }
232 
233 double ImageTFData::getAlpha() const
234 {
235  double amax = 0;
236  for (IntIntMap::const_iterator it = mOpacityMap.begin(); it != mOpacityMap.end(); ++it)
237  {
238  amax = std::max<double>(it->second, amax);
239  }
240  return amax/255;
241 }
242 
246 void ImageTFData::setWindow(double val)
247 {
248  double old = this->getWindow();
249  val = std::max(1.0, val);
250 
251  if (similar(old, val))
252  return;
253 
254  double scale = val/old;
255  this->shiftColor(0, this->getLevel(), scale);
256 
257  this->internalsHaveChanged();
258 }
259 
261 {
262  if (mColorMap.empty())
263  return 0;
264  return mColorMap.rbegin()->first - mColorMap.begin()->first;
265 // return mWindow;
266 }
267 
271 void ImageTFData::setLevel(double val)
272 {
273  double old = this->getLevel();
274  if (similar(old, val))
275  return;
276  double shift = val-old;
277 
278  this->shiftColor(shift, 0.0, 1.0);
279 
280 // mLevel = val;
281  this->internalsHaveChanged();
282 }
283 
284 double ImageTFData::getLevel() const
285 {
286  if (mColorMap.empty())
287  return 0;
288  int a = mColorMap.begin()->first;
289  int b = mColorMap.rbegin()->first;
290  return a + (b-a)/2;
291 // return mLevel;
292 }
293 
295 {
296  return mOpacityMap;
297 }
299 {
300  return mColorMap;
301 }
302 void ImageTFData::addAlphaPoint(int alphaPosition, int alphaValue)
303 {
304  //mOpacityMapPtr->insert(std::pair<int, int>(alphaPosition, alphaValue));
305  mOpacityMap[alphaPosition] = alphaValue;
306  this->internalsHaveChanged();
307 }
308 void ImageTFData::removeAlphaPoint(int alphaPosition)
309 {
310  mOpacityMap.erase(alphaPosition);
311  this->internalsHaveChanged();
312 }
313 void ImageTFData::moveAlphaPoint(int oldpos, int newpos, int alphaValue)
314 {
315  mOpacityMap.erase(oldpos);
316  mOpacityMap[newpos] = alphaValue;
317  this->internalsHaveChanged();
318 }
319 void ImageTFData::addColorPoint(int colorPosition, QColor colorValue)
320 {
321  mColorMap[colorPosition] = colorValue;
322  //mColorMapPtr->insert(std::pair<int, QColor>(colorPosition, colorValue));
323  this->internalsHaveChanged();
324 }
325 void ImageTFData::removeColorPoint(int colorPosition)
326 {
327  mColorMap.erase(colorPosition);
328  this->internalsHaveChanged();
329 }
330 
331 void ImageTFData::moveColorPoint(int oldpos, int newpos, QColor colorValue)
332 {
333  mColorMap.erase(oldpos);
334  mColorMap[newpos] = colorValue;
335  this->internalsHaveChanged();
336 }
337 
339 {
340  mOpacityMap = val;
341  this->internalsHaveChanged();
342 }
343 
345 {
346  mColorMap = val;
347  this->internalsHaveChanged();
348 }
349 
351 {
352  vtkColorTransferFunctionPtr tf = vtkColorTransferFunctionPtr::New();
353  this->fillColorTFFromMap(tf);
354  return tf;
355 }
356 
358 {
359  vtkPiecewiseFunctionPtr tf = vtkPiecewiseFunctionPtr::New();
360  this->fillOpacityTFFromMap(tf);
361  return tf;
362 }
363 
365 {
366  tf->SetColorSpaceToRGB();
367  tf->RemoveAllPoints();
368  for (ColorMap::const_iterator iter = mColorMap.begin(); iter != mColorMap.end(); ++iter)
369  {
370  QColor c = iter->second;
371  tf->AddRGBPoint(iter->first, c.redF(), c.greenF(), c.blueF());
372  }
373 }
374 
376 {
377  tf->RemoveAllPoints();
378  for (IntIntMap::const_iterator iter = mOpacityMap.begin(); iter != mOpacityMap.end(); ++iter)
379  tf->AddPoint(iter->first, iter->second / 255.0);
380 // tf->Update();
381 }
382 
383 }
cx::ImageTFData::ImageTFData
ImageTFData()
Definition: cxImageTFData.cpp:38
cx::ImageTFData::resetColor
void resetColor(ColorMap val)
Definition: cxImageTFData.cpp:344
cx::ImageTFData::resetAlpha
void resetAlpha(IntIntMap val)
Definition: cxImageTFData.cpp:338
cxLogger.h
cx::ImageTFData::internalsHaveChanged
virtual void internalsHaveChanged()
Definition: cxImageTFData.h:119
cx::ImageTFData::fillOpacityTFFromMap
void fillOpacityTFFromMap(vtkPiecewiseFunctionPtr tf) const
Definition: cxImageTFData.cpp:375
cx::ImageTFData::mOpacityMap
IntIntMap mOpacityMap
Definition: cxImageTFData.h:126
cx
Namespace for all CustusX production code.
Definition: cx_dev_group_definitions.h:13
cx::ImageTFData::removeAlphaPoint
void removeAlphaPoint(int alphaPosition)
Remove point from the opacity transfer function.
Definition: cxImageTFData.cpp:308
cx::ImageTFData::moveColorPoint
void moveColorPoint(int oldpos, int newpos, QColor colorValue)
Definition: cxImageTFData.cpp:331
cx::ImageTFData::getOpacityMap
IntIntMap getOpacityMap()
Definition: cxImageTFData.cpp:294
cx::ImageTFData::shift
void shift(int val)
shift the transfter function index values by the input amount. Used for signed/unsigned conversion.
Definition: cxImageTFData.cpp:149
cx::ImageTFData::mColorMap
ColorMap mColorMap
Definition: cxImageTFData.h:127
cxVector3D.h
cx::ImageTFData::getAlpha
double getAlpha() const
Definition: cxImageTFData.cpp:233
cx::ColorMap
std::map< int, QColor > ColorMap
Definition: cxImage.h:36
cx::ImageTFData::setAlpha
void setAlpha(double val)
range [0..1]
Definition: cxImageTFData.cpp:205
cx::ImageTFData::fillColorTFFromMap
void fillColorTFFromMap(vtkColorTransferFunctionPtr tf) const
Definition: cxImageTFData.cpp:364
cx::ImageTFData::parseXml
virtual void parseXml(QDomNode dataNode)
Use a XML node to load data.
Definition: cxImageTFData.cpp:79
cx::ImageTFData::getLLR
double getLLR() const
Definition: cxImageTFData.cpp:192
cx::ImageTFData::shiftOpacity
void shiftOpacity(int shift)
Definition: cxImageTFData.cpp:169
cx::ImageTFData::getWindow
double getWindow() const
Definition: cxImageTFData.cpp:260
vtkPiecewiseFunctionPtr
vtkSmartPointer< class vtkPiecewiseFunction > vtkPiecewiseFunctionPtr
Definition: vtkForwardDeclarations.h:105
cx::ImageTFData::shiftColor
void shiftColor(int shift, double center, double scale)
Definition: cxImageTFData.cpp:157
cx::ImageTFData::generateColorTF
vtkColorTransferFunctionPtr generateColorTF() const
Definition: cxImageTFData.cpp:350
cx::ImageTFData::setLLR
void setLLR(double val)
range [scalarMin..scalarMax]
Definition: cxImageTFData.cpp:182
cx::ImageTFData::moveAlphaPoint
void moveAlphaPoint(int oldpos, int newpos, int alphaValue)
Definition: cxImageTFData.cpp:313
cxTypeConversions.h
cx::ImageTFData::setLevel
void setLevel(double val)
range [scalarMin..scalarMax]
Definition: cxImageTFData.cpp:271
cx::ImageTFData::removeColorPoint
void removeColorPoint(int colorPosition)
Remove point from the color transfer function.
Definition: cxImageTFData.cpp:325
cxImageTFData.h
cx::IntIntMap
std::map< int, int > IntIntMap
Definition: cxImage.h:35
cx::ImageTFData::addXml
virtual void addXml(QDomNode dataNode)
adds xml information about the transferfunction and its variabels
Definition: cxImageTFData.cpp:52
cx::ImageTFData::addColorPoint
void addColorPoint(int colorPosition, QColor colorValue)
Add point to the color transfer function.
Definition: cxImageTFData.cpp:319
cx::ImageTFData::generateOpacityTF
vtkPiecewiseFunctionPtr generateOpacityTF() const
Definition: cxImageTFData.cpp:357
cx::ImageTFData::unsignedCT
void unsignedCT(bool onLoad)
Definition: cxImageTFData.cpp:135
cx::ImageTFData::getColorMap
ColorMap getColorMap()
Definition: cxImageTFData.cpp:298
vtkColorTransferFunctionPtr
vtkSmartPointer< class vtkColorTransferFunction > vtkColorTransferFunctionPtr
Definition: vtkForwardDeclarations.h:44
cx::ImageTFData::deepCopy
void deepCopy(ImageTFData *source)
Definition: cxImageTFData.cpp:46
cx::ImageTFData::setWindow
void setWindow(double val)
range [1..scalarMax-scalarMin]
Definition: cxImageTFData.cpp:246
cx::ImageTFData::addAlphaPoint
void addAlphaPoint(int alphaPosition, int alphaValue)
Add point to the opacity transfer function.
Definition: cxImageTFData.cpp:302
CX_LOG_WARNING
#define CX_LOG_WARNING
Definition: cxLogger.h:98
cxImageTF3D.h
cx::similar
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
Definition: cxCameraStyleForView.cpp:506
cx::ImageTFData
Data class for Transfer Function info, either 2D or 3D.
Definition: cxImageTFData.h:76
cx::ImageTFData::~ImageTFData
virtual ~ImageTFData()
Definition: cxImageTFData.cpp:42
cx::ImageTFData::getLevel
double getLevel() const
Definition: cxImageTFData.cpp:284