Medical Imaging Interaction Toolkit  2018.4.99-c0f884b2
Medical Imaging Interaction Toolkit
mitkLevelWindow.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "mitkLevelWindow.h"
14 #include "mitkImage.h"
15 #include "mitkImageSliceSelector.h"
17 
18 #include <algorithm>
19 
21 {
22  // Check if total range is ok
23  {
24  if (m_RangeMin > m_RangeMax)
26  if (m_RangeMin == m_RangeMax)
27  m_RangeMin = m_RangeMax - 1;
28  }
29 
30  // Check if current window is ok
31  {
34 
43 
45  {
46  m_UpperWindowBound += 0.5;
47  m_LowerWindowBound -= 0.5;
48 
51  }
52  }
53 }
54 
56  : m_LowerWindowBound(level - window / 2.0),
57  m_UpperWindowBound(level + window / 2.0),
58  m_RangeMin(-2048.0),
59  m_RangeMax(4096.0),
60  m_DefaultLowerBound(-2048.0),
61  m_DefaultUpperBound(4096.0),
62  m_IsFloatingImage(false),
63  m_Fixed(false)
64 {
65  SetDefaultLevelWindow(level, window);
66  SetLevelWindow(level, window, true);
67 }
68 
72  m_RangeMin(levWin.GetRangeMin()),
73  m_RangeMax(levWin.GetRangeMax()),
77  m_Fixed(levWin.GetFixed())
78 {
79 }
80 
82 {
83 }
84 
86 {
88 }
89 
91 {
93 }
94 
96 {
97  return ((m_DefaultUpperBound + m_DefaultLowerBound) / 2.0);
98 }
99 
101 {
103 }
104 
106 {
108 }
109 
111 {
112  return m_LowerWindowBound;
113 }
114 
116 {
117  return m_UpperWindowBound;
118 }
119 
121 {
122  SetDefaultBoundaries((level - (window / 2.0)), (level + (window / 2.0)));
123 }
124 
125 void mitk::LevelWindow::SetLevelWindow(mitk::ScalarType level, mitk::ScalarType window, bool expandRangesIfNecessary)
126 {
127  SetWindowBounds((level - (window / 2.0)), (level + (window / 2.0)), expandRangesIfNecessary);
128 }
129 
131  mitk::ScalarType upperBound,
132  bool expandRangesIfNecessary)
133 {
134  if (IsFixed())
135  return;
136 
137  m_LowerWindowBound = lowerBound;
138  m_UpperWindowBound = upperBound;
139 
140  if (expandRangesIfNecessary)
141  {
142  /* if caller is sure he wants exactly that level/window, we make sure the limits match */
146  {
148  }
149 
151  {
153  }
154  }
155 
157 }
158 
160 {
161  if (IsFixed())
162  return;
163  m_RangeMin = min;
164  m_RangeMax = max;
166 }
167 
169 {
170  if (IsFixed())
171  return;
172  m_DefaultLowerBound = low;
173  m_DefaultUpperBound = up;
174  // Check if default window is ok
175  {
178 
181  }
183 }
184 
186 {
188 }
189 
191 {
192  return m_RangeMin;
193 }
194 
196 {
197  return m_RangeMax;
198 }
199 
201 {
202  return m_RangeMax - m_RangeMin;
203 }
204 
206 {
207  return m_DefaultUpperBound;
208 }
209 
211 {
212  return m_DefaultLowerBound;
213 }
214 
216 {
218 }
219 
257  bool /*tryPicTags*/,
258  bool guessByCentralSlice,
259  unsigned selectedComponent)
260 {
261  if (IsFixed())
262  return;
263 
264  if (image == nullptr || !image->IsInitialized())
265  return;
266 
267  if (itk::ImageIOBase::IOComponentType::FLOAT == image->GetPixelType().GetComponentType()
268  || itk::ImageIOBase::IOComponentType::DOUBLE == image->GetPixelType().GetComponentType())
269  {
270  m_IsFloatingImage = true;
271  }
272  else
273  {
274  m_IsFloatingImage = false;
275  }
276 
277  const mitk::Image *wholeImage = image;
278  ScalarType minValue = 0.0;
279  ScalarType maxValue = 0.0;
280  ScalarType min2ndValue = 0.0;
281  ScalarType max2ndValue = 0.0;
283  if (guessByCentralSlice)
284  {
285  sliceSelector->SetInput(image);
286  sliceSelector->SetSliceNr(image->GetDimension(2) / 2);
287  sliceSelector->SetTimeNr(image->GetDimension(3) / 2);
288  sliceSelector->SetChannelNr(image->GetDimension(4) / 2);
289  sliceSelector->Update();
290  image = sliceSelector->GetOutput();
291  if (image == nullptr || !image->IsInitialized())
292  return;
293 
294  minValue = image->GetStatistics()->GetScalarValueMin(0, selectedComponent);
295  maxValue = image->GetStatistics()->GetScalarValueMaxNoRecompute();
296  min2ndValue = image->GetStatistics()->GetScalarValue2ndMinNoRecompute();
297  max2ndValue = image->GetStatistics()->GetScalarValue2ndMaxNoRecompute();
298  if (minValue == maxValue)
299  {
300  // guessByCentralSlice seems to have failed, lets look at all data
301  image = wholeImage;
302  minValue = image->GetStatistics()->GetScalarValueMin(0, selectedComponent);
303  maxValue = image->GetStatistics()->GetScalarValueMaxNoRecompute();
304  min2ndValue = image->GetStatistics()->GetScalarValue2ndMinNoRecompute();
305  max2ndValue = image->GetStatistics()->GetScalarValue2ndMaxNoRecompute();
306  }
307  }
308  else
309  {
310  const_cast<Image *>(image)->Update();
311  minValue = image->GetStatistics()->GetScalarValueMin(0, selectedComponent);
312  maxValue = image->GetStatistics()->GetScalarValueMaxNoRecompute(0);
313  min2ndValue = image->GetStatistics()->GetScalarValue2ndMinNoRecompute(0);
314  max2ndValue = image->GetStatistics()->GetScalarValue2ndMaxNoRecompute(0);
315  for (unsigned int i = 1; i < image->GetDimension(3); ++i)
316  {
317  ScalarType minValueTemp = image->GetStatistics()->GetScalarValueMin(i, selectedComponent);
318  if (minValue > minValueTemp)
319  minValue = minValueTemp;
320  ScalarType maxValueTemp = image->GetStatistics()->GetScalarValueMaxNoRecompute(i);
321  if (maxValue < maxValueTemp)
322  maxValue = maxValueTemp;
323  ScalarType min2ndValueTemp = image->GetStatistics()->GetScalarValue2ndMinNoRecompute(i);
324  if (min2ndValue > min2ndValueTemp)
325  min2ndValue = min2ndValueTemp;
326  ScalarType max2ndValueTemp = image->GetStatistics()->GetScalarValue2ndMaxNoRecompute(i);
327  if (max2ndValue > max2ndValueTemp)
328  max2ndValue = max2ndValueTemp;
329  }
330  }
331 
332  // Fix for bug# 344 Level Window wird bei Eris Cut bildern nicht richtig gesetzt
333  if (image->GetPixelType().GetPixelType() == itk::ImageIOBase::SCALAR &&
334  image->GetPixelType().GetComponentType() == itk::ImageIOBase::INT && image->GetPixelType().GetBpe() >= 8)
335  {
336  // the windows compiler complains about ambiguos 'pow' call, therefore static casting to (double, int)
337  if (minValue == -(pow((double)2.0, static_cast<int>(image->GetPixelType().GetBpe() / 2))))
338  {
339  minValue = min2ndValue;
340  }
341  }
342  // End fix
343 
345  if (minValue == maxValue)
346  {
347  minValue = maxValue - 1;
348  }
349  else
350  {
351  // Due to bug #8690 level window now is no longer of fixed range by default but the range adapts according to
352  // levelwindow interaction
353  // This is done because the range should be a little bit larger from the beginning so that the scale doesn't start
354  // to resize right from the beginning
355  double additionalRange = 0.15 * (maxValue - minValue);
356  minValue -= additionalRange;
357  maxValue += additionalRange;
358  }
359 
360  if (!std::isfinite(minValue))
361  {
362  minValue = image->GetStatistics()->GetScalarValue2ndMinNoRecompute(0);
363  }
364  if (!std::isfinite(maxValue))
365  {
366  maxValue = image->GetStatistics()->GetScalarValue2ndMaxNoRecompute(0);
367  }
368 
369  SetRangeMinMax(minValue, maxValue);
370  SetDefaultBoundaries(minValue, maxValue);
371 
372  unsigned int numPixelsInDataset = image->GetDimensions()[0];
373  for (unsigned int k = 0; k < image->GetDimension(); ++k)
374  numPixelsInDataset *= image->GetDimensions()[k];
375  unsigned int minCount = image->GetStatistics()->GetCountOfMinValuedVoxelsNoRecompute();
376  unsigned int maxCount = image->GetStatistics()->GetCountOfMaxValuedVoxelsNoRecompute();
377  ScalarType minCountFraction = minCount / ScalarType(numPixelsInDataset);
378  ScalarType maxCountFraction = maxCount / ScalarType(numPixelsInDataset);
379 
381  if (min2ndValue == maxValue)
382  {
383  // noop; full range is fine
384  }
385 
387  else if (min2ndValue == max2ndValue)
388  {
389  ScalarType minDelta = std::min(min2ndValue - minValue, maxValue - min2ndValue);
390  minValue = min2ndValue - minDelta;
391  maxValue = min2ndValue + minDelta;
392  }
393 
394  // now we can assume more than three distict scalar values
395  else
396  {
397  ScalarType innerRange = max2ndValue - min2ndValue;
398 
399  if (minCountFraction > 0.2)
400  {
401  ScalarType halfInnerRangeGapMinValue = min2ndValue - innerRange / 2.0;
402  minValue = std::max(minValue, halfInnerRangeGapMinValue);
403  }
404  else
405  {
406  minValue = min2ndValue;
407  }
408 
409  if (maxCountFraction > 0.2)
410  {
411  ScalarType halfInnerRangeGapMaxValue = max2ndValue + innerRange / 2.0;
412  maxValue = std::min(maxValue, halfInnerRangeGapMaxValue);
413  }
414  else
415  {
416  maxValue = max2ndValue;
417  }
418  }
419  SetWindowBounds(minValue, maxValue);
420  SetDefaultLevelWindow((maxValue - minValue) / 2 + minValue, maxValue - minValue);
421 }
422 
424 {
425  if (IsFixed())
426  return;
427 
428  if (image == nullptr || !image->IsInitialized())
429  return;
430 
431  ScalarType minValue = image->GetStatistics()->GetScalarValueMin(0);
432  if (!std::isfinite(minValue))
433  {
434  minValue = image->GetStatistics()->GetScalarValue2ndMinNoRecompute(0);
435  }
436  ScalarType maxValue = image->GetStatistics()->GetScalarValueMaxNoRecompute(0);
437  if (!std::isfinite(maxValue))
438  {
439  maxValue = image->GetStatistics()->GetScalarValue2ndMaxNoRecompute(0);
440  }
441 
442  SetRangeMinMax(minValue, maxValue);
443  SetDefaultBoundaries(minValue, maxValue);
444  SetWindowBounds(minValue, maxValue);
445  SetDefaultLevelWindow((maxValue - minValue) / 2 + minValue, maxValue - minValue);
446 }
447 
449 {
450  m_Fixed = fixed;
451 }
452 
454 {
455  return m_Fixed;
456 }
457 
459 {
460  return m_Fixed;
461 }
462 
464 {
465  return m_IsFloatingImage;
466 }
467 
469 {
470  m_IsFloatingImage = value;
471 }
472 
474 {
475  return mitk::Equal(this->m_RangeMin, levWin.m_RangeMin, mitk::sqrteps) &&
481  m_Fixed == levWin.IsFixed() && m_IsFloatingImage == levWin.IsFloatingValues();
482 }
483 
485 {
486  return !((*this) == levWin);
487 }
488 
490 {
491  if (this == &levWin)
492  {
493  return *this;
494  }
495  else
496  {
497  m_RangeMin = levWin.GetRangeMin();
498  m_RangeMax = levWin.GetRangeMax();
503  m_Fixed = levWin.GetFixed();
505  return *this;
506  }
507 }
void SetWindowBounds(ScalarType lowerBound, ScalarType upperBound, bool expandRangesIfNecessary=true)
ScalarType m_DefaultLowerBound
virtual bool operator!=(const LevelWindow &levWin) const
non equality operator implementation that allows to compare two level windows
LevelWindow(ScalarType level=127.5, ScalarType window=255.0)
ScalarType GetLevel() const
method that returns the level value, i.e. the center of the current grey value interval ...
float k(1.0)
void ResetDefaultLevelWindow()
Resets the level and the window value to the default values.
void SetFixed(bool fixed)
const mitk::PixelType GetPixelType(int n=0) const
Returns the PixelType of channel n.
Definition: mitkImage.cpp:101
double ScalarType
ScalarType m_DefaultUpperBound
void SetToImageRange(const Image *image)
sets level/window to the min/max greyvalues of the given Image
unsigned int * GetDimensions() const
Get the sizes of all dimensions as an integer-array.
Definition: mitkImage.cpp:1309
virtual mitk::ScalarType GetScalarValue2ndMaxNoRecompute(unsigned int t=0)
Get the second largest value for scalar images, but do not recompute it first.
static void Update(vtkPolyData *)
Definition: mitkSurface.cpp:31
ScalarType GetDefaultUpperBound() const
static Pointer New()
StatisticsHolderPointer GetStatistics() const
Returns a pointer to the ImageStatisticsHolder object that holds all statistics information for the i...
Definition: mitkImage.h:646
virtual mitk::ScalarType GetScalarValueMaxNoRecompute(unsigned int t=0)
Get the largest value for scalar images, but do not recompute it first.
virtual unsigned int GetCountOfMaxValuedVoxelsNoRecompute(unsigned int t=0)
Get the count of voxels with the largest scalar value in the dataset.
vcl_size_t GetBpe() const
Get the number of bits per element (of an element)
ScalarType GetDefaultLowerBound() const
void SetRangeMinMax(ScalarType min, ScalarType max)
The LevelWindow class Class to store level/window values.
virtual ScalarType GetScalarValueMin(int t=0, unsigned int component=0)
Get the minimum for scalar images. Recomputation performed only when necessary.
int GetComponentType() const
Get the component type (the scalar (!) type). Each element may contain m_NumberOfComponents (more tha...
virtual LevelWindow & operator=(const LevelWindow &levWin)
implementation necessary because operator made private in itk::Object
void SetFloatingValues(bool value)
Sets the floating image value.
void SetDefaultLevelWindow(ScalarType level, ScalarType window)
void ResetDefaultRangeMinMax()
the default min and max range for image will be reset
unsigned int GetDimension() const
Get dimension of the image.
Definition: mitkImage.cpp:106
ScalarType GetUpperWindowBound() const
ScalarType GetRange() const
returns the size of the grey value range
Image class for storing images.
Definition: mitkImage.h:72
void SetAuto(const Image *image, bool tryPicTags=true, bool guessByCentralSlice=true, unsigned selectedComponent=0)
sets level/window to optimize the contrast of the given Image
ScalarType m_UpperWindowBound
ScalarType GetDefaultWindow() const
returns the default window size for the image
itk::ImageIOBase::IOPixelType GetPixelType() const
static T max(T x, T y)
Definition: svm.cpp:56
mitk::Image::Pointer image
ScalarType GetRangeMax() const
ScalarType GetWindow() const
returns the current window size, i.e the range size of the current grey value interval ...
static T min(T x, T y)
Definition: svm.cpp:53
MITKCORE_EXPORT const ScalarType sqrteps
void SetDefaultBoundaries(ScalarType low, ScalarType up)
MITKNEWMODULE_EXPORT bool Equal(mitk::ExampleDataStructure *leftHandSide, mitk::ExampleDataStructure *rightHandSide, mitk::ScalarType eps, bool verbose)
Returns true if the example data structures are considered equal.
virtual unsigned int GetCountOfMinValuedVoxelsNoRecompute(unsigned int t=0) const
Get the count of voxels with the smallest scalar value in the dataset.
ScalarType m_LowerWindowBound
virtual bool IsInitialized() const
Check whether the data has been initialized, i.e., at least the Geometry and other header data has be...
static void swap(T &x, T &y)
Definition: svm.cpp:58
ScalarType GetDefaultLevel() const
method returns the default level value for the image
ScalarType GetRangeMin() const
virtual bool operator==(const LevelWindow &levWin) const
equality operator implementation that allows to compare two level windows
void SetLevelWindow(ScalarType level, ScalarType window, bool expandRangesIfNecessary=true)
ScalarType GetLowerWindowBound() const
virtual mitk::ScalarType GetScalarValue2ndMinNoRecompute(unsigned int t=0) const
Get the second smallest value for scalar images, but do not recompute it first.
bool IsFloatingValues() const
Shows if floating values are accepted.