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