00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "mitkLevelWindow.h"
00020 #include "mitkImageSliceSelector.h"
00021
00022 #include <ipFunc/mitkIpFunc.h>
00023 #include <mitkIpPic.h>
00024 #include <algorithm>
00025
00026 void mitk::LevelWindow::EnsureConsistency()
00027 {
00028
00029 {
00030 if ( m_RangeMin > m_RangeMax )
00031 std::swap(m_RangeMin,m_RangeMax);
00032 if (m_RangeMin == m_RangeMax )
00033 m_RangeMin = m_RangeMax - 1;
00034 }
00035
00036
00037 {
00038 if ( m_LowerWindowBound > m_UpperWindowBound )
00039 std::swap(m_LowerWindowBound,m_UpperWindowBound);
00040
00041 if ( m_LowerWindowBound < m_RangeMin ) m_LowerWindowBound = m_RangeMin;
00042 if ( m_UpperWindowBound < m_RangeMin ) m_UpperWindowBound = m_RangeMin;
00043 if ( m_LowerWindowBound > m_RangeMax ) m_LowerWindowBound = m_RangeMax;
00044 if ( m_UpperWindowBound > m_RangeMax ) m_UpperWindowBound = m_RangeMax;
00045
00046 if (m_LowerWindowBound == m_UpperWindowBound )
00047 {
00048 if(m_LowerWindowBound == m_RangeMin )
00049 m_UpperWindowBound++;
00050 else
00051 m_LowerWindowBound--;
00052 }
00053 }
00054 }
00055
00056 mitk::LevelWindow::LevelWindow(mitk::ScalarType level, mitk::ScalarType window)
00057 : m_LowerWindowBound( level - window / 2.0 ), m_UpperWindowBound( level + window / 2.0 ),
00058 m_RangeMin( -2048.0 ), m_RangeMax( 4096.0 ),
00059 m_DefaultLowerBound( -2048.0 ), m_DefaultUpperBound( 4096.0 ),
00060 m_Fixed( false )
00061 {
00062 SetDefaultLevelWindow(level, window);
00063 }
00064
00065 mitk::LevelWindow::LevelWindow(const mitk::LevelWindow& levWin)
00066 : m_LowerWindowBound( levWin.GetLowerWindowBound() )
00067 , m_UpperWindowBound( levWin.GetUpperWindowBound() )
00068 , m_RangeMin( levWin.GetRangeMin() )
00069 , m_RangeMax( levWin.GetRangeMax() )
00070 , m_DefaultLowerBound( levWin.GetDefaultLowerBound() )
00071 , m_DefaultUpperBound( levWin.GetDefaultUpperBound() )
00072 , m_Fixed( levWin.GetFixed() )
00073 {
00074 }
00075
00076 mitk::LevelWindow::~LevelWindow()
00077 {
00078 }
00079
00080 mitk::ScalarType mitk::LevelWindow::GetLevel() const
00081 {
00082 return (m_UpperWindowBound-m_LowerWindowBound) / 2.0 + m_LowerWindowBound;
00083 }
00084
00085 mitk::ScalarType mitk::LevelWindow::GetWindow() const
00086 {
00087 return (m_UpperWindowBound-m_LowerWindowBound);
00088 }
00089
00090 mitk::ScalarType mitk::LevelWindow::GetDefaultLevel() const
00091 {
00092 return ((m_DefaultUpperBound+m_DefaultLowerBound)/2.0);
00093 }
00094
00095 mitk::ScalarType mitk::LevelWindow::GetDefaultWindow() const
00096 {
00097 return ((m_DefaultUpperBound-m_DefaultLowerBound));
00098 }
00099
00100 void mitk::LevelWindow::ResetDefaultLevelWindow()
00101 {
00102 SetLevelWindow(GetDefaultLevel(), GetDefaultWindow());
00103 }
00104
00105 mitk::ScalarType mitk::LevelWindow::GetLowerWindowBound() const
00106 {
00107 return m_LowerWindowBound;
00108 }
00109
00110 mitk::ScalarType mitk::LevelWindow::GetUpperWindowBound() const
00111 {
00112 return m_UpperWindowBound;
00113 }
00114
00115 void mitk::LevelWindow::SetDefaultLevelWindow(mitk::ScalarType level, mitk::ScalarType window)
00116 {
00117 SetDefaultBoundaries((level-(window/2)), (level+(window/2)));
00118 }
00119
00120 void mitk::LevelWindow::SetLevelWindow(mitk::ScalarType level, mitk::ScalarType window)
00121 {
00122 SetWindowBounds((level-(window/2.0)), (level+(window/2.0)));
00123 }
00124
00125 void mitk::LevelWindow::SetWindowBounds(mitk::ScalarType lowerBound, mitk::ScalarType upperBound)
00126 {
00127 if ( IsFixed() ) return;
00128 m_LowerWindowBound = lowerBound;
00129 m_UpperWindowBound = upperBound;
00130 EnsureConsistency();
00131 }
00132
00133 void mitk::LevelWindow::SetRangeMinMax(mitk::ScalarType min, mitk::ScalarType max)
00134 {
00135 if ( IsFixed() ) return;
00136 m_RangeMin = min;
00137 m_RangeMax = max;
00138 EnsureConsistency();
00139 }
00140
00141 void mitk::LevelWindow::SetDefaultBoundaries(mitk::ScalarType low, mitk::ScalarType up)
00142 {
00143 if ( IsFixed() ) return;
00144 m_DefaultLowerBound = low;
00145 m_DefaultUpperBound = up;
00146
00147 {
00148 if ( m_DefaultLowerBound > m_DefaultUpperBound )
00149 std::swap(m_DefaultLowerBound,m_DefaultUpperBound);
00150
00151 if (m_DefaultLowerBound == m_DefaultUpperBound )
00152 m_DefaultLowerBound--;
00153 }
00154 EnsureConsistency();
00155 }
00156
00157 void mitk::LevelWindow::SetToMaxWindowSize()
00158 {
00159 SetWindowBounds( m_RangeMin , m_RangeMax );
00160 }
00161
00162 mitk::ScalarType mitk::LevelWindow::GetRangeMin() const
00163 {
00164 return m_RangeMin;
00165 }
00166
00167 mitk::ScalarType mitk::LevelWindow::GetRangeMax() const
00168 {
00169 return m_RangeMax;
00170 }
00171
00172 mitk::ScalarType mitk::LevelWindow::GetRange() const
00173 {
00174 return m_RangeMax - m_RangeMin;
00175 }
00176
00177 mitk::ScalarType mitk::LevelWindow::GetDefaultUpperBound() const
00178 {
00179 return m_DefaultUpperBound;
00180 }
00181
00182 mitk::ScalarType mitk::LevelWindow::GetDefaultLowerBound() const
00183 {
00184 return m_DefaultLowerBound;
00185 }
00186
00187 void mitk::LevelWindow::ResetDefaultRangeMinMax()
00188 {
00189 SetRangeMinMax(m_DefaultLowerBound, m_DefaultUpperBound);
00190 }
00191
00228 void mitk::LevelWindow::SetAuto(const mitk::Image* image, bool tryPicTags, bool guessByCentralSlice)
00229 {
00230 if ( IsFixed() )
00231 return;
00232
00233 if ( image == NULL || !image->IsInitialized() ) return;
00234
00235 const mitk::Image* wholeImage = image;
00236 ScalarType minValue = 0.0;
00237 ScalarType maxValue = 0.0;
00238 ScalarType min2ndValue = 0.0;
00239 ScalarType max2ndValue = 0.0;
00240 mitk::ImageSliceSelector::Pointer sliceSelector = mitk::ImageSliceSelector::New();
00241 if ( guessByCentralSlice )
00242 {
00243 sliceSelector->SetInput(image);
00244 sliceSelector->SetSliceNr(image->GetDimension(2)/2);
00245 sliceSelector->SetTimeNr(image->GetDimension(3)/2);
00246 sliceSelector->SetChannelNr(image->GetDimension(4)/2);
00247 sliceSelector->Update();
00248 image = sliceSelector->GetOutput();
00249 if ( image == NULL || !image->IsInitialized() ) return;
00250
00251 minValue = image->GetScalarValueMin();
00252 maxValue = image->GetScalarValueMaxNoRecompute();
00253 min2ndValue = image->GetScalarValue2ndMinNoRecompute();
00254 max2ndValue = image->GetScalarValue2ndMaxNoRecompute();
00255 if ( minValue == maxValue )
00256 {
00257
00258 image = wholeImage;
00259 minValue = image->GetScalarValueMin();
00260 maxValue = image->GetScalarValueMaxNoRecompute();
00261 min2ndValue = image->GetScalarValue2ndMinNoRecompute();
00262 max2ndValue = image->GetScalarValue2ndMaxNoRecompute();
00263 }
00264 }
00265 else
00266 {
00267 const_cast<Image*>(image)->Update();
00268 minValue = image->GetScalarValueMin(0);
00269 maxValue = image->GetScalarValueMaxNoRecompute(0);
00270 min2ndValue = image->GetScalarValue2ndMinNoRecompute(0);
00271 max2ndValue = image->GetScalarValue2ndMaxNoRecompute(0);
00272 for (unsigned int i = 1; i < image->GetDimension(3); ++i)
00273 {
00274 ScalarType minValueTemp = image->GetScalarValueMin(i);
00275 if (minValue > minValueTemp)
00276 minValue = minValueTemp;
00277 ScalarType maxValueTemp = image->GetScalarValueMaxNoRecompute(i);
00278 if (maxValue < maxValueTemp)
00279 maxValue = maxValueTemp;
00280 ScalarType min2ndValueTemp = image->GetScalarValue2ndMinNoRecompute(i);
00281 if (min2ndValue > min2ndValueTemp)
00282 min2ndValue = min2ndValueTemp;
00283 ScalarType max2ndValueTemp = image->GetScalarValue2ndMaxNoRecompute(i);
00284 if (max2ndValue > max2ndValueTemp)
00285 max2ndValue = max2ndValueTemp;
00286 }
00287 }
00288
00289
00290 if (image->GetPixelType().GetType() == mitkIpPicInt && image->GetPixelType().GetBpe() >= 8)
00291 {
00292 if (minValue == -(pow((double)2.0,image->GetPixelType().GetBpe())/2))
00293 {
00294 minValue = min2ndValue;
00295 }
00296 }
00297
00298
00300 if ( minValue == maxValue )
00301 {
00302 minValue = maxValue-1;
00303 }
00304 SetRangeMinMax(minValue, maxValue);
00305 SetDefaultBoundaries(minValue, maxValue);
00306
00307 if ( tryPicTags )
00308 {
00309 if ( SetAutoByPicTags(const_cast<Image*>(image)->GetPic()) )
00310 {
00311 return;
00312 }
00313 }
00314
00315
00316 unsigned int numPixelsInDataset = image->GetDimensions()[0];
00317 for ( unsigned int k=0; k<image->GetDimension(); ++k ) numPixelsInDataset *= image->GetDimensions()[k];
00318 unsigned int minCount = image->GetCountOfMinValuedVoxelsNoRecompute();
00319 unsigned int maxCount = image->GetCountOfMaxValuedVoxelsNoRecompute();
00320 float minCountFraction = minCount/float(numPixelsInDataset);
00321 float maxCountFraction = maxCount/float(numPixelsInDataset);
00322
00324 if ( min2ndValue == maxValue )
00325 {
00326
00327 }
00328
00330 else if ( min2ndValue == max2ndValue )
00331 {
00332 ScalarType minDelta = std::min(min2ndValue-minValue, maxValue-min2ndValue);
00333 minValue = min2ndValue - minDelta;
00334 maxValue = min2ndValue + minDelta;
00335 }
00336
00337
00338 else
00339 {
00340 ScalarType innerRange = max2ndValue - min2ndValue;
00341
00342 if ( minCountFraction > 0.2 )
00343 {
00344 ScalarType halfInnerRangeGapMinValue = min2ndValue - innerRange/2.0;
00345 minValue = std::max(minValue, halfInnerRangeGapMinValue);
00346 }
00347 else
00348 {
00349 minValue = min2ndValue;
00350 }
00351
00352 if ( maxCountFraction > 0.2 )
00353 {
00354 ScalarType halfInnerRangeGapMaxValue = max2ndValue + innerRange/2.0;
00355 maxValue = std::min(maxValue, halfInnerRangeGapMaxValue);
00356 }
00357 else
00358 {
00359 maxValue = max2ndValue;
00360 }
00361 }
00362 SetWindowBounds(minValue, maxValue);
00363 SetDefaultLevelWindow((maxValue - minValue) / 2 + minValue, maxValue - minValue);
00364 }
00365
00366 bool mitk::LevelWindow::SetAutoByPicTags(const mitkIpPicDescriptor* aPic)
00367 {
00368 if ( IsFixed() )
00369 return false;
00370
00371 mitkIpPicDescriptor* pic = const_cast<mitkIpPicDescriptor*>(aPic);
00372 if ( pic == NULL )
00373 {
00374 return false;
00375 }
00376 mitkIpPicTSV_t *tsv = mitkIpPicQueryTag( pic, "LEVEL/WINDOW" );
00377 if( tsv != NULL )
00378 {
00379 double level = 0;
00380 double window = 0;
00381 #define GET_C_W( type, tsv, C, W ) \
00382 level = ((type *)tsv->value)[0]; \
00383 window = ((type *)tsv->value)[1];
00384
00385 mitkIpPicFORALL_2( GET_C_W, tsv, level, window );
00386
00387 ScalarType min = GetRangeMin();
00388 ScalarType max = GetRangeMax();
00389 if ((double)(GetRangeMin()) > (level - window/2))
00390 {
00391 min = level - window/2;
00392 }
00393 if ((double)(GetRangeMax()) < (level + window/2))
00394 {
00395 max = level + window/2;
00396 }
00397 SetRangeMinMax(min, max);
00398 SetDefaultBoundaries(min, max);
00399 SetLevelWindow( level, window );
00400 return true;
00401 }
00402 return false;
00403 }
00404
00405 void mitk::LevelWindow::SetFixed( bool fixed )
00406 {
00407 m_Fixed = fixed;
00408 }
00409
00410 bool mitk::LevelWindow::GetFixed() const
00411 {
00412 return m_Fixed;
00413 }
00414
00415 bool mitk::LevelWindow::IsFixed() const
00416 {
00417 return m_Fixed;
00418 }
00419
00420 bool mitk::LevelWindow::operator==(const mitk::LevelWindow& levWin) const
00421 {
00422 if ( m_RangeMin == levWin.GetRangeMin() &&
00423 m_RangeMax == levWin.GetRangeMax() &&
00424 m_LowerWindowBound == levWin.GetLowerWindowBound() && m_UpperWindowBound == levWin.GetUpperWindowBound() &&
00425 m_DefaultLowerBound == levWin.GetDefaultLowerBound() && m_DefaultUpperBound == levWin.GetDefaultUpperBound() && m_Fixed == levWin.IsFixed() ) {
00426
00427 return true;
00428 }
00429 else {
00430 return false;
00431 }
00432 }
00433
00434 bool mitk::LevelWindow::operator!=(const mitk::LevelWindow& levWin) const
00435 {
00436 return ! ( (*this) == levWin);
00437 }
00438
00439 mitk::LevelWindow& mitk::LevelWindow::operator=(const mitk::LevelWindow& levWin)
00440 {
00441 if (this == &levWin) {
00442 return *this;
00443 }
00444 else {
00445 m_RangeMin = levWin.GetRangeMin();
00446 m_RangeMax = levWin.GetRangeMax();
00447 m_LowerWindowBound= levWin.GetLowerWindowBound();
00448 m_UpperWindowBound= levWin.GetUpperWindowBound();
00449 m_DefaultLowerBound = levWin.GetDefaultLowerBound();
00450 m_DefaultUpperBound = levWin.GetDefaultUpperBound();
00451 m_Fixed = levWin.GetFixed();
00452 return *this;
00453 }
00454 }