LCOV - code coverage report
Current view: top level - gcore - gdal_rat.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 391 581 67.3 %
Date: 2024-05-03 15:49:35 Functions: 54 71 76.1 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL Core
       4             :  * Purpose:  Implementation of GDALRasterAttributeTable and related classes.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2005, Frank Warmerdam
       9             :  * Copyright (c) 2009, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * Permission is hereby granted, free of charge, to any person obtaining a
      12             :  * copy of this software and associated documentation files (the "Software"),
      13             :  * to deal in the Software without restriction, including without limitation
      14             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15             :  * and/or sell copies of the Software, and to permit persons to whom the
      16             :  * Software is furnished to do so, subject to the following conditions:
      17             :  *
      18             :  * The above copyright notice and this permission notice shall be included
      19             :  * in all copies or substantial portions of the Software.
      20             :  *
      21             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27             :  * DEALINGS IN THE SOFTWARE.
      28             :  ****************************************************************************/
      29             : 
      30             : #include "cpl_port.h"
      31             : #include "gdal.h"
      32             : #include "gdal_priv.h"
      33             : #include "gdal_rat.h"
      34             : 
      35             : #include <cmath>
      36             : #include <cstddef>
      37             : #include <cstdlib>
      38             : 
      39             : #include <algorithm>
      40             : #include <vector>
      41             : 
      42             : #include "cpl_conv.h"
      43             : #include "cpl_error.h"
      44             : #include "cpl_string.h"
      45             : #include "cpl_vsi.h"
      46             : 
      47             : #ifdef __clang__
      48             : #pragma clang diagnostic push
      49             : #pragma clang diagnostic ignored "-Wunknown-pragmas"
      50             : #pragma clang diagnostic ignored "-Wdocumentation"
      51             : #pragma clang diagnostic ignored "-Wold-style-cast"
      52             : #endif
      53             : #include "json.h"
      54             : #ifdef __clang__
      55             : #pragma clang diagnostic pop
      56             : #endif
      57             : #include "ogrgeojsonwriter.h"
      58             : 
      59             : /**
      60             :  * \class GDALRasterAttributeTable
      61             :  *
      62             :  * The GDALRasterAttributeTable (or RAT) class is used to encapsulate a table
      63             :  * used to provide attribute information about pixel values.  Each row
      64             :  * in the table applies to a range of pixel values (or a single value in
      65             :  * some cases), and might have attributes such as the histogram count for
      66             :  * that range, the color pixels of that range should be drawn names of classes
      67             :  * or any other generic information.
      68             :  *
      69             :  * Raster attribute tables can be used to represent histograms, color tables,
      70             :  * and classification information.
      71             :  *
      72             :  * Each column in a raster attribute table has a name, a type (integer,
      73             :  * floating point or string), and a GDALRATFieldUsage.  The usage distinguishes
      74             :  * columns with particular understood purposes (such as color, histogram
      75             :  * count, name) and columns that have specific purposes not understood by
      76             :  * the library (long label, suitability_for_growing_wheat, etc).
      77             :  *
      78             :  * In the general case each row has a column indicating the minimum pixel
      79             :  * values falling into that category, and a column indicating the maximum
      80             :  * pixel value.  These are indicated with usage values of GFU_Min, and
      81             :  * GFU_Max.  In other cases where each row is a discrete pixel value, one
      82             :  * column of usage GFU_MinMax can be used.
      83             :  *
      84             :  * In other cases all the categories are of equal size and regularly spaced
      85             :  * and the categorization information can be determine just by knowing the
      86             :  * value at which the categories start, and the size of a category.  This
      87             :  * is called "Linear Binning" and the information is kept specially on
      88             :  * the raster attribute table as a whole.
      89             :  *
      90             :  * RATs are normally associated with GDALRasterBands and be be queried
      91             :  * using the GDALRasterBand::GetDefaultRAT() method.
      92             :  */
      93             : 
      94             : /************************************************************************/
      95             : /*                  ~GDALRasterAttributeTable()                         */
      96             : /*                                                                      */
      97             : /*                      Virtual Destructor                              */
      98             : /************************************************************************/
      99             : 
     100             : GDALRasterAttributeTable::~GDALRasterAttributeTable() = default;
     101             : 
     102             : /************************************************************************/
     103             : /*                              ValuesIO()                              */
     104             : /*                                                                      */
     105             : /*                      Default Implementations                         */
     106             : /************************************************************************/
     107             : 
     108             : /**
     109             :  * \brief Read or Write a block of doubles to/from the Attribute Table.
     110             :  *
     111             :  * This method is the same as the C function GDALRATValuesIOAsDouble().
     112             :  *
     113             :  * @param eRWFlag Either GF_Read or GF_Write
     114             :  * @param iField column of the Attribute Table
     115             :  * @param iStartRow start row to start reading/writing (zero based)
     116             :  * @param iLength number of rows to read or write
     117             :  * @param pdfData pointer to array of doubles to read/write. Should be at least
     118             :  *   iLength long.
     119             :  *
     120             :  * @return CE_None or CE_Failure if iStartRow + iLength greater than number of
     121             :  *   rows in table.
     122             :  */
     123             : 
     124           0 : CPLErr GDALRasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField,
     125             :                                           int iStartRow, int iLength,
     126             :                                           double *pdfData)
     127             : {
     128           0 :     if ((iStartRow + iLength) > GetRowCount())
     129             :     {
     130           0 :         return CE_Failure;
     131             :     }
     132             : 
     133           0 :     if (eRWFlag == GF_Read)
     134             :     {
     135           0 :         for (int iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++)
     136             :         {
     137           0 :             pdfData[iIndex] = GetValueAsDouble(iIndex, iField);
     138             :         }
     139             :     }
     140             :     else
     141             :     {
     142           0 :         for (int iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++)
     143             :         {
     144           0 :             SetValue(iIndex, iField, pdfData[iIndex]);
     145             :         }
     146             :     }
     147           0 :     return CE_None;
     148             : }
     149             : 
     150             : /************************************************************************/
     151             : /*                       GDALRATValuesIOAsDouble()                      */
     152             : /************************************************************************/
     153             : 
     154             : /**
     155             :  * \brief Read or Write a block of doubles to/from the Attribute Table.
     156             :  *
     157             :  * This function is the same as the C++ method
     158             :  * GDALRasterAttributeTable::ValuesIO()
     159             :  */
     160          22 : CPLErr CPL_STDCALL GDALRATValuesIOAsDouble(GDALRasterAttributeTableH hRAT,
     161             :                                            GDALRWFlag eRWFlag, int iField,
     162             :                                            int iStartRow, int iLength,
     163             :                                            double *pdfData)
     164             : 
     165             : {
     166          22 :     VALIDATE_POINTER1(hRAT, "GDALRATValuesIOAsDouble", CE_Failure);
     167             : 
     168          44 :     return GDALRasterAttributeTable::FromHandle(hRAT)->ValuesIO(
     169          22 :         eRWFlag, iField, iStartRow, iLength, pdfData);
     170             : }
     171             : 
     172             : /**
     173             :  * \brief Read or Write a block of integers to/from the Attribute Table.
     174             :  *
     175             :  * This method is the same as the C function GDALRATValuesIOAsInteger().
     176             :  *
     177             :  * @param eRWFlag Either GF_Read or GF_Write
     178             :  * @param iField column of the Attribute Table
     179             :  * @param iStartRow start row to start reading/writing (zero based)
     180             :  * @param iLength number of rows to read or write
     181             :  * @param pnData pointer to array of ints to read/write. Should be at least
     182             :  *     iLength long.
     183             :  *
     184             :  * @return CE_None or CE_Failure if iStartRow + iLength greater than number of
     185             :  *     rows in table.
     186             :  */
     187             : 
     188           0 : CPLErr GDALRasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField,
     189             :                                           int iStartRow, int iLength,
     190             :                                           int *pnData)
     191             : {
     192           0 :     if ((iStartRow + iLength) > GetRowCount())
     193             :     {
     194           0 :         return CE_Failure;
     195             :     }
     196             : 
     197           0 :     if (eRWFlag == GF_Read)
     198             :     {
     199           0 :         for (int iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++)
     200             :         {
     201           0 :             pnData[iIndex] = GetValueAsInt(iIndex, iField);
     202             :         }
     203             :     }
     204             :     else
     205             :     {
     206           0 :         for (int iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++)
     207             :         {
     208           0 :             SetValue(iIndex, iField, pnData[iIndex]);
     209             :         }
     210             :     }
     211           0 :     return CE_None;
     212             : }
     213             : 
     214             : /************************************************************************/
     215             : /*                       GDALRATValuesIOAsInteger()                     */
     216             : /************************************************************************/
     217             : 
     218             : /**
     219             :  * \brief Read or Write a block of ints to/from the Attribute Table.
     220             :  *
     221             :  * This function is the same as the C++ method
     222             :  * GDALRasterAttributeTable::ValuesIO()
     223             :  */
     224          22 : CPLErr CPL_STDCALL GDALRATValuesIOAsInteger(GDALRasterAttributeTableH hRAT,
     225             :                                             GDALRWFlag eRWFlag, int iField,
     226             :                                             int iStartRow, int iLength,
     227             :                                             int *pnData)
     228             : 
     229             : {
     230          22 :     VALIDATE_POINTER1(hRAT, "GDALRATValuesIOAsInteger", CE_Failure);
     231             : 
     232          44 :     return GDALRasterAttributeTable::FromHandle(hRAT)->ValuesIO(
     233          22 :         eRWFlag, iField, iStartRow, iLength, pnData);
     234             : }
     235             : 
     236             : /**
     237             :  * \brief Read or Write a block of strings to/from the Attribute Table.
     238             :  *
     239             :  * This method is the same as the C function GDALRATValuesIOAsString().
     240             :  * When reading, papszStrList must be already allocated to the correct size.
     241             :  * The caller is expected to call CPLFree on each read string.
     242             :  *
     243             :  * @param eRWFlag Either GF_Read or GF_Write
     244             :  * @param iField column of the Attribute Table
     245             :  * @param iStartRow start row to start reading/writing (zero based)
     246             :  * @param iLength number of rows to read or write
     247             :  * @param papszStrList pointer to array of strings to read/write. Should be at
     248             :  *   least iLength long.
     249             :  *
     250             :  * @return CE_None or CE_Failure if iStartRow + iLength greater than number of
     251             :  *   rows in table.
     252             :  */
     253             : 
     254           0 : CPLErr GDALRasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField,
     255             :                                           int iStartRow, int iLength,
     256             :                                           char **papszStrList)
     257             : {
     258           0 :     if ((iStartRow + iLength) > GetRowCount())
     259             :     {
     260           0 :         return CE_Failure;
     261             :     }
     262             : 
     263           0 :     if (eRWFlag == GF_Read)
     264             :     {
     265           0 :         for (int iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++)
     266             :         {
     267           0 :             papszStrList[iIndex] = VSIStrdup(GetValueAsString(iIndex, iField));
     268             :         }
     269             :     }
     270             :     else
     271             :     {
     272           0 :         for (int iIndex = iStartRow; iIndex < (iStartRow + iLength); iIndex++)
     273             :         {
     274           0 :             SetValue(iIndex, iField, papszStrList[iIndex]);
     275             :         }
     276             :     }
     277           0 :     return CE_None;
     278             : }
     279             : 
     280             : /************************************************************************/
     281             : /*                       GDALRATValuesIOAsString()                      */
     282             : /************************************************************************/
     283             : 
     284             : /**
     285             :  * \brief Read or Write a block of strings to/from the Attribute Table.
     286             :  *
     287             :  * This function is the same as the C++ method
     288             :  * GDALRasterAttributeTable::ValuesIO()
     289             :  */
     290          24 : CPLErr CPL_STDCALL GDALRATValuesIOAsString(GDALRasterAttributeTableH hRAT,
     291             :                                            GDALRWFlag eRWFlag, int iField,
     292             :                                            int iStartRow, int iLength,
     293             :                                            char **papszStrList)
     294             : 
     295             : {
     296          24 :     VALIDATE_POINTER1(hRAT, "GDALRATValuesIOAsString", CE_Failure);
     297             : 
     298          48 :     return GDALRasterAttributeTable::FromHandle(hRAT)->ValuesIO(
     299          24 :         eRWFlag, iField, iStartRow, iLength, papszStrList);
     300             : }
     301             : 
     302             : /************************************************************************/
     303             : /*                            SetRowCount()                             */
     304             : /************************************************************************/
     305             : 
     306             : /**
     307             :  * \brief Set row count.
     308             :  *
     309             :  * Resizes the table to include the indicated number of rows.  Newly created
     310             :  * rows will be initialized to their default values - "" for strings,
     311             :  * and zero for numeric fields.
     312             :  *
     313             :  * This method is the same as the C function GDALRATSetRowCount().
     314             :  *
     315             :  * @param nNewCount the new number of rows.
     316             :  */
     317             : 
     318           0 : void GDALRasterAttributeTable::SetRowCount(CPL_UNUSED int nNewCount)
     319             : {
     320           0 : }
     321             : 
     322             : /************************************************************************/
     323             : /*                         GDALRATSetRowCount()                         */
     324             : /************************************************************************/
     325             : 
     326             : /**
     327             :  * \brief Set row count.
     328             :  *
     329             :  * This function is the same as the C++ method
     330             :  * GDALRasterAttributeTable::SetRowCount()
     331             :  *
     332             :  * @param hRAT RAT handle.
     333             :  * @param nNewCount the new number of rows.
     334             :  */
     335           5 : void CPL_STDCALL GDALRATSetRowCount(GDALRasterAttributeTableH hRAT,
     336             :                                     int nNewCount)
     337             : 
     338             : {
     339           5 :     VALIDATE_POINTER0(hRAT, "GDALRATSetRowCount");
     340             : 
     341           5 :     GDALRasterAttributeTable::FromHandle(hRAT)->SetRowCount(nNewCount);
     342             : }
     343             : 
     344             : /************************************************************************/
     345             : /*                           GetRowOfValue()                            */
     346             : /************************************************************************/
     347             : 
     348             : /**
     349             :  * \fn GDALRasterAttributeTable::GetRowOfValue(double) const
     350             :  * \brief Get row for pixel value.
     351             :  *
     352             :  * Given a raw pixel value, the raster attribute table is scanned to
     353             :  * determine which row in the table applies to the pixel value.  The
     354             :  * row index is returned.
     355             :  *
     356             :  * This method is the same as the C function GDALRATGetRowOfValue().
     357             :  *
     358             :  * @param dfValue the pixel value.
     359             :  *
     360             :  * @return the row index or -1 if no row is appropriate.
     361             :  */
     362             : 
     363             : /**/
     364             : /**/
     365             : 
     366           0 : int GDALRasterAttributeTable::GetRowOfValue(double /* dfValue */) const
     367             : {
     368           0 :     return -1;
     369             : }
     370             : 
     371             : /************************************************************************/
     372             : /*                        GDALRATGetRowOfValue()                        */
     373             : /************************************************************************/
     374             : 
     375             : /**
     376             :  * \brief Get row for pixel value.
     377             :  *
     378             :  * This function is the same as the C++ method
     379             :  * GDALRasterAttributeTable::GetRowOfValue()
     380             :  */
     381           3 : int CPL_STDCALL GDALRATGetRowOfValue(GDALRasterAttributeTableH hRAT,
     382             :                                      double dfValue)
     383             : 
     384             : {
     385           3 :     VALIDATE_POINTER1(hRAT, "GDALRATGetRowOfValue", 0);
     386             : 
     387           3 :     return GDALRasterAttributeTable::FromHandle(hRAT)->GetRowOfValue(dfValue);
     388             : }
     389             : 
     390             : /************************************************************************/
     391             : /*                           GetRowOfValue()                            */
     392             : /************************************************************************/
     393             : 
     394             : /**
     395             :  * \brief Get row for pixel value.
     396             :  *
     397             :  * Given a raw pixel value, the raster attribute table is scanned to
     398             :  * determine which row in the table applies to the pixel value.  The
     399             :  * row index is returned.
     400             :  *
     401             :  * Int arg for now just converted to double.  Perhaps we will
     402             :  * handle this in a special way some day?
     403             :  *
     404             :  * This method is the same as the C function GDALRATGetRowOfValue().
     405             :  *
     406             :  * @param nValue the pixel value.
     407             :  *
     408             :  * @return the row index or -1 if no row is appropriate.
     409             :  */
     410             : 
     411           0 : int GDALRasterAttributeTable::GetRowOfValue(int nValue) const
     412             : 
     413             : {
     414           0 :     return GetRowOfValue(static_cast<double>(nValue));
     415             : }
     416             : 
     417             : /************************************************************************/
     418             : /*                            CreateColumn()                            */
     419             : /************************************************************************/
     420             : 
     421             : /**
     422             :  * \fn GDALRasterAttributeTable::CreateColumn(const char*, GDALRATFieldType,
     423             :  * GDALRATFieldUsage) \brief Create new column.
     424             :  *
     425             :  * If the table already has rows, all row values for the new column will
     426             :  * be initialized to the default value ("", or zero).  The new column is
     427             :  * always created as the last column, can will be column (field)
     428             :  * "GetColumnCount()-1" after CreateColumn() has completed successfully.
     429             :  *
     430             :  * This method is the same as the C function GDALRATCreateColumn().
     431             :  *
     432             :  * @param pszFieldName the name of the field to create.
     433             :  * @param eFieldType the field type (integer, double or string).
     434             :  * @param eFieldUsage the field usage, GFU_Generic if not known.
     435             :  *
     436             :  * @return CE_None on success or CE_Failure if something goes wrong.
     437             :  */
     438             : 
     439             : /**/
     440             : /**/
     441             : 
     442             : CPLErr
     443           0 : GDALRasterAttributeTable::CreateColumn(const char * /* pszFieldName */,
     444             :                                        GDALRATFieldType /* eFieldType */,
     445             :                                        GDALRATFieldUsage /* eFieldUsage */)
     446             : {
     447           0 :     return CE_Failure;
     448             : }
     449             : 
     450             : /************************************************************************/
     451             : /*                        GDALRATCreateColumn()                         */
     452             : /************************************************************************/
     453             : 
     454             : /**
     455             :  * \brief Create new column.
     456             :  *
     457             :  * This function is the same as the C++ method
     458             :  * GDALRasterAttributeTable::CreateColumn()
     459             :  */
     460          25 : CPLErr CPL_STDCALL GDALRATCreateColumn(GDALRasterAttributeTableH hRAT,
     461             :                                        const char *pszFieldName,
     462             :                                        GDALRATFieldType eFieldType,
     463             :                                        GDALRATFieldUsage eFieldUsage)
     464             : 
     465             : {
     466          25 :     VALIDATE_POINTER1(hRAT, "GDALRATCreateColumn", CE_Failure);
     467             : 
     468          50 :     return GDALRasterAttributeTable::FromHandle(hRAT)->CreateColumn(
     469          25 :         pszFieldName, eFieldType, eFieldUsage);
     470             : }
     471             : 
     472             : /************************************************************************/
     473             : /*                          SetLinearBinning()                          */
     474             : /************************************************************************/
     475             : 
     476             : /**
     477             :  * \brief Set linear binning information.
     478             :  *
     479             :  * For RATs with equal sized categories (in pixel value space) that are
     480             :  * evenly spaced, this method may be used to associate the linear binning
     481             :  * information with the table.
     482             :  *
     483             :  * This method is the same as the C function GDALRATSetLinearBinning().
     484             :  *
     485             :  * @param dfRow0MinIn the lower bound (pixel value) of the first category.
     486             :  * @param dfBinSizeIn the width of each category (in pixel value units).
     487             :  *
     488             :  * @return CE_None on success or CE_Failure on failure.
     489             :  */
     490             : 
     491           0 : CPLErr GDALRasterAttributeTable::SetLinearBinning(CPL_UNUSED double dfRow0MinIn,
     492             :                                                   CPL_UNUSED double dfBinSizeIn)
     493             : {
     494           0 :     return CE_Failure;
     495             : }
     496             : 
     497             : /************************************************************************/
     498             : /*                      GDALRATSetLinearBinning()                       */
     499             : /************************************************************************/
     500             : 
     501             : /**
     502             :  * \brief Set linear binning information.
     503             :  *
     504             :  * This function is the same as the C++ method
     505             :  * GDALRasterAttributeTable::SetLinearBinning()
     506             :  */
     507           1 : CPLErr CPL_STDCALL GDALRATSetLinearBinning(GDALRasterAttributeTableH hRAT,
     508             :                                            double dfRow0Min, double dfBinSize)
     509             : 
     510             : {
     511           1 :     VALIDATE_POINTER1(hRAT, "GDALRATSetLinearBinning", CE_Failure);
     512             : 
     513           2 :     return GDALRasterAttributeTable::FromHandle(hRAT)->SetLinearBinning(
     514           1 :         dfRow0Min, dfBinSize);
     515             : }
     516             : 
     517             : /************************************************************************/
     518             : /*                          GetLinearBinning()                          */
     519             : /************************************************************************/
     520             : 
     521             : /**
     522             :  * \brief Get linear binning information.
     523             :  *
     524             :  * Returns linear binning information if any is associated with the RAT.
     525             :  *
     526             :  * This method is the same as the C function GDALRATGetLinearBinning().
     527             :  *
     528             :  * @param pdfRow0Min (out) the lower bound (pixel value) of the first category.
     529             :  * @param pdfBinSize (out) the width of each category (in pixel value units).
     530             :  *
     531             :  * @return TRUE if linear binning information exists or FALSE if there is none.
     532             :  */
     533             : 
     534           0 : int GDALRasterAttributeTable::GetLinearBinning(
     535             :     CPL_UNUSED double *pdfRow0Min, CPL_UNUSED double *pdfBinSize) const
     536             : {
     537           0 :     return false;
     538             : }
     539             : 
     540             : /************************************************************************/
     541             : /*                      GDALRATGetLinearBinning()                       */
     542             : /************************************************************************/
     543             : 
     544             : /**
     545             :  * \brief Get linear binning information.
     546             :  *
     547             :  * This function is the same as the C++ method
     548             :  * GDALRasterAttributeTable::GetLinearBinning()
     549             :  */
     550           1 : int CPL_STDCALL GDALRATGetLinearBinning(GDALRasterAttributeTableH hRAT,
     551             :                                         double *pdfRow0Min, double *pdfBinSize)
     552             : 
     553             : {
     554           1 :     VALIDATE_POINTER1(hRAT, "GDALRATGetLinearBinning", 0);
     555             : 
     556           2 :     return GDALRasterAttributeTable::FromHandle(hRAT)->GetLinearBinning(
     557           1 :         pdfRow0Min, pdfBinSize);
     558             : }
     559             : 
     560             : /************************************************************************/
     561             : /*                        GDALRATGetTableType()                         */
     562             : /************************************************************************/
     563             : 
     564             : /**
     565             :  * \brief Get Rat Table Type
     566             :  *
     567             :  * @since GDAL 2.4
     568             :  *
     569             :  * This function is the same as the C++ method
     570             :  * GDALRasterAttributeTable::GetTableType()
     571             :  */
     572          10 : GDALRATTableType CPL_STDCALL GDALRATGetTableType(GDALRasterAttributeTableH hRAT)
     573             : {
     574          10 :     VALIDATE_POINTER1(hRAT, "GDALRATGetTableType", GRTT_THEMATIC);
     575             : 
     576          10 :     return GDALDefaultRasterAttributeTable::FromHandle(hRAT)->GetTableType();
     577             : }
     578             : 
     579             : /************************************************************************/
     580             : /*                        GDALRATSetTableType()                         */
     581             : /************************************************************************/
     582             : 
     583             : /**
     584             :  * \brief Set RAT Table Type
     585             :  *
     586             :  * @since GDAL 2.4
     587             :  *
     588             :  * This function is the same as the C++ method
     589             :  * GDALRasterAttributeTable::SetTableType()
     590             :  */
     591           3 : CPLErr CPL_STDCALL GDALRATSetTableType(GDALRasterAttributeTableH hRAT,
     592             :                                        const GDALRATTableType eInTableType)
     593             : 
     594             : {
     595           3 :     VALIDATE_POINTER1(hRAT, "GDALRATSetTableType", CE_Failure);
     596             : 
     597           6 :     return GDALDefaultRasterAttributeTable::FromHandle(hRAT)->SetTableType(
     598           3 :         eInTableType);
     599             : }
     600             : 
     601             : /************************************************************************/
     602             : /*                             Serialize()                              */
     603             : /************************************************************************/
     604             : 
     605             : /** Serialize as a XML tree.
     606             :  * @return XML tree.
     607             :  */
     608          12 : CPLXMLNode *GDALRasterAttributeTable::Serialize() const
     609             : 
     610             : {
     611          12 :     if ((GetColumnCount() == 0) && (GetRowCount() == 0))
     612           1 :         return nullptr;
     613             : 
     614             :     CPLXMLNode *psTree =
     615          11 :         CPLCreateXMLNode(nullptr, CXT_Element, "GDALRasterAttributeTable");
     616             : 
     617             :     /* -------------------------------------------------------------------- */
     618             :     /*      Add attributes with regular binning info if appropriate.        */
     619             :     /* -------------------------------------------------------------------- */
     620          11 :     char szValue[128] = {'\0'};
     621          11 :     double dfRow0Min = 0.0;
     622          11 :     double dfBinSize = 0.0;
     623             : 
     624          11 :     if (GetLinearBinning(&dfRow0Min, &dfBinSize))
     625             :     {
     626           4 :         CPLsnprintf(szValue, sizeof(szValue), "%.16g", dfRow0Min);
     627           4 :         CPLCreateXMLNode(CPLCreateXMLNode(psTree, CXT_Attribute, "Row0Min"),
     628             :                          CXT_Text, szValue);
     629             : 
     630           4 :         CPLsnprintf(szValue, sizeof(szValue), "%.16g", dfBinSize);
     631           4 :         CPLCreateXMLNode(CPLCreateXMLNode(psTree, CXT_Attribute, "BinSize"),
     632             :                          CXT_Text, szValue);
     633             :     }
     634             : 
     635             :     /* -------------------------------------------------------------------- */
     636             :     /*      Store table type                                                */
     637             :     /* -------------------------------------------------------------------- */
     638          11 :     const GDALRATTableType tableType = GetTableType();
     639          11 :     if (tableType == GRTT_ATHEMATIC)
     640             :     {
     641           3 :         CPLsnprintf(szValue, sizeof(szValue), "athematic");
     642             :     }
     643             :     else
     644             :     {
     645           8 :         CPLsnprintf(szValue, sizeof(szValue), "thematic");
     646             :     }
     647          11 :     CPLCreateXMLNode(CPLCreateXMLNode(psTree, CXT_Attribute, "tableType"),
     648             :                      CXT_Text, szValue);
     649             : 
     650             :     /* -------------------------------------------------------------------- */
     651             :     /*      Define each column.                                             */
     652             :     /* -------------------------------------------------------------------- */
     653          11 :     const int iColCount = GetColumnCount();
     654             : 
     655          25 :     for (int iCol = 0; iCol < iColCount; iCol++)
     656             :     {
     657          14 :         CPLXMLNode *psCol = CPLCreateXMLNode(psTree, CXT_Element, "FieldDefn");
     658             : 
     659          14 :         snprintf(szValue, sizeof(szValue), "%d", iCol);
     660          14 :         CPLCreateXMLNode(CPLCreateXMLNode(psCol, CXT_Attribute, "index"),
     661             :                          CXT_Text, szValue);
     662             : 
     663          14 :         CPLCreateXMLElementAndValue(psCol, "Name", GetNameOfCol(iCol));
     664             : 
     665          14 :         snprintf(szValue, sizeof(szValue), "%d",
     666          14 :                  static_cast<int>(GetTypeOfCol(iCol)));
     667          14 :         CPLCreateXMLElementAndValue(psCol, "Type", szValue);
     668             : 
     669          14 :         snprintf(szValue, sizeof(szValue), "%d",
     670          14 :                  static_cast<int>(GetUsageOfCol(iCol)));
     671          14 :         CPLCreateXMLElementAndValue(psCol, "Usage", szValue);
     672             :     }
     673             : 
     674             :     /* -------------------------------------------------------------------- */
     675             :     /*      Write out each row.                                             */
     676             :     /* -------------------------------------------------------------------- */
     677          11 :     const int iRowCount = GetRowCount();
     678          11 :     CPLXMLNode *psTail = nullptr;
     679          11 :     CPLXMLNode *psRow = nullptr;
     680             : 
     681        1001 :     for (int iRow = 0; iRow < iRowCount; iRow++)
     682             :     {
     683         990 :         psRow = CPLCreateXMLNode(nullptr, CXT_Element, "Row");
     684         990 :         if (psTail == nullptr)
     685           7 :             CPLAddXMLChild(psTree, psRow);
     686             :         else
     687         983 :             psTail->psNext = psRow;
     688         990 :         psTail = psRow;
     689             : 
     690         990 :         snprintf(szValue, sizeof(szValue), "%d", iRow);
     691         990 :         CPLCreateXMLNode(CPLCreateXMLNode(psRow, CXT_Attribute, "index"),
     692             :                          CXT_Text, szValue);
     693             : 
     694        1985 :         for (int iCol = 0; iCol < iColCount; iCol++)
     695             :         {
     696         995 :             const char *pszValue = szValue;
     697             : 
     698         995 :             if (GetTypeOfCol(iCol) == GFT_Integer)
     699           8 :                 snprintf(szValue, sizeof(szValue), "%d",
     700           8 :                          GetValueAsInt(iRow, iCol));
     701         987 :             else if (GetTypeOfCol(iCol) == GFT_Real)
     702         985 :                 CPLsnprintf(szValue, sizeof(szValue), "%.16g",
     703         985 :                             GetValueAsDouble(iRow, iCol));
     704             :             else
     705           2 :                 pszValue = GetValueAsString(iRow, iCol);
     706             : 
     707         995 :             CPLCreateXMLElementAndValue(psRow, "F", pszValue);
     708             :         }
     709             :     }
     710             : 
     711          11 :     return psTree;
     712             : }
     713             : 
     714             : /************************************************************************/
     715             : /*                             SerializeJSON()                           */
     716             : /************************************************************************/
     717             : 
     718             : /** Serialize as a JSON object.
     719             :  * @return JSON object (of type json_object*)
     720             :  */
     721           3 : void *GDALRasterAttributeTable::SerializeJSON() const
     722             : 
     723             : {
     724           3 :     json_object *poRAT = json_object_new_object();
     725             : 
     726           3 :     if ((GetColumnCount() == 0) && (GetRowCount() == 0))
     727           0 :         return poRAT;
     728             : 
     729             :     /* -------------------------------------------------------------------- */
     730             :     /*      Add attributes with regular binning info if appropriate.        */
     731             :     /* -------------------------------------------------------------------- */
     732           3 :     double dfRow0Min = 0.0;
     733           3 :     double dfBinSize = 0.0;
     734           3 :     json_object *poRow0Min = nullptr;
     735           3 :     json_object *poBinSize = nullptr;
     736           3 :     json_object *poTableType = nullptr;
     737             : 
     738           3 :     if (GetLinearBinning(&dfRow0Min, &dfBinSize))
     739             :     {
     740           1 :         poRow0Min = json_object_new_double_with_precision(dfRow0Min, 16);
     741           1 :         json_object_object_add(poRAT, "row0Min", poRow0Min);
     742             : 
     743           1 :         poBinSize = json_object_new_double_with_precision(dfBinSize, 16);
     744           1 :         json_object_object_add(poRAT, "binSize", poBinSize);
     745             :     }
     746             : 
     747             :     /* -------------------------------------------------------------------- */
     748             :     /*      Table Type                                                      */
     749             :     /* -------------------------------------------------------------------- */
     750           3 :     const GDALRATTableType tableType = GetTableType();
     751           3 :     if (tableType == GRTT_ATHEMATIC)
     752             :     {
     753           1 :         poTableType = json_object_new_string("athematic");
     754             :     }
     755             :     else
     756             :     {
     757           2 :         poTableType = json_object_new_string("thematic");
     758             :     }
     759           3 :     json_object_object_add(poRAT, "tableType", poTableType);
     760             : 
     761             :     /* -------------------------------------------------------------------- */
     762             :     /*      Define each column.                                             */
     763             :     /* -------------------------------------------------------------------- */
     764           3 :     const int iColCount = GetColumnCount();
     765           3 :     json_object *poFieldDefnArray = json_object_new_array();
     766             : 
     767          24 :     for (int iCol = 0; iCol < iColCount; iCol++)
     768             :     {
     769          21 :         json_object *const poFieldDefn = json_object_new_object();
     770             : 
     771          21 :         json_object *const poColumnIndex = json_object_new_int(iCol);
     772          21 :         json_object_object_add(poFieldDefn, "index", poColumnIndex);
     773             : 
     774          21 :         json_object *const poName = json_object_new_string(GetNameOfCol(iCol));
     775          21 :         json_object_object_add(poFieldDefn, "name", poName);
     776             : 
     777             :         json_object *const poType =
     778          21 :             json_object_new_int(static_cast<int>(GetTypeOfCol(iCol)));
     779          21 :         json_object_object_add(poFieldDefn, "type", poType);
     780             : 
     781             :         json_object *const poUsage =
     782          21 :             json_object_new_int(static_cast<int>(GetUsageOfCol(iCol)));
     783          21 :         json_object_object_add(poFieldDefn, "usage", poUsage);
     784             : 
     785          21 :         json_object_array_add(poFieldDefnArray, poFieldDefn);
     786             :     }
     787             : 
     788           3 :     json_object_object_add(poRAT, "fieldDefn", poFieldDefnArray);
     789             : 
     790             :     /* -------------------------------------------------------------------- */
     791             :     /*      Write out each row.                                             */
     792             :     /* -------------------------------------------------------------------- */
     793           3 :     const int iRowCount = GetRowCount();
     794           3 :     json_object *poRowArray = json_object_new_array();
     795             : 
     796         224 :     for (int iRow = 0; iRow < iRowCount; iRow++)
     797             :     {
     798         221 :         json_object *const poRow = json_object_new_object();
     799             : 
     800         221 :         json_object *const poRowIndex = json_object_new_int(iRow);
     801         221 :         json_object_object_add(poRow, "index", poRowIndex);
     802             : 
     803         221 :         json_object *const poFArray = json_object_new_array();
     804             : 
     805         478 :         for (int iCol = 0; iCol < iColCount; iCol++)
     806             :         {
     807         257 :             json_object *poF = nullptr;
     808         257 :             if (GetTypeOfCol(iCol) == GFT_Integer)
     809          28 :                 poF = json_object_new_int(GetValueAsInt(iRow, iCol));
     810         229 :             else if (GetTypeOfCol(iCol) == GFT_Real)
     811         221 :                 poF = json_object_new_double_with_precision(
     812         221 :                     GetValueAsDouble(iRow, iCol), 16);
     813             :             else
     814           8 :                 poF = json_object_new_string(GetValueAsString(iRow, iCol));
     815             : 
     816         257 :             json_object_array_add(poFArray, poF);
     817             :         }
     818         221 :         json_object_object_add(poRow, "f", poFArray);
     819         221 :         json_object_array_add(poRowArray, poRow);
     820             :     }
     821           3 :     json_object_object_add(poRAT, "row", poRowArray);
     822             : 
     823           3 :     return poRAT;
     824             : }
     825             : 
     826             : /************************************************************************/
     827             : /*                              XMLInit()                               */
     828             : /************************************************************************/
     829             : 
     830             : /** Deserialize from XML.
     831             :  * @param psTree XML tree
     832             :  * @return error code.
     833             :  */
     834          14 : CPLErr GDALRasterAttributeTable::XMLInit(const CPLXMLNode *psTree,
     835             :                                          const char * /*pszVRTPath*/)
     836             : 
     837             : {
     838          14 :     CPLAssert(GetRowCount() == 0 && GetColumnCount() == 0);
     839             : 
     840             :     /* -------------------------------------------------------------------- */
     841             :     /*      Linear binning.                                                 */
     842             :     /* -------------------------------------------------------------------- */
     843          19 :     if (CPLGetXMLValue(psTree, "Row0Min", nullptr) &&
     844           5 :         CPLGetXMLValue(psTree, "BinSize", nullptr))
     845             :     {
     846           5 :         SetLinearBinning(CPLAtof(CPLGetXMLValue(psTree, "Row0Min", "")),
     847           5 :                          CPLAtof(CPLGetXMLValue(psTree, "BinSize", "")));
     848             :     }
     849             : 
     850             :     /* -------------------------------------------------------------------- */
     851             :     /*      Table Type                                                      */
     852             :     /* -------------------------------------------------------------------- */
     853          14 :     if (CPLGetXMLValue(psTree, "tableType", nullptr))
     854             :     {
     855          12 :         const char *pszValue = CPLGetXMLValue(psTree, "tableType", "thematic");
     856          12 :         if (EQUAL(pszValue, "athematic"))
     857             :         {
     858           3 :             SetTableType(GRTT_ATHEMATIC);
     859             :         }
     860             :         else
     861             :         {
     862           9 :             SetTableType(GRTT_THEMATIC);
     863             :         }
     864             :     }
     865             : 
     866             :     /* -------------------------------------------------------------------- */
     867             :     /*      Column definitions                                              */
     868             :     /* -------------------------------------------------------------------- */
     869             : 
     870        1340 :     for (CPLXMLNode *psChild = psTree->psChild; psChild != nullptr;
     871        1326 :          psChild = psChild->psNext)
     872             :     {
     873        1326 :         if (psChild->eType == CXT_Element &&
     874        1304 :             EQUAL(psChild->pszValue, "FieldDefn"))
     875             :         {
     876          17 :             CreateColumn(CPLGetXMLValue(psChild, "Name", ""),
     877             :                          static_cast<GDALRATFieldType>(
     878          17 :                              atoi(CPLGetXMLValue(psChild, "Type", "1"))),
     879             :                          static_cast<GDALRATFieldUsage>(
     880          17 :                              atoi(CPLGetXMLValue(psChild, "Usage", "0"))));
     881             :         }
     882             :     }
     883             : 
     884             :     /* -------------------------------------------------------------------- */
     885             :     /*      Row data.                                                       */
     886             :     /* -------------------------------------------------------------------- */
     887        1340 :     for (const CPLXMLNode *psChild = psTree->psChild; psChild != nullptr;
     888        1326 :          psChild = psChild->psNext)
     889             :     {
     890        1326 :         if (psChild->eType == CXT_Element && EQUAL(psChild->pszValue, "Row"))
     891             :         {
     892        1287 :             const int iRow = atoi(CPLGetXMLValue(psChild, "index", "0"));
     893        1287 :             int iField = 0;
     894             : 
     895        3868 :             for (CPLXMLNode *psF = psChild->psChild; psF != nullptr;
     896        2581 :                  psF = psF->psNext)
     897             :             {
     898        2581 :                 if (psF->eType != CXT_Element || !EQUAL(psF->pszValue, "F"))
     899        1287 :                     continue;
     900             : 
     901        1294 :                 if (psF->psChild != nullptr && psF->psChild->eType == CXT_Text)
     902        1294 :                     SetValue(iRow, iField++, psF->psChild->pszValue);
     903             :                 else
     904           0 :                     SetValue(iRow, iField++, "");
     905             :             }
     906             :         }
     907             :     }
     908             : 
     909          14 :     return CE_None;
     910             : }
     911             : 
     912             : /************************************************************************/
     913             : /*                      InitializeFromColorTable()                      */
     914             : /************************************************************************/
     915             : 
     916             : /**
     917             :  * \brief Initialize from color table.
     918             :  *
     919             :  * This method will setup a whole raster attribute table based on the
     920             :  * contents of the passed color table.  The Value (GFU_MinMax),
     921             :  * Red (GFU_Red), Green (GFU_Green), Blue (GFU_Blue), and Alpha (GFU_Alpha)
     922             :  * fields are created, and a row is set for each entry in the color table.
     923             :  *
     924             :  * The raster attribute table must be empty before calling
     925             :  * InitializeFromColorTable().
     926             :  *
     927             :  * The Value fields are set based on the implicit assumption with color
     928             :  * tables that entry 0 applies to pixel value 0, 1 to 1, etc.
     929             :  *
     930             :  * This method is the same as the C function GDALRATInitializeFromColorTable().
     931             :  *
     932             :  * @param poTable the color table to copy from.
     933             :  *
     934             :  * @return CE_None on success or CE_Failure if something goes wrong.
     935             :  */
     936             : 
     937           0 : CPLErr GDALRasterAttributeTable::InitializeFromColorTable(
     938             :     const GDALColorTable *poTable)
     939             : 
     940             : {
     941           0 :     if (GetRowCount() > 0 || GetColumnCount() > 0)
     942             :     {
     943           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     944             :                  "Raster Attribute Table not empty in "
     945             :                  "InitializeFromColorTable()");
     946           0 :         return CE_Failure;
     947             :     }
     948             : 
     949           0 :     SetLinearBinning(0.0, 1.0);
     950           0 :     CreateColumn("Value", GFT_Integer, GFU_MinMax);
     951           0 :     CreateColumn("Red", GFT_Integer, GFU_Red);
     952           0 :     CreateColumn("Green", GFT_Integer, GFU_Green);
     953           0 :     CreateColumn("Blue", GFT_Integer, GFU_Blue);
     954           0 :     CreateColumn("Alpha", GFT_Integer, GFU_Alpha);
     955             : 
     956           0 :     SetRowCount(poTable->GetColorEntryCount());
     957             : 
     958           0 :     for (int iRow = 0; iRow < poTable->GetColorEntryCount(); iRow++)
     959             :     {
     960             :         GDALColorEntry sEntry;
     961             : 
     962           0 :         poTable->GetColorEntryAsRGB(iRow, &sEntry);
     963             : 
     964           0 :         SetValue(iRow, 0, iRow);
     965           0 :         SetValue(iRow, 1, sEntry.c1);
     966           0 :         SetValue(iRow, 2, sEntry.c2);
     967           0 :         SetValue(iRow, 3, sEntry.c3);
     968           0 :         SetValue(iRow, 4, sEntry.c4);
     969             :     }
     970             : 
     971           0 :     return CE_None;
     972             : }
     973             : 
     974             : /************************************************************************/
     975             : /*                  GDALRATInitializeFromColorTable()                   */
     976             : /************************************************************************/
     977             : 
     978             : /**
     979             :  * \brief Initialize from color table.
     980             :  *
     981             :  * This function is the same as the C++ method
     982             :  * GDALRasterAttributeTable::InitializeFromColorTable()
     983             :  */
     984           0 : CPLErr CPL_STDCALL GDALRATInitializeFromColorTable(
     985             :     GDALRasterAttributeTableH hRAT, GDALColorTableH hCT)
     986             : 
     987             : {
     988           0 :     VALIDATE_POINTER1(hRAT, "GDALRATInitializeFromColorTable", CE_Failure);
     989             : 
     990           0 :     return GDALRasterAttributeTable::FromHandle(hRAT)->InitializeFromColorTable(
     991           0 :         GDALColorTable::FromHandle(hCT));
     992             : }
     993             : 
     994             : /************************************************************************/
     995             : /*                       TranslateToColorTable()                        */
     996             : /************************************************************************/
     997             : 
     998             : /**
     999             :  * \brief Translate to a color table.
    1000             :  *
    1001             :  * This method will attempt to create a corresponding GDALColorTable from
    1002             :  * this raster attribute table.
    1003             :  *
    1004             :  * This method is the same as the C function GDALRATTranslateToColorTable().
    1005             :  *
    1006             :  * @param nEntryCount The number of entries to produce (0 to nEntryCount-1),
    1007             :  * or -1 to auto-determine the number of entries.
    1008             :  *
    1009             :  * @return the generated color table or NULL on failure.
    1010             :  */
    1011             : 
    1012           0 : GDALColorTable *GDALRasterAttributeTable::TranslateToColorTable(int nEntryCount)
    1013             : 
    1014             : {
    1015             :     /* -------------------------------------------------------------------- */
    1016             :     /*      Establish which fields are red, green, blue and alpha.          */
    1017             :     /* -------------------------------------------------------------------- */
    1018           0 :     const int iRed = GetColOfUsage(GFU_Red);
    1019           0 :     const int iGreen = GetColOfUsage(GFU_Green);
    1020           0 :     const int iBlue = GetColOfUsage(GFU_Blue);
    1021             : 
    1022           0 :     if (iRed == -1 || iGreen == -1 || iBlue == -1)
    1023           0 :         return nullptr;
    1024             : 
    1025           0 :     const int iAlpha = GetColOfUsage(GFU_Alpha);
    1026             : 
    1027             :     /* -------------------------------------------------------------------- */
    1028             :     /*      If we aren't given an explicit number of values to scan for,    */
    1029             :     /*      search for the maximum "max" value.                             */
    1030             :     /* -------------------------------------------------------------------- */
    1031           0 :     if (nEntryCount == -1)
    1032             :     {
    1033           0 :         int iMaxCol = GetColOfUsage(GFU_Max);
    1034           0 :         if (iMaxCol == -1)
    1035           0 :             iMaxCol = GetColOfUsage(GFU_MinMax);
    1036             : 
    1037           0 :         if (iMaxCol == -1 || GetRowCount() == 0)
    1038           0 :             return nullptr;
    1039             : 
    1040           0 :         for (int iRow = 0; iRow < GetRowCount(); iRow++)
    1041             :         {
    1042           0 :             nEntryCount = std::max(
    1043           0 :                 nEntryCount, std::min(65535, GetValueAsInt(iRow, iMaxCol)) + 1);
    1044             :         }
    1045             : 
    1046           0 :         if (nEntryCount < 0)
    1047           0 :             return nullptr;
    1048             : 
    1049             :         // Restrict our number of entries to something vaguely sensible.
    1050           0 :         nEntryCount = std::min(65535, nEntryCount);
    1051             :     }
    1052             : 
    1053             :     /* -------------------------------------------------------------------- */
    1054             :     /*      Assign values to color table.                                   */
    1055             :     /* -------------------------------------------------------------------- */
    1056           0 :     GDALColorTable *poCT = new GDALColorTable();
    1057             : 
    1058           0 :     for (int iEntry = 0; iEntry < nEntryCount; iEntry++)
    1059             :     {
    1060           0 :         GDALColorEntry sColor = {0, 0, 0, 0};
    1061           0 :         const int iRow = GetRowOfValue(iEntry);
    1062             : 
    1063           0 :         if (iRow != -1)
    1064             :         {
    1065           0 :             sColor.c1 = static_cast<short>(GetValueAsInt(iRow, iRed));
    1066           0 :             sColor.c2 = static_cast<short>(GetValueAsInt(iRow, iGreen));
    1067           0 :             sColor.c3 = static_cast<short>(GetValueAsInt(iRow, iBlue));
    1068           0 :             if (iAlpha == -1)
    1069           0 :                 sColor.c4 = 255;
    1070             :             else
    1071           0 :                 sColor.c4 = static_cast<short>(GetValueAsInt(iRow, iAlpha));
    1072             :         }
    1073             : 
    1074           0 :         poCT->SetColorEntry(iEntry, &sColor);
    1075             :     }
    1076             : 
    1077           0 :     return poCT;
    1078             : }
    1079             : 
    1080             : /************************************************************************/
    1081             : /*                  GDALRATInitializeFromColorTable()                   */
    1082             : /************************************************************************/
    1083             : 
    1084             : /**
    1085             :  * \brief Translate to a color table.
    1086             :  *
    1087             :  * This function is the same as the C++ method
    1088             :  * GDALRasterAttributeTable::TranslateToColorTable()
    1089             :  */
    1090             : GDALColorTableH CPL_STDCALL
    1091           0 : GDALRATTranslateToColorTable(GDALRasterAttributeTableH hRAT, int nEntryCount)
    1092             : 
    1093             : {
    1094           0 :     VALIDATE_POINTER1(hRAT, "GDALRATTranslateToColorTable", nullptr);
    1095             : 
    1096           0 :     return GDALRasterAttributeTable::FromHandle(hRAT)->TranslateToColorTable(
    1097           0 :         nEntryCount);
    1098             : }
    1099             : 
    1100             : /************************************************************************/
    1101             : /*                            DumpReadable()                            */
    1102             : /************************************************************************/
    1103             : 
    1104             : /**
    1105             :  * \brief Dump RAT in readable form.
    1106             :  *
    1107             :  * Currently the readable form is the XML encoding ... only barely
    1108             :  * readable.
    1109             :  *
    1110             :  * This method is the same as the C function GDALRATDumpReadable().
    1111             :  *
    1112             :  * @param fp file to dump to or NULL for stdout.
    1113             :  */
    1114             : 
    1115           0 : void GDALRasterAttributeTable::DumpReadable(FILE *fp)
    1116             : 
    1117             : {
    1118           0 :     CPLXMLNode *psTree = Serialize();
    1119           0 :     char *const pszXMLText = CPLSerializeXMLTree(psTree);
    1120             : 
    1121           0 :     CPLDestroyXMLNode(psTree);
    1122             : 
    1123           0 :     if (fp == nullptr)
    1124           0 :         fp = stdout;
    1125             : 
    1126           0 :     fprintf(fp, "%s\n", pszXMLText);
    1127             : 
    1128           0 :     CPLFree(pszXMLText);
    1129           0 : }
    1130             : 
    1131             : /************************************************************************/
    1132             : /*                        GDALRATDumpReadable()                         */
    1133             : /************************************************************************/
    1134             : 
    1135             : /**
    1136             :  * \brief Dump RAT in readable form.
    1137             :  *
    1138             :  * This function is the same as the C++ method
    1139             :  * GDALRasterAttributeTable::DumpReadable()
    1140             :  */
    1141           0 : void CPL_STDCALL GDALRATDumpReadable(GDALRasterAttributeTableH hRAT, FILE *fp)
    1142             : 
    1143             : {
    1144           0 :     VALIDATE_POINTER0(hRAT, "GDALRATDumpReadable");
    1145             : 
    1146           0 :     GDALRasterAttributeTable::FromHandle(hRAT)->DumpReadable(fp);
    1147             : }
    1148             : 
    1149             : /* \class GDALDefaultRasterAttributeTable
    1150             :  *
    1151             :  * An implementation of GDALRasterAttributeTable that keeps
    1152             :  * all data in memory. This is the same as the implementation
    1153             :  * of GDALRasterAttributeTable in GDAL <= 1.10.
    1154             :  */
    1155             : 
    1156             : /************************************************************************/
    1157             : /*                  GDALDefaultRasterAttributeTable()                   */
    1158             : /*                                                                      */
    1159             : /*      Simple initialization constructor.                              */
    1160             : /************************************************************************/
    1161             : 
    1162             : //! Construct empty table.
    1163             : 
    1164         414 : GDALDefaultRasterAttributeTable::GDALDefaultRasterAttributeTable()
    1165             :     : bLinearBinning(false), dfRow0Min(-0.5), dfBinSize(1.0),
    1166             :       eTableType(GRTT_THEMATIC), bColumnsAnalysed(false), nMinCol(-1),
    1167         414 :       nMaxCol(-1), nRowCount(0)
    1168             : {
    1169         414 : }
    1170             : 
    1171             : /************************************************************************/
    1172             : /*                   GDALCreateRasterAttributeTable()                   */
    1173             : /************************************************************************/
    1174             : 
    1175             : /**
    1176             :  * \brief Construct empty table.
    1177             :  *
    1178             :  * This function is the same as the C++ method
    1179             :  * GDALDefaultRasterAttributeTable::GDALDefaultRasterAttributeTable()
    1180             :  */
    1181           9 : GDALRasterAttributeTableH CPL_STDCALL GDALCreateRasterAttributeTable()
    1182             : 
    1183             : {
    1184           9 :     return new GDALDefaultRasterAttributeTable();
    1185             : }
    1186             : 
    1187             : /************************************************************************/
    1188             : /*                 ~GDALDefaultRasterAttributeTable()                   */
    1189             : /*                                                                      */
    1190             : /*      All magic done by magic by the container destructors.           */
    1191             : /************************************************************************/
    1192             : 
    1193             : GDALDefaultRasterAttributeTable::~GDALDefaultRasterAttributeTable() = default;
    1194             : 
    1195             : /************************************************************************/
    1196             : /*                  GDALDestroyRasterAttributeTable()                   */
    1197             : /************************************************************************/
    1198             : 
    1199             : /**
    1200             :  * \brief Destroys a RAT.
    1201             :  *
    1202             :  * This function is the same as the C++ method
    1203             :  * GDALRasterAttributeTable::~GDALRasterAttributeTable()
    1204             :  */
    1205          16 : void CPL_STDCALL GDALDestroyRasterAttributeTable(GDALRasterAttributeTableH hRAT)
    1206             : 
    1207             : {
    1208          16 :     if (hRAT != nullptr)
    1209          16 :         delete GDALRasterAttributeTable::FromHandle(hRAT);
    1210          16 : }
    1211             : 
    1212             : /************************************************************************/
    1213             : /*                           AnalyseColumns()                           */
    1214             : /*                                                                      */
    1215             : /*      Internal method to work out which column to use for various     */
    1216             : /*      tasks.                                                          */
    1217             : /************************************************************************/
    1218             : 
    1219           2 : void GDALDefaultRasterAttributeTable::AnalyseColumns()
    1220             : 
    1221             : {
    1222           2 :     bColumnsAnalysed = true;
    1223             : 
    1224           2 :     nMinCol = GetColOfUsage(GFU_Min);
    1225           2 :     if (nMinCol == -1)
    1226           2 :         nMinCol = GetColOfUsage(GFU_MinMax);
    1227             : 
    1228           2 :     nMaxCol = GetColOfUsage(GFU_Max);
    1229           2 :     if (nMaxCol == -1)
    1230           2 :         nMaxCol = GetColOfUsage(GFU_MinMax);
    1231           2 : }
    1232             : 
    1233             : /************************************************************************/
    1234             : /*                           GetColumnCount()                           */
    1235             : /************************************************************************/
    1236             : 
    1237          84 : int GDALDefaultRasterAttributeTable::GetColumnCount() const
    1238             : 
    1239             : {
    1240          84 :     return static_cast<int>(aoFields.size());
    1241             : }
    1242             : 
    1243             : /************************************************************************/
    1244             : /*                       GDALRATGetColumnCount()                        */
    1245             : /************************************************************************/
    1246             : 
    1247             : /**
    1248             :  * \brief Fetch table column count.
    1249             :  *
    1250             :  * This function is the same as the C++ method
    1251             :  * GDALRasterAttributeTable::GetColumnCount()
    1252             :  */
    1253          31 : int CPL_STDCALL GDALRATGetColumnCount(GDALRasterAttributeTableH hRAT)
    1254             : 
    1255             : {
    1256          31 :     VALIDATE_POINTER1(hRAT, "GDALRATGetColumnCount", 0);
    1257             : 
    1258          31 :     return GDALRasterAttributeTable::FromHandle(hRAT)->GetColumnCount();
    1259             : }
    1260             : 
    1261             : /************************************************************************/
    1262             : /*                            GetNameOfCol()                            */
    1263             : /************************************************************************/
    1264             : 
    1265             : /** \brief Fetch name of indicated column.
    1266             :  * @param iCol column index.
    1267             :  * @return name.
    1268             :  */
    1269          62 : const char *GDALDefaultRasterAttributeTable::GetNameOfCol(int iCol) const
    1270             : 
    1271             : {
    1272          62 :     if (iCol < 0 || iCol >= static_cast<int>(aoFields.size()))
    1273           0 :         return "";
    1274             : 
    1275          62 :     return aoFields[iCol].sName;
    1276             : }
    1277             : 
    1278             : /************************************************************************/
    1279             : /*                        GDALRATGetNameOfCol()                         */
    1280             : /************************************************************************/
    1281             : 
    1282             : /**
    1283             :  * \brief Fetch name of indicated column.
    1284             :  *
    1285             :  * This function is the same as the C++ method
    1286             :  * GDALRasterAttributeTable::GetNameOfCol()
    1287             :  * @param hRAT RAT handle.
    1288             :  * @param iCol column index.
    1289             :  * @return name.
    1290             :  */
    1291          37 : const char *CPL_STDCALL GDALRATGetNameOfCol(GDALRasterAttributeTableH hRAT,
    1292             :                                             int iCol)
    1293             : 
    1294             : {
    1295          37 :     VALIDATE_POINTER1(hRAT, "GDALRATGetNameOfCol", nullptr);
    1296             : 
    1297          37 :     return GDALRasterAttributeTable::FromHandle(hRAT)->GetNameOfCol(iCol);
    1298             : }
    1299             : 
    1300             : /************************************************************************/
    1301             : /*                           GetUsageOfCol()                            */
    1302             : /************************************************************************/
    1303             : 
    1304             : /**
    1305             :  * \brief Fetch column usage value.
    1306             :  *
    1307             :  * @param iCol column index.
    1308             :  * @return usage.
    1309             :  */
    1310          58 : GDALRATFieldUsage GDALDefaultRasterAttributeTable::GetUsageOfCol(int iCol) const
    1311             : 
    1312             : {
    1313          58 :     if (iCol < 0 || iCol >= static_cast<int>(aoFields.size()))
    1314           0 :         return GFU_Generic;
    1315             : 
    1316          58 :     return aoFields[iCol].eUsage;
    1317             : }
    1318             : 
    1319             : /************************************************************************/
    1320             : /*                        GDALRATGetUsageOfCol()                        */
    1321             : /************************************************************************/
    1322             : 
    1323             : /**
    1324             :  * \brief Fetch column usage value.
    1325             :  *
    1326             :  * This function is the same as the C++ method
    1327             :  * GDALRasterAttributeTable::GetUsageOfCol()
    1328             :  * @param hRAT RAT handle.
    1329             :  * @param iCol column index.
    1330             :  * @return usage.
    1331             :  */
    1332             : GDALRATFieldUsage CPL_STDCALL
    1333          40 : GDALRATGetUsageOfCol(GDALRasterAttributeTableH hRAT, int iCol)
    1334             : 
    1335             : {
    1336          40 :     VALIDATE_POINTER1(hRAT, "GDALRATGetUsageOfCol", GFU_Generic);
    1337             : 
    1338          40 :     return GDALRasterAttributeTable::FromHandle(hRAT)->GetUsageOfCol(iCol);
    1339             : }
    1340             : 
    1341             : /************************************************************************/
    1342             : /*                            GetTypeOfCol()                            */
    1343             : /************************************************************************/
    1344             : 
    1345             : /**
    1346             :  * \brief Fetch column type.
    1347             :  *
    1348             :  * @param iCol column index.
    1349             :  * @return type.
    1350             :  */
    1351        1885 : GDALRATFieldType GDALDefaultRasterAttributeTable::GetTypeOfCol(int iCol) const
    1352             : 
    1353             : {
    1354        1885 :     if (iCol < 0 || iCol >= static_cast<int>(aoFields.size()))
    1355           0 :         return GFT_Integer;
    1356             : 
    1357        1885 :     return aoFields[iCol].eType;
    1358             : }
    1359             : 
    1360             : /************************************************************************/
    1361             : /*                        GDALRATGetTypeOfCol()                         */
    1362             : /************************************************************************/
    1363             : 
    1364             : /**
    1365             :  * \brief Fetch column type.
    1366             :  *
    1367             :  * This function is the same as the C++ method
    1368             :  * GDALRasterAttributeTable::GetTypeOfCol()
    1369             :  * @param hRAT RAT handle.
    1370             :  * @param iCol column index.
    1371             :  * @return type.
    1372             :  */
    1373          83 : GDALRATFieldType CPL_STDCALL GDALRATGetTypeOfCol(GDALRasterAttributeTableH hRAT,
    1374             :                                                  int iCol)
    1375             : 
    1376             : {
    1377          83 :     VALIDATE_POINTER1(hRAT, "GDALRATGetTypeOfCol", GFT_Integer);
    1378             : 
    1379          83 :     return GDALRasterAttributeTable::FromHandle(hRAT)->GetTypeOfCol(iCol);
    1380             : }
    1381             : 
    1382             : /************************************************************************/
    1383             : /*                           GetColOfUsage()                            */
    1384             : /************************************************************************/
    1385             : 
    1386             : /** Return the index of the column that corresponds to the passed usage.
    1387             :  * @param eUsage usage.
    1388             :  * @return column index, or -1 in case of error.
    1389             :  */
    1390           8 : int GDALDefaultRasterAttributeTable::GetColOfUsage(
    1391             :     GDALRATFieldUsage eUsage) const
    1392             : 
    1393             : {
    1394          16 :     for (unsigned int i = 0; i < aoFields.size(); i++)
    1395             :     {
    1396          12 :         if (aoFields[i].eUsage == eUsage)
    1397           4 :             return i;
    1398             :     }
    1399             : 
    1400           4 :     return -1;
    1401             : }
    1402             : 
    1403             : /************************************************************************/
    1404             : /*                        GDALRATGetColOfUsage()                        */
    1405             : /************************************************************************/
    1406             : 
    1407             : /**
    1408             :  * \brief Fetch column index for given usage.
    1409             :  *
    1410             :  * This function is the same as the C++ method
    1411             :  * GDALRasterAttributeTable::GetColOfUsage()
    1412             :  */
    1413          13 : int CPL_STDCALL GDALRATGetColOfUsage(GDALRasterAttributeTableH hRAT,
    1414             :                                      GDALRATFieldUsage eUsage)
    1415             : 
    1416             : {
    1417          13 :     VALIDATE_POINTER1(hRAT, "GDALRATGetColOfUsage", 0);
    1418             : 
    1419          13 :     return GDALRasterAttributeTable::FromHandle(hRAT)->GetColOfUsage(eUsage);
    1420             : }
    1421             : 
    1422             : /************************************************************************/
    1423             : /*                            GetRowCount()                             */
    1424             : /************************************************************************/
    1425             : 
    1426          97 : int GDALDefaultRasterAttributeTable::GetRowCount() const
    1427             : 
    1428             : {
    1429          97 :     return static_cast<int>(nRowCount);
    1430             : }
    1431             : 
    1432             : /************************************************************************/
    1433             : /*                        GDALRATGetUsageOfCol()                        */
    1434             : /************************************************************************/
    1435             : /**
    1436             :  * \brief Fetch row count.
    1437             :  *
    1438             :  * This function is the same as the C++ method
    1439             :  * GDALRasterAttributeTable::GetRowCount()
    1440             :  */
    1441          41 : int CPL_STDCALL GDALRATGetRowCount(GDALRasterAttributeTableH hRAT)
    1442             : 
    1443             : {
    1444          41 :     VALIDATE_POINTER1(hRAT, "GDALRATGetRowCount", 0);
    1445             : 
    1446          41 :     return GDALRasterAttributeTable::FromHandle(hRAT)->GetRowCount();
    1447             : }
    1448             : 
    1449             : /************************************************************************/
    1450             : /*                          GetValueAsString()                          */
    1451             : /************************************************************************/
    1452             : 
    1453          22 : const char *GDALDefaultRasterAttributeTable::GetValueAsString(int iRow,
    1454             :                                                               int iField) const
    1455             : 
    1456             : {
    1457          22 :     if (iField < 0 || iField >= static_cast<int>(aoFields.size()))
    1458             :     {
    1459           0 :         CPLError(CE_Failure, CPLE_AppDefined, "iField (%d) out of range.",
    1460             :                  iField);
    1461             : 
    1462           0 :         return "";
    1463             :     }
    1464             : 
    1465          22 :     if (iRow < 0 || iRow >= nRowCount)
    1466             :     {
    1467           0 :         CPLError(CE_Failure, CPLE_AppDefined, "iRow (%d) out of range.", iRow);
    1468             : 
    1469           0 :         return "";
    1470             :     }
    1471             : 
    1472          22 :     switch (aoFields[iField].eType)
    1473             :     {
    1474           0 :         case GFT_Integer:
    1475             :         {
    1476             :             const_cast<GDALDefaultRasterAttributeTable *>(this)
    1477           0 :                 ->osWorkingResult.Printf("%d", aoFields[iField].anValues[iRow]);
    1478           0 :             return osWorkingResult;
    1479             :         }
    1480             : 
    1481           0 :         case GFT_Real:
    1482             :         {
    1483             :             const_cast<GDALDefaultRasterAttributeTable *>(this)
    1484             :                 ->osWorkingResult.Printf("%.16g",
    1485           0 :                                          aoFields[iField].adfValues[iRow]);
    1486           0 :             return osWorkingResult;
    1487             :         }
    1488             : 
    1489          22 :         case GFT_String:
    1490             :         {
    1491          22 :             return aoFields[iField].aosValues[iRow];
    1492             :         }
    1493             :     }
    1494             : 
    1495           0 :     return "";
    1496             : }
    1497             : 
    1498             : /************************************************************************/
    1499             : /*                      GDALRATGetValueAsString()                       */
    1500             : /************************************************************************/
    1501             : /**
    1502             :  * \brief Fetch field value as a string.
    1503             :  *
    1504             :  * This function is the same as the C++ method
    1505             :  * GDALRasterAttributeTable::GetValueAsString()
    1506             :  */
    1507          36 : const char *CPL_STDCALL GDALRATGetValueAsString(GDALRasterAttributeTableH hRAT,
    1508             :                                                 int iRow, int iField)
    1509             : 
    1510             : {
    1511          36 :     VALIDATE_POINTER1(hRAT, "GDALRATGetValueAsString", nullptr);
    1512             : 
    1513          72 :     return GDALRasterAttributeTable::FromHandle(hRAT)->GetValueAsString(iRow,
    1514          36 :                                                                         iField);
    1515             : }
    1516             : 
    1517             : /************************************************************************/
    1518             : /*                           GetValueAsInt()                            */
    1519             : /************************************************************************/
    1520             : 
    1521         171 : int GDALDefaultRasterAttributeTable::GetValueAsInt(int iRow, int iField) const
    1522             : 
    1523             : {
    1524         171 :     if (iField < 0 || iField >= static_cast<int>(aoFields.size()))
    1525             :     {
    1526           0 :         CPLError(CE_Failure, CPLE_AppDefined, "iField (%d) out of range.",
    1527             :                  iField);
    1528             : 
    1529           0 :         return 0;
    1530             :     }
    1531             : 
    1532         171 :     if (iRow < 0 || iRow >= nRowCount)
    1533             :     {
    1534           0 :         CPLError(CE_Failure, CPLE_AppDefined, "iRow (%d) out of range.", iRow);
    1535             : 
    1536           0 :         return 0;
    1537             :     }
    1538             : 
    1539         171 :     switch (aoFields[iField].eType)
    1540             :     {
    1541         171 :         case GFT_Integer:
    1542         171 :             return aoFields[iField].anValues[iRow];
    1543             : 
    1544           0 :         case GFT_Real:
    1545           0 :             return static_cast<int>(aoFields[iField].adfValues[iRow]);
    1546             : 
    1547           0 :         case GFT_String:
    1548           0 :             return atoi(aoFields[iField].aosValues[iRow].c_str());
    1549             :     }
    1550             : 
    1551           0 :     return 0;
    1552             : }
    1553             : 
    1554             : /************************************************************************/
    1555             : /*                        GDALRATGetValueAsInt()                        */
    1556             : /************************************************************************/
    1557             : 
    1558             : /**
    1559             :  * \brief Fetch field value as a integer.
    1560             :  *
    1561             :  * This function is the same as the C++ method
    1562             :  * GDALRasterAttributeTable::GetValueAsInt()
    1563             :  */
    1564          52 : int CPL_STDCALL GDALRATGetValueAsInt(GDALRasterAttributeTableH hRAT, int iRow,
    1565             :                                      int iField)
    1566             : 
    1567             : {
    1568          52 :     VALIDATE_POINTER1(hRAT, "GDALRATGetValueAsInt", 0);
    1569             : 
    1570         104 :     return GDALRasterAttributeTable::FromHandle(hRAT)->GetValueAsInt(iRow,
    1571          52 :                                                                      iField);
    1572             : }
    1573             : 
    1574             : /************************************************************************/
    1575             : /*                          GetValueAsDouble()                          */
    1576             : /************************************************************************/
    1577             : 
    1578        1035 : double GDALDefaultRasterAttributeTable::GetValueAsDouble(int iRow,
    1579             :                                                          int iField) const
    1580             : 
    1581             : {
    1582        1035 :     if (iField < 0 || iField >= static_cast<int>(aoFields.size()))
    1583             :     {
    1584           0 :         CPLError(CE_Failure, CPLE_AppDefined, "iField (%d) out of range.",
    1585             :                  iField);
    1586             : 
    1587           0 :         return 0;
    1588             :     }
    1589             : 
    1590        1035 :     if (iRow < 0 || iRow >= nRowCount)
    1591             :     {
    1592           0 :         CPLError(CE_Failure, CPLE_AppDefined, "iRow (%d) out of range.", iRow);
    1593             : 
    1594           0 :         return 0;
    1595             :     }
    1596             : 
    1597        1035 :     switch (aoFields[iField].eType)
    1598             :     {
    1599           0 :         case GFT_Integer:
    1600           0 :             return aoFields[iField].anValues[iRow];
    1601             : 
    1602        1035 :         case GFT_Real:
    1603        1035 :             return aoFields[iField].adfValues[iRow];
    1604             : 
    1605           0 :         case GFT_String:
    1606           0 :             return CPLAtof(aoFields[iField].aosValues[iRow].c_str());
    1607             :     }
    1608             : 
    1609           0 :     return 0;
    1610             : }
    1611             : 
    1612             : /************************************************************************/
    1613             : /*                      GDALRATGetValueAsDouble()                       */
    1614             : /************************************************************************/
    1615             : 
    1616             : /**
    1617             :  * \brief Fetch field value as a double.
    1618             :  *
    1619             :  * This function is the same as the C++ method
    1620             :  * GDALRasterAttributeTable::GetValueAsDouble()
    1621             :  */
    1622          33 : double CPL_STDCALL GDALRATGetValueAsDouble(GDALRasterAttributeTableH hRAT,
    1623             :                                            int iRow, int iField)
    1624             : 
    1625             : {
    1626          33 :     VALIDATE_POINTER1(hRAT, "GDALRATGetValueAsDouble", 0);
    1627             : 
    1628          66 :     return GDALRasterAttributeTable::FromHandle(hRAT)->GetValueAsDouble(iRow,
    1629          33 :                                                                         iField);
    1630             : }
    1631             : 
    1632             : /************************************************************************/
    1633             : /*                            SetRowCount()                             */
    1634             : /************************************************************************/
    1635             : 
    1636             : /** Set row count.
    1637             :  * @param nNewCount new count.
    1638             :  */
    1639        1477 : void GDALDefaultRasterAttributeTable::SetRowCount(int nNewCount)
    1640             : 
    1641             : {
    1642        1477 :     if (nNewCount == nRowCount)
    1643          20 :         return;
    1644             : 
    1645        3450 :     for (auto &oField : aoFields)
    1646             :     {
    1647        1993 :         switch (oField.eType)
    1648             :         {
    1649         535 :             case GFT_Integer:
    1650         535 :                 oField.anValues.resize(nNewCount);
    1651         535 :                 break;
    1652             : 
    1653        1368 :             case GFT_Real:
    1654        1368 :                 oField.adfValues.resize(nNewCount);
    1655        1368 :                 break;
    1656             : 
    1657          90 :             case GFT_String:
    1658          90 :                 oField.aosValues.resize(nNewCount);
    1659          90 :                 break;
    1660             :         }
    1661             :     }
    1662             : 
    1663        1457 :     nRowCount = nNewCount;
    1664             : }
    1665             : 
    1666             : /************************************************************************/
    1667             : /*                              SetValue()                              */
    1668             : /************************************************************************/
    1669             : 
    1670             : /** Set value
    1671             :  * @param iRow row index.
    1672             :  * @param iField field index.
    1673             :  * @param pszValue value.
    1674             :  */
    1675        1877 : void GDALDefaultRasterAttributeTable::SetValue(int iRow, int iField,
    1676             :                                                const char *pszValue)
    1677             : 
    1678             : {
    1679        1877 :     if (iField < 0 || iField >= static_cast<int>(aoFields.size()))
    1680             :     {
    1681           0 :         CPLError(CE_Failure, CPLE_AppDefined, "iField (%d) out of range.",
    1682             :                  iField);
    1683             : 
    1684           0 :         return;
    1685             :     }
    1686             : 
    1687        1877 :     if (iRow == nRowCount)
    1688        1287 :         SetRowCount(nRowCount + 1);
    1689             : 
    1690        1877 :     if (iRow < 0 || iRow >= nRowCount)
    1691             :     {
    1692           0 :         CPLError(CE_Failure, CPLE_AppDefined, "iRow (%d) out of range.", iRow);
    1693             : 
    1694           0 :         return;
    1695             :     }
    1696             : 
    1697        1877 :     switch (aoFields[iField].eType)
    1698             :     {
    1699          10 :         case GFT_Integer:
    1700          10 :             aoFields[iField].anValues[iRow] = atoi(pszValue);
    1701          10 :             break;
    1702             : 
    1703        1280 :         case GFT_Real:
    1704        1280 :             aoFields[iField].adfValues[iRow] = CPLAtof(pszValue);
    1705        1280 :             break;
    1706             : 
    1707         587 :         case GFT_String:
    1708         587 :             aoFields[iField].aosValues[iRow] = pszValue;
    1709         587 :             break;
    1710             :     }
    1711             : }
    1712             : 
    1713             : /************************************************************************/
    1714             : /*                      GDALRATSetValueAsString()                       */
    1715             : /************************************************************************/
    1716             : 
    1717             : /**
    1718             :  * \brief Set field value from string.
    1719             :  *
    1720             :  * This function is the same as the C++ method
    1721             :  * GDALRasterAttributeTable::SetValue()
    1722             :  * @param hRAT RAT handle.
    1723             :  * @param iRow row index.
    1724             :  * @param iField field index.
    1725             :  * @param pszValue value.
    1726             :  */
    1727          27 : void CPL_STDCALL GDALRATSetValueAsString(GDALRasterAttributeTableH hRAT,
    1728             :                                          int iRow, int iField,
    1729             :                                          const char *pszValue)
    1730             : 
    1731             : {
    1732          27 :     VALIDATE_POINTER0(hRAT, "GDALRATSetValueAsString");
    1733             : 
    1734          27 :     GDALRasterAttributeTable::FromHandle(hRAT)->SetValue(iRow, iField,
    1735          27 :                                                          pszValue);
    1736             : }
    1737             : 
    1738             : /************************************************************************/
    1739             : /*                              SetValue()                              */
    1740             : /************************************************************************/
    1741             : 
    1742        1032 : void GDALDefaultRasterAttributeTable::SetValue(int iRow, int iField, int nValue)
    1743             : 
    1744             : {
    1745        1032 :     if (iField < 0 || iField >= static_cast<int>(aoFields.size()))
    1746             :     {
    1747           0 :         CPLError(CE_Failure, CPLE_AppDefined, "iField (%d) out of range.",
    1748             :                  iField);
    1749             : 
    1750           0 :         return;
    1751             :     }
    1752             : 
    1753        1032 :     if (iRow == nRowCount)
    1754         157 :         SetRowCount(nRowCount + 1);
    1755             : 
    1756        1032 :     if (iRow < 0 || iRow >= nRowCount)
    1757             :     {
    1758           0 :         CPLError(CE_Failure, CPLE_AppDefined, "iRow (%d) out of range.", iRow);
    1759             : 
    1760           0 :         return;
    1761             :     }
    1762             : 
    1763        1032 :     switch (aoFields[iField].eType)
    1764             :     {
    1765        1032 :         case GFT_Integer:
    1766        1032 :             aoFields[iField].anValues[iRow] = nValue;
    1767        1032 :             break;
    1768             : 
    1769           0 :         case GFT_Real:
    1770           0 :             aoFields[iField].adfValues[iRow] = nValue;
    1771           0 :             break;
    1772             : 
    1773           0 :         case GFT_String:
    1774             :         {
    1775             :             char szValue[100];
    1776             : 
    1777           0 :             snprintf(szValue, sizeof(szValue), "%d", nValue);
    1778           0 :             aoFields[iField].aosValues[iRow] = szValue;
    1779             :         }
    1780           0 :         break;
    1781             :     }
    1782             : }
    1783             : 
    1784             : /************************************************************************/
    1785             : /*                        GDALRATSetValueAsInt()                        */
    1786             : /************************************************************************/
    1787             : 
    1788             : /**
    1789             :  * \brief Set field value from integer.
    1790             :  *
    1791             :  * This function is the same as the C++ method
    1792             :  * GDALRasterAttributeTable::SetValue()
    1793             :  */
    1794          39 : void CPL_STDCALL GDALRATSetValueAsInt(GDALRasterAttributeTableH hRAT, int iRow,
    1795             :                                       int iField, int nValue)
    1796             : 
    1797             : {
    1798          39 :     VALIDATE_POINTER0(hRAT, "GDALRATSetValueAsInt");
    1799             : 
    1800          39 :     GDALRasterAttributeTable::FromHandle(hRAT)->SetValue(iRow, iField, nValue);
    1801             : }
    1802             : 
    1803             : /************************************************************************/
    1804             : /*                              SetValue()                              */
    1805             : /************************************************************************/
    1806             : 
    1807        2804 : void GDALDefaultRasterAttributeTable::SetValue(int iRow, int iField,
    1808             :                                                double dfValue)
    1809             : 
    1810             : {
    1811        2804 :     if (iField < 0 || iField >= static_cast<int>(aoFields.size()))
    1812             :     {
    1813           0 :         CPLError(CE_Failure, CPLE_AppDefined, "iField (%d) out of range.",
    1814             :                  iField);
    1815             : 
    1816           0 :         return;
    1817             :     }
    1818             : 
    1819        2804 :     if (iRow == nRowCount)
    1820           0 :         SetRowCount(nRowCount + 1);
    1821             : 
    1822        2804 :     if (iRow < 0 || iRow >= nRowCount)
    1823             :     {
    1824           0 :         CPLError(CE_Failure, CPLE_AppDefined, "iRow (%d) out of range.", iRow);
    1825             : 
    1826           0 :         return;
    1827             :     }
    1828             : 
    1829        2804 :     switch (aoFields[iField].eType)
    1830             :     {
    1831           0 :         case GFT_Integer:
    1832           0 :             aoFields[iField].anValues[iRow] = static_cast<int>(dfValue);
    1833           0 :             break;
    1834             : 
    1835        2804 :         case GFT_Real:
    1836        2804 :             aoFields[iField].adfValues[iRow] = dfValue;
    1837        2804 :             break;
    1838             : 
    1839           0 :         case GFT_String:
    1840             :         {
    1841           0 :             char szValue[100] = {'\0'};
    1842             : 
    1843           0 :             CPLsnprintf(szValue, sizeof(szValue), "%.15g", dfValue);
    1844           0 :             aoFields[iField].aosValues[iRow] = szValue;
    1845             :         }
    1846           0 :         break;
    1847             :     }
    1848             : }
    1849             : 
    1850             : /************************************************************************/
    1851             : /*                      GDALRATSetValueAsDouble()                       */
    1852             : /************************************************************************/
    1853             : 
    1854             : /**
    1855             :  * \brief Set field value from double.
    1856             :  *
    1857             :  * This function is the same as the C++ method
    1858             :  * GDALRasterAttributeTable::SetValue()
    1859             :  */
    1860          25 : void CPL_STDCALL GDALRATSetValueAsDouble(GDALRasterAttributeTableH hRAT,
    1861             :                                          int iRow, int iField, double dfValue)
    1862             : 
    1863             : {
    1864          25 :     VALIDATE_POINTER0(hRAT, "GDALRATSetValueAsDouble");
    1865             : 
    1866          25 :     GDALRasterAttributeTable::FromHandle(hRAT)->SetValue(iRow, iField, dfValue);
    1867             : }
    1868             : 
    1869             : /************************************************************************/
    1870             : /*                       ChangesAreWrittenToFile()                      */
    1871             : /************************************************************************/
    1872             : 
    1873           0 : int GDALDefaultRasterAttributeTable::ChangesAreWrittenToFile()
    1874             : {
    1875             :     // GDALRasterBand.SetDefaultRAT needs to be called on instances of
    1876             :     // GDALDefaultRasterAttributeTable since changes are just in-memory
    1877           0 :     return false;
    1878             : }
    1879             : 
    1880             : /************************************************************************/
    1881             : /*                   GDALRATChangesAreWrittenToFile()                   */
    1882             : /************************************************************************/
    1883             : 
    1884             : /**
    1885             :  * \brief Determine whether changes made to this RAT are reflected directly in
    1886             :  * the dataset
    1887             :  *
    1888             :  * This function is the same as the C++ method
    1889             :  * GDALRasterAttributeTable::ChangesAreWrittenToFile()
    1890             :  */
    1891           2 : int CPL_STDCALL GDALRATChangesAreWrittenToFile(GDALRasterAttributeTableH hRAT)
    1892             : {
    1893           2 :     VALIDATE_POINTER1(hRAT, "GDALRATChangesAreWrittenToFile", false);
    1894             : 
    1895           2 :     return GDALRasterAttributeTable::FromHandle(hRAT)
    1896           2 :         ->ChangesAreWrittenToFile();
    1897             : }
    1898             : 
    1899             : /************************************************************************/
    1900             : /*                           GetRowOfValue()                            */
    1901             : /************************************************************************/
    1902             : 
    1903           2 : int GDALDefaultRasterAttributeTable::GetRowOfValue(double dfValue) const
    1904             : 
    1905             : {
    1906             :     /* -------------------------------------------------------------------- */
    1907             :     /*      Handle case of regular binning.                                 */
    1908             :     /* -------------------------------------------------------------------- */
    1909           2 :     if (bLinearBinning)
    1910             :     {
    1911           0 :         const int iBin =
    1912           0 :             static_cast<int>(floor((dfValue - dfRow0Min) / dfBinSize));
    1913           0 :         if (iBin < 0 || iBin >= nRowCount)
    1914           0 :             return -1;
    1915             : 
    1916           0 :         return iBin;
    1917             :     }
    1918             : 
    1919             :     /* -------------------------------------------------------------------- */
    1920             :     /*      Do we have any information?                                     */
    1921             :     /* -------------------------------------------------------------------- */
    1922           2 :     if (!bColumnsAnalysed)
    1923           2 :         const_cast<GDALDefaultRasterAttributeTable *>(this)->AnalyseColumns();
    1924             : 
    1925           2 :     if (nMinCol == -1 && nMaxCol == -1)
    1926           0 :         return -1;
    1927             : 
    1928           2 :     const GDALRasterAttributeField *poMin = nullptr;
    1929           2 :     if (nMinCol != -1)
    1930           2 :         poMin = &(aoFields[nMinCol]);
    1931             :     else
    1932           0 :         poMin = nullptr;
    1933             : 
    1934           2 :     const GDALRasterAttributeField *poMax = nullptr;
    1935           2 :     if (nMaxCol != -1)
    1936           2 :         poMax = &(aoFields[nMaxCol]);
    1937             :     else
    1938           0 :         poMax = nullptr;
    1939             : 
    1940             :     /* -------------------------------------------------------------------- */
    1941             :     /*      Search through rows for match.                                  */
    1942             :     /* -------------------------------------------------------------------- */
    1943           4 :     for (int iRow = 0; iRow < nRowCount; iRow++)
    1944             :     {
    1945           4 :         if (poMin != nullptr)
    1946             :         {
    1947           4 :             if (poMin->eType == GFT_Integer)
    1948             :             {
    1949           4 :                 while (iRow < nRowCount && dfValue < poMin->anValues[iRow])
    1950           0 :                     iRow++;
    1951             :             }
    1952           0 :             else if (poMin->eType == GFT_Real)
    1953             :             {
    1954           0 :                 while (iRow < nRowCount && dfValue < poMin->adfValues[iRow])
    1955           0 :                     iRow++;
    1956             :             }
    1957             : 
    1958           4 :             if (iRow == nRowCount)
    1959           0 :                 break;
    1960             :         }
    1961             : 
    1962           4 :         if (poMax != nullptr)
    1963             :         {
    1964          14 :             if ((poMax->eType == GFT_Integer &&
    1965           6 :                  dfValue > poMax->anValues[iRow]) ||
    1966           2 :                 (poMax->eType == GFT_Real && dfValue > poMax->adfValues[iRow]))
    1967           2 :                 continue;
    1968             :         }
    1969             : 
    1970           2 :         return iRow;
    1971             :     }
    1972             : 
    1973           0 :     return -1;
    1974             : }
    1975             : 
    1976             : /************************************************************************/
    1977             : /*                           GetRowOfValue()                            */
    1978             : /*                                                                      */
    1979             : /*      Int arg for now just converted to double.  Perhaps we will      */
    1980             : /*      handle this in a special way some day?                          */
    1981             : /************************************************************************/
    1982             : 
    1983           0 : int GDALDefaultRasterAttributeTable::GetRowOfValue(int nValue) const
    1984             : 
    1985             : {
    1986           0 :     return GetRowOfValue(static_cast<double>(nValue));
    1987             : }
    1988             : 
    1989             : /************************************************************************/
    1990             : /*                          SetLinearBinning()                          */
    1991             : /************************************************************************/
    1992             : 
    1993          13 : CPLErr GDALDefaultRasterAttributeTable::SetLinearBinning(double dfRow0MinIn,
    1994             :                                                          double dfBinSizeIn)
    1995             : 
    1996             : {
    1997          13 :     bLinearBinning = true;
    1998          13 :     dfRow0Min = dfRow0MinIn;
    1999          13 :     dfBinSize = dfBinSizeIn;
    2000             : 
    2001          13 :     return CE_None;
    2002             : }
    2003             : 
    2004             : /************************************************************************/
    2005             : /*                          GetLinearBinning()                          */
    2006             : /************************************************************************/
    2007             : 
    2008          13 : int GDALDefaultRasterAttributeTable::GetLinearBinning(double *pdfRow0Min,
    2009             :                                                       double *pdfBinSize) const
    2010             : 
    2011             : {
    2012          13 :     if (!bLinearBinning)
    2013           9 :         return false;
    2014             : 
    2015           4 :     *pdfRow0Min = dfRow0Min;
    2016           4 :     *pdfBinSize = dfBinSize;
    2017             : 
    2018           4 :     return true;
    2019             : }
    2020             : 
    2021             : /************************************************************************/
    2022             : /*                          GetTableType()                              */
    2023             : /************************************************************************/
    2024             : 
    2025             : /**
    2026             :  * \brief Get RAT Table Type
    2027             :  *
    2028             :  * Returns whether table type is thematic or athematic
    2029             :  *
    2030             :  * This method is the same as the C function GDALRATGetTableType().
    2031             :  *
    2032             :  * @since GDAL 2.4
    2033             :  *
    2034             :  * @return GRTT_THEMATIC or GRTT_ATHEMATIC
    2035             :  */
    2036             : 
    2037          15 : GDALRATTableType GDALDefaultRasterAttributeTable::GetTableType() const
    2038             : {
    2039          15 :     return eTableType;
    2040             : }
    2041             : 
    2042             : /************************************************************************/
    2043             : /*                          SetTableType()                              */
    2044             : /************************************************************************/
    2045             : 
    2046             : /**
    2047             :  * \brief Set RAT Table Type
    2048             :  *
    2049             :  * Set whether table type is thematic or athematic
    2050             :  *
    2051             :  * This method is the same as the C function GDALRATSetTableType().
    2052             :  *
    2053             :  * @param eInTableType the new RAT table type (GRTT_THEMATIC or GRTT_ATHEMATIC)
    2054             :  *
    2055             :  * @since GDAL 2.4
    2056             :  *
    2057             :  * @return CE_None on success or CE_Failure on failure.
    2058             :  */
    2059             : 
    2060          28 : CPLErr GDALDefaultRasterAttributeTable::SetTableType(
    2061             :     const GDALRATTableType eInTableType)
    2062             : {
    2063          28 :     eTableType = eInTableType;
    2064          28 :     return CE_None;
    2065             : }
    2066             : 
    2067             : /************************************************************************/
    2068             : /*                            CreateColumn()                            */
    2069             : /************************************************************************/
    2070             : 
    2071             : CPLErr
    2072         169 : GDALDefaultRasterAttributeTable::CreateColumn(const char *pszFieldName,
    2073             :                                               GDALRATFieldType eFieldType,
    2074             :                                               GDALRATFieldUsage eFieldUsage)
    2075             : 
    2076             : {
    2077         169 :     const size_t iNewField = aoFields.size();
    2078             : 
    2079         169 :     aoFields.resize(iNewField + 1);
    2080             : 
    2081         169 :     aoFields[iNewField].sName = pszFieldName;
    2082             : 
    2083             :     // color columns should be int 0..255
    2084         169 :     if ((eFieldUsage == GFU_Red) || (eFieldUsage == GFU_Green) ||
    2085         133 :         (eFieldUsage == GFU_Blue) || (eFieldUsage == GFU_Alpha))
    2086             :     {
    2087          41 :         eFieldType = GFT_Integer;
    2088             :     }
    2089         169 :     aoFields[iNewField].eType = eFieldType;
    2090         169 :     aoFields[iNewField].eUsage = eFieldUsage;
    2091             : 
    2092         169 :     if (eFieldType == GFT_Integer)
    2093          98 :         aoFields[iNewField].anValues.resize(nRowCount);
    2094          71 :     else if (eFieldType == GFT_Real)
    2095          37 :         aoFields[iNewField].adfValues.resize(nRowCount);
    2096          34 :     else if (eFieldType == GFT_String)
    2097          34 :         aoFields[iNewField].aosValues.resize(nRowCount);
    2098             : 
    2099         169 :     return CE_None;
    2100             : }
    2101             : 
    2102             : /************************************************************************/
    2103             : /*                            RemoveStatistics()                        */
    2104             : /************************************************************************/
    2105             : 
    2106             : /**
    2107             :  * \brief Remove Statistics from RAT
    2108             :  *
    2109             :  * Remove statistics (such as histogram) from the RAT. This is important
    2110             :  * if these have been invalidated, for example by cropping the image.
    2111             :  *
    2112             :  * This method is the same as the C function GDALRATRemoveStatistics().
    2113             :  *
    2114             :  * @since GDAL 2.4
    2115             :  */
    2116             : 
    2117           2 : void GDALDefaultRasterAttributeTable::RemoveStatistics()
    2118             : 
    2119             : {
    2120             :     // since we are storing the fields in a vector it will generally
    2121             :     // be faster to create a new vector and replace the old one
    2122             :     // rather than actually erasing columns.
    2123           4 :     std::vector<GDALRasterAttributeField> aoNewFields;
    2124           4 :     for (const auto &field : aoFields)
    2125             :     {
    2126           2 :         switch (field.eUsage)
    2127             :         {
    2128           1 :             case GFU_PixelCount:
    2129             :             case GFU_Min:
    2130             :             case GFU_Max:
    2131             :             case GFU_RedMin:
    2132             :             case GFU_GreenMin:
    2133             :             case GFU_BlueMin:
    2134             :             case GFU_AlphaMin:
    2135             :             case GFU_RedMax:
    2136             :             case GFU_GreenMax:
    2137             :             case GFU_BlueMax:
    2138             :             case GFU_AlphaMax:
    2139             :             {
    2140           1 :                 break;
    2141             :             }
    2142             : 
    2143           1 :             default:
    2144           1 :                 if (field.sName != "Histogram")
    2145             :                 {
    2146           1 :                     aoNewFields.push_back(field);
    2147             :                 }
    2148             :         }
    2149             :     }
    2150           2 :     aoFields = std::move(aoNewFields);
    2151           2 : }
    2152             : 
    2153             : /************************************************************************/
    2154             : /*                               Clone()                                */
    2155             : /************************************************************************/
    2156             : 
    2157          12 : GDALDefaultRasterAttributeTable *GDALDefaultRasterAttributeTable::Clone() const
    2158             : 
    2159             : {
    2160          12 :     return new GDALDefaultRasterAttributeTable(*this);
    2161             : }
    2162             : 
    2163             : /************************************************************************/
    2164             : /*                            GDALRATClone()                            */
    2165             : /************************************************************************/
    2166             : 
    2167             : /**
    2168             :  * \brief Copy Raster Attribute Table
    2169             :  *
    2170             :  * This function is the same as the C++ method GDALRasterAttributeTable::Clone()
    2171             :  */
    2172             : GDALRasterAttributeTableH CPL_STDCALL
    2173           5 : GDALRATClone(const GDALRasterAttributeTableH hRAT)
    2174             : 
    2175             : {
    2176           5 :     VALIDATE_POINTER1(hRAT, "GDALRATClone", nullptr);
    2177             : 
    2178           5 :     return GDALRasterAttributeTable::FromHandle(hRAT)->Clone();
    2179             : }
    2180             : 
    2181             : /************************************************************************/
    2182             : /*                            GDALRATSerializeJSON()                    */
    2183             : /************************************************************************/
    2184             : 
    2185             : /**
    2186             :  * \brief Serialize Raster Attribute Table in Json format
    2187             :  *
    2188             :  * This function is the same as the C++ method
    2189             :  * GDALRasterAttributeTable::SerializeJSON()
    2190             :  */
    2191           3 : void *CPL_STDCALL GDALRATSerializeJSON(GDALRasterAttributeTableH hRAT)
    2192             : 
    2193             : {
    2194           3 :     VALIDATE_POINTER1(hRAT, "GDALRATSerializeJSON", nullptr);
    2195             : 
    2196           3 :     return GDALRasterAttributeTable::FromHandle(hRAT)->SerializeJSON();
    2197             : }
    2198             : 
    2199             : /************************************************************************/
    2200             : /*                        GDALRATRemoveStatistics()                     */
    2201             : /************************************************************************/
    2202             : 
    2203             : /**
    2204             :  * \brief Remove Statistics from RAT
    2205             :  *
    2206             :  * This function is the same as the C++ method
    2207             :  * GDALRasterAttributeTable::RemoveStatistics()
    2208             :  *
    2209             :  * @since GDAL 2.4
    2210             :  */
    2211           1 : void CPL_STDCALL GDALRATRemoveStatistics(GDALRasterAttributeTableH hRAT)
    2212             : 
    2213             : {
    2214           1 :     VALIDATE_POINTER0(hRAT, "GDALRATRemoveStatistics");
    2215             : 
    2216           1 :     GDALRasterAttributeTable::FromHandle(hRAT)->RemoveStatistics();
    2217             : }

Generated by: LCOV version 1.14