+/*# ---------------------------------------------------------------------
+#
+# Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
+# pour la Sant�)
+# Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
+# Previous Authors : Laurent Guigues, Jean-Pierre Roux
+# CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
+#
+# This software is governed by the CeCILL-B license under French law and
+# abiding by the rules of distribution of free software. You can use,
+# modify and/ or redistribute the software under the terms of the CeCILL-B
+# license as circulated by CEA, CNRS and INRIA at the following URL
+# http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+# or in the file LICENSE.txt.
+#
+# As a counterpart to the access to the source code and rights to copy,
+# modify and redistribute granted by the license, users are provided only
+# with a limited warranty and the software's author, the holder of the
+# economic rights, and the successive licensors have only limited
+# liability.
+#
+# The fact that you are presently reading this means that you have had
+# knowledge of the CeCILL-B license and that you accept its terms.
+# ------------------------------------------------------------------------ */
/**
* \file
- * \brief Class bbtk::ThresholdImageView .
+ * \author Eduardo Davila and Claire Mouton.
+ * \brief Class bbtk::ThresholdImageView.
+ * \date September 2012
*/
#include "ColorLayerImageView.h"
#include <vtkLookupTable.h>
#include <vtkImageData.h>
+#include <algorithm>
- //=========================================================================
- //=========================================================================
- //=========================================================================
- //=========================================================================
- ColorLayerImageView::ColorLayerImageView( )
- {
- }
- //=========================================================================
- ColorLayerImageView::~ColorLayerImageView()
- {
- }
- //=========================================================================
+//=========================================================================
+//=========================================================================
+//=========================================================================
+//=========================================================================
+ColorLayerImageView::ColorLayerImageView( )
+{
+ _z2 = 0;
+ _fix_dynamic = true;
+ _color_type = false;
+}
+
+//=========================================================================
+ColorLayerImageView::~ColorLayerImageView()
+{
+}
+//=========================================================================
//----------------------------------------------------------------------------
-void ColorLayerImageView::ConfigLookupTable() // virtual
+void ColorLayerImageView::SetSliceFixDynamic(bool fix_dynamic)
{
- double range[2];
-
- GetImage()->GetScalarRange(range);
- if (range[1]==0)
+ _fix_dynamic = fix_dynamic;
+}
+
+//----------------------------------------------------------------------------
+void ColorLayerImageView::SetX2(int x2)
+{
+ _x2 = x2;
+}
+
+//----------------------------------------------------------------------------
+void ColorLayerImageView::SetY2(int y2)
+{
+ _y2 = y2;
+}
+
+
+//----------------------------------------------------------------------------
+void ColorLayerImageView::SetZ2(int z2)
+{
+ _z2 = z2;
+}
+
+//----------------------------------------------------------------------------
+int ColorLayerImageView::GetX() // virtual
+{
+ int result=0;
+ if (_fix_dynamic==false)
+ {
+ result = _x2;
+ }
+ else
+ {
+ result = LayerImageBase::GetX();
+ }
+
+ return result;
+}
+
+//----------------------------------------------------------------------------
+int ColorLayerImageView::GetY() // virtual
+{
+ int result=0;
+ if (_fix_dynamic==false)
+ {
+ result = _y2;
+ }
+ else
+ {
+ result = LayerImageBase::GetY();
+ }
+
+ return result;
+}
+
+//----------------------------------------------------------------------------
+int ColorLayerImageView::GetZ() // virtual
+{
+ int result=0;
+ if (_fix_dynamic==false)
+ {
+ result = _z2;
+ }
+ else
+ {
+ result = LayerImageBase::GetZ();
+ }
+
+ return result;
+}
+
+//----------------------------------------------------------------------------
+void ColorLayerImageView::SetBaseColors(std::vector<double> & base_color)
+{
+ // The base color vector must be of a size multiple of 3, not null.
+//EED if ((base_color.size() != 0) && (base_color.size() % 3 == 0))
+ if ( base_color.size() % 3 == 0)
+ {
+ _base_color = base_color;
+ } else if (base_color.size() != 0) // Otherwise, an exception should be thrown.
{
- range[1]=255;
+ std::cout << "CM ColorLayerImageView::SetBaseColors : ERROR!!! The base color vector has an inconsistent size. It must be of a size multiple of 3, different from 0, but its size is: "<< base_color.size() << ". Therefore, the default values will be used as base colors." << std::endl;
}
-
- int minTot = floor (range[0]);
- int maxTot = ceil (range[1]);
-
-
- vtkLookupTable* thresholdTable = GetThresholdTable();
- thresholdTable->SetNumberOfTableValues(maxTot+1);
- thresholdTable->SetTableRange(range);
- thresholdTable->SetAlphaRange(0, 1);
- thresholdTable->SetValueRange(0, 1);
- thresholdTable->SetSaturationRange(0, 0);
- thresholdTable->SetRampToLinear( );
-
- //Assign a fake color for the upper image, and set the white as transparent
- int i,ii;
- double iBlue=0 , iYellow=0 , iRed=0;
- double delta=(maxTot-minTot)/3.0;
-
- double delta0=delta*0;
- double delta1=delta*1;
- double delta2=delta*2;
- double delta3=delta*3;
-
-
- for(i = minTot; i <= maxTot; i++)
+}
+
+
+//----------------------------------------------------------------------------
+void ColorLayerImageView::SetBaseTransparence(std::vector<double> & base_transparence)
+{
+ _transparence_level_boundary = base_transparence;
+}
+
+
+//----------------------------------------------------------------------------
+double ColorLayerImageView::GetBaseColors(unsigned int index)
+{
+ if (_base_color.size() > index)
+ return _base_color.at(index);
+ // An exception should be thrown if the index does not exist in the color vector.
+ else
+ {
+ std::cout << "CM ColorLayerImageView::GetBaseColors : ERROR!!! The index " << index << "is out of the base color vector range." << std ::endl;
+ return -1.0;
+ }
+}
+
+//----------------------------------------------------------------------------
+void ColorLayerImageView::SetGreyLevelBoundaries(std::vector<double> & grey_level_boundary)
+{
+ _grey_level_boundary = grey_level_boundary;
+
+//EED 2017 / 11 / 27
+/*
+ // The size must be greater than or equal to 2 (at least min and max must exist).
+ if ( grey_level_boundary.size() >= 2)
+ {
+ sort ( grey_level_boundary.begin(), grey_level_boundary.end() );
+ _grey_level_boundary = grey_level_boundary;
+ }
+ // Otherwise, an exception should be thrown.
+ else if (grey_level_boundary.size() != 0)
+ std::cout << "CM ColorLayerImageView::SetGreyLevelBoundaries : ERROR!!! The grey level boundaries vector has an inconsistent size. It must be of a size greater than or equal to 2 (at least min and max must exist), but its size is: " << grey_level_boundary.size() << ". Therefore, the histogram will be equally split." << std::endl;
+*/
+
+}
+
+//----------------------------------------------------------------------------
+double ColorLayerImageView::GetGreyLevelBoundaries(unsigned int index)
+{
+ if (_grey_level_boundary.size() > index)
+ return _grey_level_boundary.at(index);
+ // An exception should be thrown if the index does not exist in the grey level boundary vector.
+ else
+ {
+ std::cout << "CM ColorLayerImageView::GetGreyLevelBoundaries : ERROR!!! The index " << index << "is out of the grey level boundaries vector range." << std ::endl;
+ return -1.0;
+ }
+}
+
+//----------------------------------------------------------------------------
+void ColorLayerImageView::SetPlainOrGradientColor(bool color_type)
+{
+ _color_type = color_type;
+}
+
+//----------------------------------------------------------------------------
+int ColorLayerImageView::GetBaseColorNb()
+{
+ return _base_color.size()/3;
+}
+
+//----------------------------------------------------------------------------
+void ColorLayerImageView::SetDefaultGreyLevelBoundary()
+{
+
+ // CM Sets the default behaviour concerning the lookup table keeping the base colors already set.
+ _grey_level_boundary.clear();
+
+ // This avoids a potential division by 0 through delta during the lookup table configuration.
+ if (_range[1]==0)
+ {
+ _range[1]=255;
+ }
+
+ int i;
+ double delta;
+ // Grey level extrema are set by default to the image grey level extrema.
+ double minTot = _range[0];
+ double maxTot = _range[1];
+
+ if (_color_type)
{
- ii=i-minTot;
- if ((ii>=delta0) && (ii<=delta1)) // iBlue
- {
- thresholdTable->SetTableValue( i , 0 , 0 , iBlue/delta , 1);
- iBlue++;
- }
- if ((ii>=delta1) && (ii<=delta2)) // iYellow
+ delta = (maxTot - minTot)/GetBaseColorNb();
+ // By default, the histogram is split into BaseColorNb areas of equal width.
+ for (i = 0; i <= GetBaseColorNb() ; i ++)
+ {
+ _grey_level_boundary.push_back(minTot + i * delta);
+ } // for
+ } else {
+ delta = (maxTot - minTot)/(GetBaseColorNb()-1);
+ for (i = 0; i < GetBaseColorNb() ; i ++)
+ {
+ _grey_level_boundary.push_back(minTot + i * delta);
+ } // for
+ } // if
+}
+
+//----------------------------------------------------------------------------
+void ColorLayerImageView::SetDefaultBaseColorAndGreyLevelBoundary()
+{
+
+ // CM Sets the default behaviour concerning the lookup table.
+ _grey_level_boundary.clear();
+ _base_color.clear();
+ // Base colors are set to blue, yellow and red.
+ // Blue.
+ _base_color.push_back(0.0);
+ _base_color.push_back(0.0);
+ _base_color.push_back(0.5);
+
+ _base_color.push_back(0.0);
+ _base_color.push_back(0.0);
+ _base_color.push_back(1.0);
+
+ _base_color.push_back(0.0);
+ _base_color.push_back(1.0);
+ _base_color.push_back(1.0);
+
+ _base_color.push_back(1.0);
+ _base_color.push_back(1.0);
+ _base_color.push_back(0.0);
+
+ _base_color.push_back(1.0);
+ _base_color.push_back(0.0);
+ _base_color.push_back(0.0);
+
+ _base_color.push_back(0.5);
+ _base_color.push_back(0.0);
+ _base_color.push_back(0.0);
+
+
+ // This avoids a potential division by 0 through delta during the lookup table configuration.
+ if (_range[1]==0)
+ {
+ _range[1]=255;
+ }
+
+// double minTot = floor (_range[0]);
+// double maxTot = ceil (_range[1]);
+ double minTot = _range[0];
+ double maxTot = _range[1];
+
+ double delta = (maxTot - minTot)/8.0;
+ // By default, the histogram is split into three areas of equal width.
+
+ _grey_level_boundary.push_back(minTot + delta*0);
+ _grey_level_boundary.push_back(minTot + delta*1);
+// _grey_level_boundary.push_back(minTot + delta*2);
+ _grey_level_boundary.push_back(minTot + delta*3);
+// _grey_level_boundary.push_back(minTot + delta*4);
+ _grey_level_boundary.push_back(minTot + delta*5);
+ // _grey_level_boundary.push_back(minTot + delta*6);
+ _grey_level_boundary.push_back(minTot + delta*7);
+ _grey_level_boundary.push_back(minTot + delta*8);
+}
+
+//----------------------------------------------------------------------------
+void ColorLayerImageView::ConfigLookupTable() // virtual
+{
+
+ // CM 2014
+ // EED 28/01/2015
+ // Grey level extrema retrieved from the image grey level extrema.
+//EED 20 oct 2015
+// GetImage()->GetScalarRange(_range);
+ GetImageScalarRange();
+ double minRange = _range[0];
+ double maxRange = _range[1];
+
+ // ------------------ Setting Default Values
+ // Checks the size consistency of vectors _base_color and _grey_level_boundary.
+ // In case of inconsistency, an exception should be thrown. Instead, the default values are set.
+
+ if (GetBaseColorNb() == 0)
+ {
+ SetDefaultBaseColorAndGreyLevelBoundary();
+ } else { // If at least one color has been set, set the grey level boundaries to build an equipartition of the image grey levels, keeping the base colors defined.
+ if (_color_type==true) // Plain
+ {
+ if (GetBaseColorNb() != (int)_grey_level_boundary.size()-1)
+ {
+//EED std::cout << "CM ColorLayerImageView::ConfigLookupTable : ERROR!!! Inconsistency between the sizes of vectors _base_color and _grey_level_boundary. _base_color.size()/3 (=" <<_base_color.size()/3 << ") should be equal to _grey_level_boundary.size()+1 (=" << _grey_level_boundary.size()<<"+1)." << std::endl;
+//EED std::cout << "CM The default values for the base colors and the grey level boundaries will be set." << std::endl;
+ SetDefaultGreyLevelBoundary();
+ } // if
+ } // _color_type
+
+ if (_color_type==false) // Gradiant
+ {
+ if (GetBaseColorNb() != (int)_grey_level_boundary.size())
+ {
+//EED std::cout << "CM ColorLayerImageView::ConfigLookupTable : ERROR!!! Inconsistency between the sizes of vectors _base_color and _grey_level_boundary. _base_color.size()/3 (=" <<_base_color.size()/3 << ") should be equal to _grey_level_boundary.size() (=" << _grey_level_boundary.size()<<")." << std::endl;
+//EED std::cout << "CM The default values for the base colors and the grey level boundaries will be set." << std::endl;
+ SetDefaultGreyLevelBoundary();
+ } // if
+ } // _color_type
+
+ }
+ // ------------------ End Of Setting Default Values
+
+ int iTransparence,transparenceSize = _transparence_level_boundary.size();
+ for (iTransparence=transparenceSize ; iTransparence < GetBaseColorNb(); iTransparence++ )
+ {
+ _transparence_level_boundary.push_back(1);
+ }
+
+
+ // ------------------ Defining the Threshold Table
+ vtkLookupTable* thresholdTable = GetThresholdTable();
+
+ double thresholdTable_range[2];
+ double r1,r2,g1,g2,b1,b2,t1,t2;
+ int start,end;
+
+ // CM Number of table values consistent with the effective number of values (see loop below).
+ thresholdTable_range[1]= std::max( GetGreyLevelBoundaries( _grey_level_boundary.size()-1 ) , ceil(maxRange) );
+ thresholdTable_range[0]= std::min( GetGreyLevelBoundaries(0), floor(minRange) );
+
+ thresholdTable_range[1]= GetGreyLevelBoundaries( _grey_level_boundary.size()-1 );
+ thresholdTable_range[0]= GetGreyLevelBoundaries(0);
+
+ thresholdTable->SetTableRange(thresholdTable_range);
+ thresholdTable->SetAlphaRange( 0,1 );
+ thresholdTable->SetValueRange( 0,1 );
+
+ thresholdTable->SetSaturationRange( 0,0 );
+ thresholdTable->SetRampToLinear( );
+
+ maxColorsThresholdTable = 1000;
+ thresholdTable->SetNumberOfTableValues( maxColorsThresholdTable+1 );
+ thresholdTable->SetNanColor(0,0,0,0);
+
+
+ // Defines the lookup table.
+ // If the image has a degradation in one (or both) extremum (lower or higher),
+ // sets the corresponding grey levels as transparent white in the lookup table.
+
+ // _color_type true, i.e. plain colors.
+ // Sets the plain color for each grey level interval.
+ if (_color_type) // Plain
+ {
+ if ( minRange<GetGreyLevelBoundaries(0) )
+ {
+ start = 0;
+ end = GrayLevel_TO_colorTableIndex( GetGreyLevelBoundaries(0) );
+ FillColorTable(start,end, 0,0,0, 0,0,0, 0,0);
+ }
+
+ if ( maxRange>GetGreyLevelBoundaries( _grey_level_boundary.size()-1 ) )
+ {
+ start = GrayLevel_TO_colorTableIndex( GetGreyLevelBoundaries( _grey_level_boundary.size()-1 ) );
+ end = GrayLevel_TO_colorTableIndex( maxRange );
+ FillColorTable(start,end, 0,0,0, 0,0,0, 0,0);
+ }
+ for (int iColor = 0; iColor < GetBaseColorNb(); iColor++)
{
- thresholdTable->SetTableValue( i , iYellow/delta , iYellow/delta , (delta-iYellow)/delta , 1);
- iYellow++;
- }
- if ((ii>=delta2) && (ii<=delta3)) // iRed
+ r1 = GetBaseColors(iColor*3+0);
+ g1 = GetBaseColors(iColor*3+1);
+ b1 = GetBaseColors(iColor*3+2);
+ start = GrayLevel_TO_colorTableIndex( GetGreyLevelBoundaries(iColor) );
+ end = GrayLevel_TO_colorTableIndex( GetGreyLevelBoundaries(iColor+1) );
+ t1 = _transparence_level_boundary[iColor];
+// t2 = _transparence_level_boundary[iColor+1];
+ FillColorTable(start,end, r1,g1,b1,r1,g1,b1,t1,t1);
+ } // for i
+ } else { // _color_type false, i.e. gradient color
+ if (GetBaseColorNb() > 1)
{
- thresholdTable->SetTableValue( i , 1 , (delta-iRed)/delta , 0 , 1);
- iRed++;
- }
- } // for
+ for (int iColor = 0; iColor < GetBaseColorNb()-1; iColor++)
+ {
+ r1 = GetBaseColors( (iColor+0)*3+0 );
+ g1 = GetBaseColors( (iColor+0)*3+1 );
+ b1 = GetBaseColors( (iColor+0)*3+2 );
+ r2 = GetBaseColors( (iColor+1)*3+0);
+ g2 = GetBaseColors( (iColor+1)*3+1);
+ b2 = GetBaseColors( (iColor+1)*3+2);
+ start = GrayLevel_TO_colorTableIndex( GetGreyLevelBoundaries(iColor) );
+ end = GrayLevel_TO_colorTableIndex( GetGreyLevelBoundaries(iColor+1) );
+ t1 = _transparence_level_boundary[iColor];
+ t2 = _transparence_level_boundary[iColor+1];
+//printf("EED ColorLayerImageView::ConfigLookupTable Make something with transparence \n");
+ FillColorTable( start,end, r1,g1,b1, r2,g2,b2, t1,t2 );
+ }// for
+ } //if
+ } // End Of if (!_color_type)
+
+ double minRangeForColorBar, maxRangeForColorBar;
+ GetRangeForColorBar( minRangeForColorBar, maxRangeForColorBar );
+ thresholdTable->SetRange( minRangeForColorBar, maxRangeForColorBar );
+
+// thresholdTable->SetTableRange( minRange, maxRange );
+// thresholdTable->SetValueRange( 0.0, 1.0 );
+// thresholdTable->SetAboveRangeColor(0,0,0,0);
+// thresholdTable->SetBelowRangeColor(0,0,0,0);
+
+ thresholdTable->Build( );
+ //EO CM EED
+}
+
+//----------------------------------------------------------------------------
+int ColorLayerImageView::GrayLevel_TO_colorTableIndex( double VALUE )
+{
- thresholdTable->Build( );
+//EED 2017-01-01 Migration VTK7
+#if VTK_MAJOR_VERSION <= 5
+ GetImage()->Update();
+#else
+ //...
+#endif
+
+
+
+//EED 20 oct 2015
+// GetImage()->GetScalarRange(_range);
+ GetImageScalarRange();
+
+ double minRange = _range[0];
+ double maxRange = _range[1];
+ return maxColorsThresholdTable * (VALUE-minRange) / (maxRange-minRange);
}
+//----------------------------------------------------------------------------
+void ColorLayerImageView::FillColorTable(int start, int end, double r1, double g1, double b1, double r2, double g2, double b2, double t1, double t2)
+{
+ vtkLookupTable* thresholdTable = GetThresholdTable();
+ int iTable;
+ double delta = end-start;
+ double dr = (r2-r1)/delta;
+ double dg = (g2-g1)/delta;
+ double db = (b2-b1)/delta;
+ double dt = (t2-t1)/delta;
+ for (iTable=0; iTable<=delta; iTable++)
+ {
+ thresholdTable->SetTableValue( iTable+start , r1+dr*iTable, g1+dg*iTable, b1+db*iTable,t1+dt*iTable);
+ } // for iTable
+}
// EOF