[Gdal-dev] Raster Attribute Tables (RATs)

Frank Warmerdam fwarmerdam at gmail.com
Thu Jul 28 13:54:20 EDT 2005


Folks,

I have finally started work on "raster attribute tables" (or RATs) for GDAL.  
This is intended to be a data structure capturing various sorts of information 
that can be associated with ranges of pixel values.  This would include:

 o Color tables where a specific color is associated with each 
   integer raster value.  Currently handled by GDALColorTable

 o Color tables where ranges of values are assigned one color value.
   Currently addressed by the COLOR_TABLE_RULE metadata returned
   by the GRASS driver, but no where else. 

 o Color tables where a range of pixel values are assigned a range of
   colors.  That is, the color for a particular pixel value is determined by
   looking up the category it falls into and interpolating the value between
   the start and end value for that category based on where the pixel value
   is between the category minimum and maximum.   This is also currently 
   only handled by the GRASS COLOR_TABLE_RULE metadata mechanism.

 o Histogram information, where histogram counts are available for for some
   binning pattern of the data.  This is currently handled via the 
   GetHistogram(), GetDefaultHistogram() and SetDefaultHistogram() methods 
   on the GDALRasterBand. 

 o Class names for categories ... currently handled by the GetCategoryNames()
   method on the GDALRasterBand. 

 o Other generic information, such as long class names, other computed
   statistics, etc.

It is still unclear to what extent this new mechanism will replace existing
mechanisms.  It is likely that it will superceed the COLOR_TABLE_RULE
mechanism implemented for the GRASS driver, but I don't expect it to
replace use of the GDALColorTable for simple paletted images.  It also
won't replace the histogram mechanism.  It *might* replace the 
GetCategoryNames() mechanism since that is so little used. 

The raster attribute table is essentially a table with one "row" for each
range of pixel values considered to belong to a class. In a classic 
256 color paletted image there would be 256 classes.  To hold a 16
bit histogrmam, it might need 65536 classes.   For an image intended
to be colored along a single color range it might only have one class. 

Each row implicitly or explicitly has a min and max pixel value defining
the range of pixel values to which the row (category/class) applies.  

The table will have one or more columns.  If the min/max ranges are not 
"regular", then they can be explicit columns in the table.  Other columns
could include "class name", "pixel count" (histogram), red, green, blue, 
alpha, red_min, red_max, and so forth.  Very simple tables might only have
one column (say the pixel count), while others may have most of the columns.

Each RAT would have a name, and a given GDALRasterBand might have more than 
one associated with it, though normally there would be zero or one such table.

I propose to implement a GDALRasterAttributeClass table for easy 
construction, and query of raster attribute tables.  The interface
would look something like:

typedef enum {
    GFT_Integer, 
    GFT_Real,
    GFT_String
} GDALRATFieldType;

typedef enum {
    GFU_Generic = 0,
    GFU_PixelCount = 1,
    GFU_Name = 2,
    GFU_Min = 3,
    GFU_Max = 4,
    GFU_Red = 5,
    GFU_Green = 6,
    GFU_Blue = 7,
    GFU_Alpha = 8,
    GFU_RedMin = 9,
    GFU_GreenMin = 10,
    GFU_BlueMin = 11,
    GFU_AlphaMin = 12,
    GFU_RedMax = 13,
    GFU_GreenMax = 14,
    GFU_BlueMax = 15,
    GFU_AlphaMax = 16,
    GFU_Max
} GDALRATFieldUsage;

class GDALRasterAttributeTable 
{
public:
    GDALRasterAttributeTable();
    ~GDALRasterAttributeTable();

    std::string   GetTableName() const;
    
    int           GetCategoryCount() const;

    const char   *GetNameOfCol( int );
    GDALRATFieldUsage GetUsageOfCol( int );
    GDALRATFieldType GetTypeOfCol( int );
    
    int           GetColOfUsage( GDALRATFieldUsage );

    int           GetRowCount() const;

    std::string   GetValueAsString( int iRow, int iField ) const;
    int           GetValueAsInt( int iRow, int iField ) const;
    double        GetValueAsDouble( int iRow, int iField ) const;

    void          SetValue( int iRow, int iField, const char *pszValue );
    void          SetValue( int iRow, int iField, double dfValue);
    void          SetValue( int iRow, int iField, int nValue );

    int           GetRowOfValue( double dfValue );
    int           GetRowOfValue( int nValue );
    int           GetColorOfValue( double dfValue, GDALColorEntry *psEntry );

    double        GetRowMin( int iRow );
    double        GetRowMax( int iRow );

    CPLErr        CreateColumn( std::string osFieldName, 
                                GDALRATFieldType eFieldType, 
                                GDALRATFieldUsage eFieldUsage );
    CPLErr        SetLinearBinning( double dfRow0Min, double dfBinSize );
    int           GetRegularBinning( double *pdfRow0Min, double *pdfBinSize );

    CPLXMLNode   *Serialize();
    CPLErr        XMLInit( CPLXMLNode *, const char * );

    CPLErr        InitializeFromColorTable( GDALColorTable * );
};


The GDALRasterBand class would have new virtual methods to query for 
or associate raster attribute tables with a band:

  virtual const GDALRasterAttributeTable *
              GetRasterAttributeTableRef( const char *pszTableName = NULL );
  virtual char **   
              GetRasterAttributeTableList();
  virtual CPLErr    
              AssociateRasterAttributeTable( GDALRasterAttributeTable * );

The GRASS and HFA (Erdas Imagine) drivers would include explicit support
for reading back the "raster attribute table" structures from those formats
directly.  The GDALPamRasterBand base class used for most driver's 
GDALRasterBand classes would also support these attribute tables via the
.aux.xml file.  

It is not yet clear to me to what extent some of the existing functions 
that overlap raster attribute tables would interact.  For instance, should
the default implementation of the GetHistogram() method search for existing 
RATs to satisfy a request?  

I think the most common use of RATs will be for applications wishing to 
preserve complex portrayal.  For instance, QGIS's GRASS plugin already uses
the COLOR_TABLE_RULE metadata to get range based colormaps.  It should be
upgraded to using RATs.  Basically scan for a RAT with color columns and
translate accordingly.  Likewise, MapServer could do the same thing, 
essentially internally defining a series of CLASSes on the raster layer based 
on the RAT rows. 

I am putting out this preliminary design to get feedback from you, the user
community, on things you would like to accomplish with RATs and suggestions
with regard to the interface and behavior. 

Best regards,

-- 
---------------------------------------+--------------------------------------
I set the clouds in motion - turn up   | Frank Warmerdam, warmerdam at pobox.com
light and sound - activate the windows | http://pobox.com/~warmerdam
and watch the world go round - Rush    | Geospatial Programmer for Rent




More information about the Gdal-dev mailing list