/*========================================================================= Program: Visualization Toolkit Module: vtkLookupTable.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /** * @class vtkLookupTable * @brief map scalar values into colors via a lookup table * * vtkLookupTable is an object that is used by mapper objects to map scalar * values into RGBA (red-green-blue-alpha) color specification, * or RGBA into scalar values. The color table can be created by direct * insertion of color values, or by specifying a hue, saturation, value, and * alpha range and generating a table. * * A special color for NaN values in the data can be specified via * SetNanColor(). In addition, a color for data values below the * lookup table range minimum can be specified with * SetBelowRangeColor(), and that color will be used for values below * the range minimum when UseBelowRangeColor is on. Likewise, a color * for data values above the lookup table range maximum can be * specified with SetAboveRangeColor(), and it is used when * UseAboveRangeColor is on. * * This class behaves differently depending on how \a IndexedLookup is set. * When true, vtkLookupTable enters a mode for representing categorical color maps. * By setting \a IndexedLookup to true, you indicate that the annotated * values are the only valid values for which entries in the color table * should be returned. The colors in the lookup \a Table are assigned * to annotated values by taking the modulus of their index in the list * of annotations. \a IndexedLookup changes the behavior of \a GetIndex, * which in turn changes the way \a MapScalarsThroughTable2 behaves; * when \a IndexedLookup is true, \a MapScalarsThroughTable2 will search for * scalar values in \a AnnotatedValues and use the resulting index to * determine the color. If a scalar value is not present in \a AnnotatedValues, * then \a NanColor will be used. * * @warning * You need to explicitly call Build() when constructing the LUT by hand. * * @sa * vtkLogLookupTable vtkWindowLevelLookupTable */ #ifndef vtkLookupTable_h #define vtkLookupTable_h #include "vtkCommonCoreModule.h" // For export macro #include "vtkScalarsToColors.h" #include "vtkUnsignedCharArray.h" // Needed for inline method #define VTK_RAMP_LINEAR 0 #define VTK_RAMP_SCURVE 1 #define VTK_RAMP_SQRT 2 #define VTK_SCALE_LINEAR 0 #define VTK_SCALE_LOG10 1 class VTKCOMMONCORE_EXPORT vtkLookupTable : public vtkScalarsToColors { public: //@{ /** * Constants for offsets of special colors (e.g., NanColor, BelowRangeColor, * AboveRangeColor) from the maximum index in the lookup table. * These should be considered private and not be used by clients of this class. */ static const vtkIdType REPEATED_LAST_COLOR_INDEX; static const vtkIdType BELOW_RANGE_COLOR_INDEX; static const vtkIdType ABOVE_RANGE_COLOR_INDEX; static const vtkIdType NAN_COLOR_INDEX; static const vtkIdType NUMBER_OF_SPECIAL_COLORS; //@} /** * Construct with range=[0,1]; and hsv ranges set up for rainbow color table * (from red to blue). */ static vtkLookupTable* New(); vtkTypeMacro(vtkLookupTable, vtkScalarsToColors); void PrintSelf(ostream& os, vtkIndent indent) override; //@{ /** * Return true if all of the values defining the mapping have an opacity * equal to 1. */ int IsOpaque() override; int IsOpaque(vtkAbstractArray* scalars, int colorMode, int component) override; //@} /** * Allocate a color table of specified size. * Note that ext is no longer used. */ int Allocate(int sz = 256, int ext = 256); /** * Generate lookup table from hue, saturation, value, alpha min/max values. * Table is built from linear ramp of each value. */ void Build() override; /** * Force the lookup table to regenerate from hue, saturation, value, * and alpha min/max values. Table is built from a linear ramp of * each value. ForceBuild() is useful if a lookup table has been * defined manually (using SetTableValue) and then an application * decides to rebuild the lookup table using the implicit process. */ virtual void ForceBuild(); /** * Copies the "special" colors into the given table. */ void BuildSpecialColors(); //@{ /** * Set the shape of the table ramp to either S-curve, linear, or sqrt. * The default is S-curve, which tails off gradually at either end. * * The equation used for the S-curve is y = (sin((x - 1/2)*pi) + 1)/2, * For an S-curve greyscale ramp, you should set NumberOfTableValues * to 402 (which is 256*pi/2) to provide room for the tails of the ramp. * * The equation for the linear ramp is simply y = x. * * The equation for the SQRT is y = sqrt(x). */ vtkSetMacro(Ramp, int); void SetRampToLinear() { this->SetRamp(VTK_RAMP_LINEAR); } void SetRampToSCurve() { this->SetRamp(VTK_RAMP_SCURVE); } void SetRampToSQRT() { this->SetRamp(VTK_RAMP_SQRT); } vtkGetMacro(Ramp, int); //@} //@{ /** * Set the type of scale to use, linear or logarithmic. The default * is linear. If the scale is logarithmic, then the TableRange must not * cross the value zero. */ void SetScale(int scale); void SetScaleToLinear() { this->SetScale(VTK_SCALE_LINEAR); } void SetScaleToLog10() { this->SetScale(VTK_SCALE_LOG10); } vtkGetMacro(Scale, int); //@} //@{ /** * Set/Get the minimum/maximum scalar values for scalar mapping. Scalar * values less than minimum range value are clamped to minimum range value. * Scalar values greater than maximum range value are clamped to maximum * range value. * The \a TableRange values are only used when \a IndexedLookup is false. */ virtual void SetTableRange(const double r[2]); virtual void SetTableRange(double min, double max); vtkGetVectorMacro(TableRange, double, 2); //@} //@{ /** * Set the range in hue (using automatic generation). Hue ranges * between [0,1]. */ vtkSetVector2Macro(HueRange, double); vtkGetVector2Macro(HueRange, double); //@} //@{ /** * Set the range in saturation (using automatic generation). Saturation * ranges between [0,1]. */ vtkSetVector2Macro(SaturationRange, double); vtkGetVector2Macro(SaturationRange, double); //@} //@{ /** * Set the range in value (using automatic generation). Value ranges * between [0,1]. */ vtkSetVector2Macro(ValueRange, double); vtkGetVector2Macro(ValueRange, double); //@} //@{ /** * Set the range in alpha (using automatic generation). Alpha ranges from * [0,1]. */ vtkSetVector2Macro(AlphaRange, double); vtkGetVector2Macro(AlphaRange, double); //@} //@{ /** * Set the color to use when a NaN (not a number) is encountered. This is an * RGBA 4-tuple of doubles in the range [0,1]. */ vtkSetVector4Macro(NanColor, double); vtkGetVector4Macro(NanColor, double); //@} /** * Return the \a NanColor as a pointer to 4 unsigned chars. This * will overwrite any data returned by previous calls to MapValue. */ unsigned char* GetNanColorAsUnsignedChars(); /** * Given an RGBA[4] color in the [0,1] range, convert it to RGBA[4] in the [0,255] range. */ static void GetColorAsUnsignedChars(const double colorIn[4], unsigned char colorOut[4]); //@{ /** * Set the color to use when a value below the range is * encountered. This is an RGBA 4-tuple of doubles in the range [0, 1]. */ vtkSetVector4Macro(BelowRangeColor, double); vtkGetVector4Macro(BelowRangeColor, double); //@} //@{ /** * Set whether the below range color should be used. */ vtkSetMacro(UseBelowRangeColor, vtkTypeBool); vtkGetMacro(UseBelowRangeColor, vtkTypeBool); vtkBooleanMacro(UseBelowRangeColor, vtkTypeBool); //@} //@{ /** * Set the color to use when a value above the range is * encountered. This is an RGBA 4-tuple of doubles in the range [0, 1]. */ vtkSetVector4Macro(AboveRangeColor, double); vtkGetVector4Macro(AboveRangeColor, double); //@} //@{ /** * Set whether the above range color should be used. */ vtkSetMacro(UseAboveRangeColor, vtkTypeBool); vtkGetMacro(UseAboveRangeColor, vtkTypeBool); vtkBooleanMacro(UseAboveRangeColor, vtkTypeBool); //@} /** * Map one value through the lookup table, returning an RBGA[4] color. */ const unsigned char* MapValue(double v) override; /** * Map one value through the lookup table and return the color as * an RGB[3] array of doubles between 0 and 1. Note lack of alpha. */ void GetColor(double x, double rgb[3]) override; /** * Map one value through the lookup table and return the alpha value * (the opacity) as a double between 0 and 1. */ double GetOpacity(double v) override; /** * Return the table index associated with a particular value. * Returns -1 if \a v is NaN. * Do not use this function when \a IndexedLookup is true: * in that case, the set of values \a v may take on is exactly the integers * from 0 to \a GetNumberOfTableValues() - 1; * and \a v serves directly as an index into \a TableValues. */ virtual vtkIdType GetIndex(double v); //@{ /** * Specify the number of values (i.e., colors) in the lookup table. */ void SetNumberOfTableValues(vtkIdType number); vtkIdType GetNumberOfTableValues() { return this->NumberOfColors; } //@} /** * Directly load color into lookup table. Use [0,1] double values for color * component specification. Make sure that you've either used the * Build() method or used SetNumberOfTableValues() prior to using this * method. */ virtual void SetTableValue(vtkIdType indx, const double rgba[4]); /** * Directly load color into lookup table. Use [0,1] double values for color * component specification. Alpha defaults to 1 if unspecified. */ virtual void SetTableValue(vtkIdType indx, double r, double g, double b, double a = 1.0); /** * Return an RGBA color value for the given index into the lookup table. Color * components are expressed as [0,1] double values. */ double* GetTableValue(vtkIdType id) VTK_SIZEHINT(4); /** * Return an RGBA color value for the given index into the lookup table. Color * components are expressed as [0,1] double values. */ void GetTableValue(vtkIdType id, double rgba[4]); /** * Get pointer to color table data. Format is array of unsigned char * R-G-B-A...R-G-B-A. */ unsigned char* GetPointer(vtkIdType id) { return this->Table->GetPointer(4 * id); } /** * Get pointer to data. Useful for direct writes into object. MaxId is bumped * by number (and memory allocated if necessary). Id is the location you * wish to write into; number is the number of rgba values to write. * \warning If you modify the table data via the pointer returned by this * member function, you must call vtkLookupTable::BuildSpecialColors() * afterwards to ensure that the special colors (below/above range and NaN * value) are up-to-date. */ unsigned char* WritePointer(vtkIdType id, int number); //@{ /** * Sets/Gets the range of scalars which will be mapped. This is a duplicate * of Get/SetTableRange. */ double* GetRange() VTK_SIZEHINT(2) override { return this->GetTableRange(); } void SetRange(double min, double max) override { this->SetTableRange(min, max); } void SetRange(const double rng[2]) override { this->SetRange(rng[0], rng[1]); } //@} /** * Returns the log of \c range in \c log_range. * There is a little more to this than simply taking the log10 of the * two range values: we do conversion of negative ranges to positive * ranges, and conversion of zero to a 'very small number'. */ static void GetLogRange(const double range[2], double log_range[2]); /** * Apply log to value, with appropriate constraints. */ static double ApplyLogScale(double v, const double range[2], const double log_range[2]); //@{ /** * Set the number of colors in the lookup table. Use * SetNumberOfTableValues() instead, it can be used both before and * after the table has been built whereas SetNumberOfColors() has no * effect after the table has been built. */ vtkSetClampMacro(NumberOfColors, vtkIdType, 2, VTK_ID_MAX); vtkGetMacro(NumberOfColors, vtkIdType); //@} //@{ /** * Set/Get the internal table array that is used to map the scalars * to colors. The table array is an unsigned char array with 4 * components representing RGBA. */ void SetTable(vtkUnsignedCharArray*); vtkGetObjectMacro(Table, vtkUnsignedCharArray); //@} /** * Map a set of scalars through the lookup table. * This member function is thread safe. */ void MapScalarsThroughTable2(void* input, unsigned char* output, int inputDataType, int numberOfValues, int inputIncrement, int outputIncrement) override; /** * Copy the contents from another LookupTable. */ void DeepCopy(vtkScalarsToColors* lut) override; /** * This should return 1 if the subclass is using log scale for mapping scalars * to colors. Returns 1 is scale == VTK_SCALE_LOG10. */ int UsingLogScale() override { return (this->GetScale() == VTK_SCALE_LOG10) ? 1 : 0; } /** * Get the number of available colors for mapping to. */ vtkIdType GetNumberOfAvailableColors() override; /** * Return a color given an integer index. * This is used to assign colors to annotations (given an offset into the * list of annotations). * If the table is empty or \a idx < 0, then NanColor is returned. */ void GetIndexedColor(vtkIdType idx, double rgba[4]) override; protected: vtkLookupTable(int sze = 256, int ext = 256); ~vtkLookupTable() override; vtkIdType NumberOfColors; vtkUnsignedCharArray* Table; double TableRange[2]; double HueRange[2]; double SaturationRange[2]; double ValueRange[2]; double AlphaRange[2]; double NanColor[4]; double BelowRangeColor[4]; vtkTypeBool UseBelowRangeColor; double AboveRangeColor[4]; vtkTypeBool UseAboveRangeColor; int Scale; int Ramp; vtkTimeStamp InsertTime; vtkTimeStamp BuildTime; double RGBA[4]; // used during conversion process unsigned char NanColorChar[4]; int OpaqueFlag; vtkTimeStamp OpaqueFlagBuildTime; vtkTimeStamp SpecialColorsBuildTime; /** * Resize the LookupTable to have enough room for the out-of-range colors */ void ResizeTableForSpecialColors(); private: vtkLookupTable(const vtkLookupTable&) = delete; void operator=(const vtkLookupTable&) = delete; }; //---------------------------------------------------------------------------- inline unsigned char* vtkLookupTable::WritePointer(vtkIdType id, int number) { this->InsertTime.Modified(); return this->Table->WritePointer(4 * id, 4 * number); } #endif