CustusX  18.04-rc5
An IGT application
cxImageDefaultTFGenerator.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 
13 
14 #include "vtkImageData.h"
15 #include "cxImage.h"
16 #include "cxImageLUT2D.h"
17 #include "cxImageTF3D.h"
18 #include "math.h"
19 #include "cxSettings.h"
20 #include "cxMathUtils.h"
21 
22 namespace cx
23 {
24 
26 {
27 
28 }
29 
31 {
32  // add shading for known preoperative modalities
33  if (mImage->getModality().contains("CT") || mImage->getModality().contains("MR"))
34  mImage->setShadingOn(settings()->value("View/shadingOn").value<bool>());
35 }
36 
38 {
39  ImageLUT2DPtr tf(new ImageLUT2D());
40 
41  double_pair fullRange = this->getFullScalarRange();
42  double_pair range = this->guessInitialScalarRange();
43  double smin = range.first;
44  double smax = range.second;
45 
46  IntIntMap opacity;
47  opacity[fullRange.first - 1] = 0;
48  opacity[fullRange.first] = 255;
49  tf->resetAlpha(opacity);
50 
51  ColorMap colors;
52  colors[smin] = QColor(Qt::black);
53  colors[smax] = QColor(Qt::white);
54  tf->resetColor(colors);
55 
56  return tf;
57 }
58 
60 {
61  ImageTF3DPtr tf(new ImageTF3D());
62 
63  double_pair range = this->guessInitialScalarRange();
64 
65  double smin = range.first;
66  double smax = range.second;
67  double srange = smax - smin;
68 
69  IntIntMap opacity;
70  // Note the ordering: add in descending order to ensure zero is
71  // always written into smin, also for binary volumes
72  // Round is required for binary volumes.
73  opacity[smin + roundAwayFromZero(0.5*srange)] = 255;
74  opacity[smin + roundAwayFromZero(0.3*srange)] = 255.0 * 0.7;
75  opacity[smin + roundAwayFromZero(0.1*srange)] = 0;
76  tf->resetAlpha(opacity);
77 
78  ColorMap colors;
79  colors[smin] = QColor(Qt::black);
80  colors[smax] = QColor(Qt::white);
81  tf->resetColor(colors);
82 
83  return tf;
84 }
85 
86 bool ImageDefaultTFGenerator::hasValidInitialWindow() const
87 {
88  return mImage->getInitialWindowWidth()>0;
89 }
90 
91 double_pair ImageDefaultTFGenerator::guessInitialScalarRange() const
92 {
93  double_pair srange = this->getFullScalarRange();
94 
95  if (this->hasValidInitialWindow())
96  {
97  srange = this->getInitialWindowRange();
98  }
99  // no initial window: add heuristics for each modality
100  if (!this->hasValidInitialWindow())
101  {
102  if (this->isUnsignedChar())
103  {
104  srange.first = 0;
105  srange.second = 255;
106 
107  if (this->looksLikeBinaryImage())
108  {
109  srange.first = 0;
110  srange.second = 1;
111  }
112  }
113  if (mImage->getModality().contains("CT"))
114  {
115  srange = this->guessCTRange();
116  }
117  if (mImage->getModality().contains("MR"))
118  {
119  srange = this->guessMRRange();
120  }
121  }
122 
123  srange = this->ensureNonZeroRoundedRange(srange);
124  return srange;
125 }
126 
127 bool ImageDefaultTFGenerator::isUnsignedChar() const
128 {
129  return mImage->getBaseVtkImageData()->GetScalarType() == VTK_UNSIGNED_CHAR;
130 }
131 
132 bool ImageDefaultTFGenerator::looksLikeBinaryImage() const
133 {
134  double_pair r = this->getFullScalarRange();
135  return similar(r.first, 0) && similar(r.second, 1);
136 }
137 
138 
139 double_pair ImageDefaultTFGenerator::ensureNonZeroRoundedRange(double_pair range) const
140 {
141  range.first = roundAwayFromZero(range.first);
142  range.second = roundAwayFromZero(range.second);
143  range.second = std::max(range.second, range.first+1);
144  return range;
145 }
146 
147 double_pair ImageDefaultTFGenerator::getFullScalarRange() const
148 {
149  double smin = mImage->getBaseVtkImageData()->GetScalarRange()[0];
150  double smax = mImage->getBaseVtkImageData()->GetScalarRange()[1];
151  return std::make_pair(smin, smax);
152 }
153 
154 double_pair ImageDefaultTFGenerator::getInitialWindowRange() const
155 {
156  double smin = mImage->getInitialWindowLevel() - mImage->getInitialWindowWidth()/2;
157  double smax = mImage->getInitialWindowLevel() + mImage->getInitialWindowWidth()/2;
158  return std::make_pair(smin, smax);
159 }
160 
161 double_pair ImageDefaultTFGenerator::guessCTRange() const
162 {
163  // signed: [-1024...3072]
164  // choose a default from lung to bone, approximately.
165  double smin = -500;
166  double smax = 900;
167 // if (0 >= mImage->getMin()) // unsigned: [0..4096]
168 // {
169 // int ct_signed2unsigned = 1024;
170 // smin += ct_signed2unsigned;
171 // smax += ct_signed2unsigned;
172 // }
173  return std::make_pair(smin, smax);
174 }
175 
176 double_pair ImageDefaultTFGenerator::guessMRRange() const
177 {
178  double_pair srange = this->getFullScalarRange();
179  srange.second *= 0.25; // usually lots of high-intensity noise of no interest
180  return srange;
181 }
182 
183 
184 } // namespace cx
Handler for the transfer functions used in 3d image volumes.
Definition: cxImageTF3D.h:51
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:27
Handling of color and opacity for 2D slices.
Definition: cxImageLUT2D.h:47
std::pair< double, double > double_pair
double roundAwayFromZero(double val)
Definition: cxMathUtils.cpp:14
std::map< int, QColor > ColorMap
Definition: cxImage.h:36
boost::shared_ptr< class ImageLUT2D > ImageLUT2DPtr
Settings * settings()
Shortcut for accessing the settings instance.
Definition: cxSettings.cpp:21
std::map< int, int > IntIntMap
Definition: cxImage.h:35
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
boost::shared_ptr< class ImageTF3D > ImageTF3DPtr
Namespace for all CustusX production code.