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