LCOV - code coverage report
Current view: top level - apps - gdalalg_raster_overview_add.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 67 67 100.0 %
Date: 2025-01-18 12:42:00 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  gdal "raster overview add" subcommand
       5             :  * Author:   Even Rouault <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2025, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "gdalalg_raster_overview_add.h"
      14             : 
      15             : #include "cpl_string.h"
      16             : #include "gdal_priv.h"
      17             : 
      18             : //! @cond Doxygen_Suppress
      19             : 
      20             : #ifndef _
      21             : #define _(x) (x)
      22             : #endif
      23             : 
      24             : /************************************************************************/
      25             : /*                    GDALRasterOverviewAlgorithmAdd()                  */
      26             : /************************************************************************/
      27             : 
      28          11 : GDALRasterOverviewAlgorithmAdd::GDALRasterOverviewAlgorithmAdd()
      29          11 :     : GDALAlgorithm(NAME, DESCRIPTION, HELP_URL)
      30             : {
      31          11 :     AddProgressArg();
      32          11 :     AddOpenOptionsArg(&m_openOptions);
      33             :     AddArg("dataset", 0, _("Dataset (in-place updated, unless --read-only)"),
      34          22 :            &m_dataset, GDAL_OF_RASTER | GDAL_OF_UPDATE)
      35          11 :         .SetPositional()
      36          11 :         .SetRequired();
      37          22 :     AddArg("external", 0, _("Add external overviews"), &m_readOnly)
      38          22 :         .AddHiddenAlias("ro")
      39          11 :         .AddHiddenAlias(GDAL_ARG_NAME_READ_ONLY);
      40             : 
      41          22 :     AddArg("resampling", 'r', _("Resampling method"), &m_resampling)
      42             :         .SetChoices("nearest", "average", "cubic", "cubicspline", "lanczos",
      43          11 :                     "bilinear", "gauss", "average_magphase", "rms", "mode")
      44          11 :         .SetHiddenChoices("near");
      45             : 
      46             :     auto &levelArg =
      47          11 :         AddArg("levels", 0, _("Levels / decimation factors"), &m_levels);
      48             :     levelArg.AddValidationAction(
      49           5 :         [this, &levelArg]()
      50             :         {
      51           4 :             const auto &values = levelArg.Get<std::vector<int>>();
      52           7 :             for (const auto &value : values)
      53             :             {
      54           4 :                 if (value < 2)
      55             :                 {
      56           1 :                     ReportError(CE_Failure, CPLE_IllegalArg,
      57             :                                 "Values of 'levels' argument should be "
      58             :                                 "integers greater or equal to 2.");
      59           1 :                     return false;
      60             :                 }
      61             :             }
      62           3 :             return true;
      63          11 :         });
      64             : 
      65             :     auto &minSizeArg =
      66             :         AddArg("min-size", 0,
      67             :                _("Maximum width or height of the smallest overview level."),
      68          11 :                &m_minSize);
      69             :     minSizeArg.AddValidationAction(
      70           5 :         [this, &minSizeArg]()
      71             :         {
      72           4 :             const int val = minSizeArg.Get<int>();
      73           4 :             if (val <= 0)
      74             :             {
      75           1 :                 ReportError(CE_Failure, CPLE_IllegalArg,
      76             :                             "Value of 'min-size' should be an integer greater "
      77             :                             "or equal to 1.");
      78           1 :                 return false;
      79             :             }
      80           3 :             return true;
      81          11 :         });
      82          11 : }
      83             : 
      84             : /************************************************************************/
      85             : /*                GDALRasterOverviewAlgorithmAdd::RunImpl()             */
      86             : /************************************************************************/
      87             : 
      88           7 : bool GDALRasterOverviewAlgorithmAdd::RunImpl(GDALProgressFunc pfnProgress,
      89             :                                              void *pProgressData)
      90             : {
      91           7 :     auto poDS = m_dataset.GetDatasetRef();
      92           7 :     CPLAssert(poDS);
      93             : 
      94          14 :     std::string resampling = m_resampling;
      95           7 :     if (resampling.empty() && poDS->GetRasterCount() > 0)
      96             :     {
      97           4 :         auto poBand = poDS->GetRasterBand(1);
      98           4 :         if (poBand->GetOverviewCount() > 0)
      99             :         {
     100             :             const char *pszResampling =
     101           1 :                 poBand->GetOverview(0)->GetMetadataItem("RESAMPLING");
     102           1 :             if (pszResampling)
     103             :             {
     104           1 :                 resampling = pszResampling;
     105           1 :                 CPLDebug("GDAL",
     106             :                          "Reusing resampling method %s from existing "
     107             :                          "overview",
     108             :                          pszResampling);
     109             :             }
     110             :         }
     111             :     }
     112           7 :     if (resampling.empty())
     113           3 :         resampling = "nearest";
     114             : 
     115           7 :     std::vector<int> levels = m_levels;
     116             : 
     117             :     // If no levels are specified, reuse the potentially existing ones.
     118           7 :     if (levels.empty() && poDS->GetRasterCount() > 0)
     119             :     {
     120           4 :         auto poBand = poDS->GetRasterBand(1);
     121           4 :         const int nExistingCount = poBand->GetOverviewCount();
     122           4 :         if (nExistingCount > 0)
     123             :         {
     124           2 :             for (int iOvr = 0; iOvr < nExistingCount; ++iOvr)
     125             :             {
     126           1 :                 auto poOverview = poBand->GetOverview(iOvr);
     127           1 :                 if (poOverview)
     128             :                 {
     129           1 :                     const int nOvFactor = GDALComputeOvFactor(
     130             :                         poOverview->GetXSize(), poBand->GetXSize(),
     131           1 :                         poOverview->GetYSize(), poBand->GetYSize());
     132           1 :                     levels.push_back(nOvFactor);
     133             :                 }
     134             :             }
     135             :         }
     136             :     }
     137             : 
     138           7 :     if (levels.empty())
     139             :     {
     140           3 :         const int nXSize = poDS->GetRasterXSize();
     141           3 :         const int nYSize = poDS->GetRasterYSize();
     142           3 :         int nOvrFactor = 1;
     143           6 :         while (DIV_ROUND_UP(nXSize, nOvrFactor) > m_minSize ||
     144           3 :                DIV_ROUND_UP(nYSize, nOvrFactor) > m_minSize)
     145             :         {
     146           3 :             nOvrFactor *= 2;
     147           3 :             levels.push_back(nOvrFactor);
     148             :         }
     149             :     }
     150             : 
     151          14 :     return levels.empty() ||
     152           7 :            GDALBuildOverviews(GDALDataset::ToHandle(poDS), resampling.c_str(),
     153           7 :                               static_cast<int>(levels.size()), levels.data(), 0,
     154          14 :                               nullptr, pfnProgress, pProgressData) == CE_None;
     155             : }
     156             : 
     157             : //! @endcond

Generated by: LCOV version 1.14