LCOV - code coverage report
Current view: top level - gcore - gdal_rat_vat_dbf.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 57 59 96.6 %
Date: 2025-01-18 12:42:00 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL Core
       4             :  * Purpose:  Read ArcGIS .vat.dbf raster attribute table
       5             :  * Author:   Even Rouault <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "gdal_priv.h"
      14             : #include "gdal_rat.h"
      15             : #include "ogrsf_frmts.h"
      16             : 
      17             : #include <algorithm>
      18             : 
      19             : /************************************************************************/
      20             : /*                            GDALLoadVATDBF()                          */
      21             : /************************************************************************/
      22             : 
      23             : /**
      24             :  * \brief Load a ESRI .vat.dbf auxiliary file as a GDAL attribute table.
      25             :  *
      26             :  * @since GDAL 3.11
      27             :  */
      28             : std::unique_ptr<GDALRasterAttributeTable>
      29           3 : GDALLoadVATDBF(const char *pszFilename)
      30             : {
      31             :     auto poDS = std::unique_ptr<GDALDataset>(
      32             :         GDALDataset::Open(pszFilename, GDAL_OF_VECTOR | GDAL_OF_VERBOSE_ERROR,
      33           6 :                           nullptr, nullptr, nullptr));
      34           3 :     auto poLayer = poDS ? poDS->GetLayer(0) : nullptr;
      35           3 :     if (!poLayer)
      36           1 :         return nullptr;
      37           4 :     auto poRAT = std::make_unique<GDALDefaultRasterAttributeTable>();
      38             : 
      39           2 :     const auto poFDefn = poLayer->GetLayerDefn();
      40           2 :     int iRedIdxFloat = -1;
      41           2 :     int iGreenIdxFloat = -1;
      42           2 :     int iBlueIdxFloat = -1;
      43           2 :     const int nFieldCount = poFDefn->GetFieldCount();
      44          20 :     for (int i = 0; i < nFieldCount; ++i)
      45             :     {
      46          18 :         const auto poFieldDefn = poFDefn->GetFieldDefn(i);
      47          18 :         const auto eFieldType = poFieldDefn->GetType();
      48          18 :         const char *pszName = poFieldDefn->GetNameRef();
      49          18 :         if (EQUAL(pszName, "VALUE"))
      50             :         {
      51           2 :             if (eFieldType == OFTReal)
      52           0 :                 poRAT->CreateColumn(pszName, GFT_Real, GFU_MinMax);
      53             :             else
      54           2 :                 poRAT->CreateColumn(pszName, GFT_Integer, GFU_MinMax);
      55             :         }
      56          16 :         else if (EQUAL(pszName, "COUNT") &&
      57           0 :                  (eFieldType == OFTInteger || eFieldType == OFTInteger64))
      58             :         {
      59           2 :             poRAT->CreateColumn(pszName, GFT_Integer, GFU_PixelCount);
      60             :         }
      61          14 :         else if ((STARTS_WITH_CI(pszName, "CLASS") || EQUAL(pszName, "NAME")) &&
      62             :                  eFieldType == OFTString)
      63             :         {
      64           2 :             poRAT->CreateColumn(pszName, GFT_String, GFU_Name);
      65             :         }
      66          12 :         else if (EQUAL(pszName, "RED") && !strstr(pszName, "min") &&
      67           2 :                  !strstr(pszName, "max") && eFieldType == OFTReal)
      68             :         {
      69             :             // Convert from [0,1] to [0,255]
      70           2 :             iRedIdxFloat = i;
      71           2 :             poRAT->CreateColumn(pszName, GFT_Integer, GFU_Red);
      72             :         }
      73          10 :         else if (EQUAL(pszName, "GREEN") && !strstr(pszName, "min") &&
      74           2 :                  !strstr(pszName, "max") && eFieldType == OFTReal)
      75             :         {
      76             :             // Convert from [0,1] to [0,255]
      77           2 :             iGreenIdxFloat = i;
      78           2 :             poRAT->CreateColumn(pszName, GFT_Integer, GFU_Green);
      79             :         }
      80           8 :         else if (EQUAL(pszName, "BLUE") && !strstr(pszName, "min") &&
      81           2 :                  !strstr(pszName, "max") && eFieldType == OFTReal)
      82             :         {
      83             :             // Convert from [0,1] to [0,255]
      84           2 :             iBlueIdxFloat = i;
      85           2 :             poRAT->CreateColumn(pszName, GFT_Integer, GFU_Blue);
      86             :         }
      87             :         else
      88             :         {
      89          12 :             poRAT->CreateColumn(
      90             :                 pszName,
      91             :                 eFieldType == OFTReal ? GFT_Real
      92           2 :                 : (eFieldType == OFTInteger || eFieldType == OFTInteger64)
      93           6 :                     ? GFT_Integer
      94             :                     : GFT_String,
      95           6 :                 GFU_Generic);
      96             :         }
      97             :     }
      98             : 
      99           2 :     int iRow = 0;
     100           6 :     for (auto &&poFeature : *poLayer)
     101             :     {
     102          40 :         for (int i = 0; i < nFieldCount; ++i)
     103             :         {
     104          36 :             if (i == iRedIdxFloat || i == iGreenIdxFloat || i == iBlueIdxFloat)
     105             :             {
     106          12 :                 poRAT->SetValue(
     107             :                     iRow, i,
     108             :                     static_cast<int>(
     109          24 :                         std::clamp(255.0 * poFeature->GetFieldAsDouble(i) + 0.5,
     110          36 :                                    0.0, 255.0)));
     111             :             }
     112             :             else
     113             :             {
     114          24 :                 switch (poRAT->GDALDefaultRasterAttributeTable::GetTypeOfCol(i))
     115             :                 {
     116          12 :                     case GFT_Integer:
     117             :                     {
     118          12 :                         poRAT->GDALDefaultRasterAttributeTable::SetValue(
     119             :                             iRow, i, poFeature->GetFieldAsInteger(i));
     120          12 :                         break;
     121             :                     }
     122           4 :                     case GFT_Real:
     123             :                     {
     124           4 :                         poRAT->GDALDefaultRasterAttributeTable::SetValue(
     125             :                             iRow, i, poFeature->GetFieldAsDouble(i));
     126           4 :                         break;
     127             :                     }
     128           8 :                     case GFT_String:
     129             :                     {
     130           8 :                         poRAT->GDALDefaultRasterAttributeTable::SetValue(
     131             :                             iRow, i, poFeature->GetFieldAsString(i));
     132           8 :                         break;
     133             :                     }
     134             :                 }
     135             :             }
     136             :         }
     137           4 :         ++iRow;
     138             :     }
     139             : 
     140           2 :     return poRAT;
     141             : }

Generated by: LCOV version 1.14