Skip to content

Commit

Permalink
Add 'gdal raster overview add' and 'gdal raster overview delete'
Browse files Browse the repository at this point in the history
  • Loading branch information
rouault committed Jan 8, 2025
1 parent d43d1ed commit ac7f7a0
Show file tree
Hide file tree
Showing 14 changed files with 802 additions and 0 deletions.
2 changes: 2 additions & 0 deletions apps/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ add_library(
gdalalg_raster_convert.cpp
gdalalg_raster_edit.cpp
gdalalg_raster_pipeline.cpp
gdalalg_raster_overview_add.cpp
gdalalg_raster_overview_delete.cpp
gdalalg_raster_read.cpp
gdalalg_raster_reproject.cpp
gdalalg_raster_write.cpp
Expand Down
2 changes: 2 additions & 0 deletions apps/gdalalg_raster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "gdalalg_raster_info.h"
#include "gdalalg_raster_convert.h"
#include "gdalalg_raster_edit.h"
#include "gdalalg_raster_overview.h"
#include "gdalalg_raster_pipeline.h"
#include "gdalalg_raster_reproject.h"

Expand All @@ -40,6 +41,7 @@ class GDALRasterAlgorithm final : public GDALAlgorithm
RegisterSubAlgorithm<GDALRasterInfoAlgorithm>();
RegisterSubAlgorithm<GDALRasterConvertAlgorithm>();
RegisterSubAlgorithm<GDALRasterEditAlgorithmStandalone>();
RegisterSubAlgorithm<GDALRasterOverviewAlgorithm>();
RegisterSubAlgorithm<GDALRasterPipelineAlgorithm>();
RegisterSubAlgorithm<GDALRasterReprojectAlgorithmStandalone>();
RegisterSubAlgorithm<GDALRasterBuildVRTAlgorithm>();
Expand Down
61 changes: 61 additions & 0 deletions apps/gdalalg_raster_overview.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/******************************************************************************
*
* Project: GDAL
* Purpose: gdal "raster overview" subcommand
* Author: Even Rouault <even dot rouault at spatialys.com>
*
******************************************************************************
* Copyright (c) 2025, Even Rouault <even dot rouault at spatialys.com>
*
* SPDX-License-Identifier: MIT
****************************************************************************/

#ifndef GDALALG_RASTER_OVERVIEW_INCLUDED
#define GDALALG_RASTER_OVERVIEW_INCLUDED

#include "gdalalgorithm.h"

//! @cond Doxygen_Suppress

#include "gdalalgorithm.h"

#include "gdalalg_raster_overview_add.h"
#include "gdalalg_raster_overview_delete.h"

/************************************************************************/
/* GDALRasterOverviewAlgorithm */
/************************************************************************/

class GDALRasterOverviewAlgorithm final : public GDALAlgorithm
{
public:
static constexpr const char *NAME = "overview";
static constexpr const char *DESCRIPTION =
"Manage overviews of a raster dataset.";
static constexpr const char *HELP_URL =
"/programs/gdal_raster_overview.html";

static std::vector<std::string> GetAliases()
{
return {};
}

GDALRasterOverviewAlgorithm() : GDALAlgorithm(NAME, DESCRIPTION, HELP_URL)
{
RegisterSubAlgorithm<GDALRasterOverviewAlgorithmAdd>();
RegisterSubAlgorithm<GDALRasterOverviewAlgorithmDelete>();
}

private:
bool RunImpl(GDALProgressFunc, void *) override
{
CPLError(CE_Failure, CPLE_AppDefined,
"The Run() method should not be called directly on the \"gdal "
"raster overview\" program.");
return false;
}
};

//! @endcond

#endif
157 changes: 157 additions & 0 deletions apps/gdalalg_raster_overview_add.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/******************************************************************************
*
* Project: GDAL
* Purpose: gdal "raster overview add" subcommand
* Author: Even Rouault <even dot rouault at spatialys.com>
*
******************************************************************************
* Copyright (c) 2025, Even Rouault <even dot rouault at spatialys.com>
*
* SPDX-License-Identifier: MIT
****************************************************************************/

#include "gdalalg_raster_overview_add.h"

#include "cpl_string.h"
#include "gdal_priv.h"

//! @cond Doxygen_Suppress

#ifndef _
#define _(x) (x)
#endif

/************************************************************************/
/* GDALRasterOverviewAlgorithmAdd() */
/************************************************************************/

GDALRasterOverviewAlgorithmAdd::GDALRasterOverviewAlgorithmAdd()
: GDALAlgorithm(NAME, DESCRIPTION, HELP_URL)
{
AddProgressArg();
AddOpenOptionsArg(&m_openOptions);
AddArg("dataset", 0, _("Dataset (in-place updated, unless --read-only)"),
&m_dataset, GDAL_OF_RASTER | GDAL_OF_UPDATE)
.SetPositional()
.SetRequired();
AddArg(GDAL_ARG_NAME_READ_ONLY, 0, _("Open the dataset in read-only mode"),
&m_readOnly)
.AddHiddenAlias("ro");

AddArg("resampling", 'r', _("Resampling method"), &m_resampling)
.SetChoices("nearest", "average", "cubic", "cubicspline", "lanczos",
"bilinear", "gauss", "average_magphase", "rms", "mode")
.SetHiddenChoices("near");

auto &levelArg =
AddArg("levels", 0, _("Levels / decimation factors"), &m_levels);
levelArg.AddValidationAction(
[this, &levelArg]()
{
const auto &values = levelArg.Get<std::vector<int>>();
for (const auto &value : values)
{
if (value < 2)
{
ReportError(CE_Failure, CPLE_IllegalArg,
"Values of 'levels' argument should be "
"integers greater or equal to 2.");
return false;
}
}
return true;
});

auto &minSizeArg =
AddArg("min-size", 0,
_("Maximum width or height of the smallest overview level."),
&m_minSize);
minSizeArg.AddValidationAction(
[this, &minSizeArg]()
{
const int val = minSizeArg.Get<int>();
if (val <= 0)
{
ReportError(CE_Failure, CPLE_IllegalArg,
"Value of 'min-size' should be an integer greater "
"or equal to 1.");
return false;
}
return true;
});
}

/************************************************************************/
/* GDALRasterOverviewAlgorithmAdd::RunImpl() */
/************************************************************************/

bool GDALRasterOverviewAlgorithmAdd::RunImpl(GDALProgressFunc pfnProgress,
void *pProgressData)
{
auto poDS = m_dataset.GetDatasetRef();
CPLAssert(poDS);

std::string resampling = m_resampling;
if (resampling.empty() && poDS->GetRasterCount() > 0)
{
auto poBand = poDS->GetRasterBand(1);
if (poBand->GetOverviewCount() > 0)
{
const char *pszResampling =
poBand->GetOverview(0)->GetMetadataItem("RESAMPLING");
if (pszResampling)
{
resampling = pszResampling;
CPLDebug("GDAL",
"Reusing resampling method %s from existing "
"overview",
pszResampling);
}
}
}
if (resampling.empty())
resampling = "nearest";

std::vector<int> levels = m_levels;

// If no levels are specified, reuse the potentially existing ones.
if (levels.empty() && poDS->GetRasterCount() > 0)
{
auto poBand = poDS->GetRasterBand(1);
const int nExistingCount = poBand->GetOverviewCount();
if (nExistingCount > 0)
{
for (int iOvr = 0; iOvr < nExistingCount; ++iOvr)
{
auto poOverview = poBand->GetOverview(iOvr);
if (poOverview)
{
const int nOvFactor = GDALComputeOvFactor(
poOverview->GetXSize(), poBand->GetXSize(),
poOverview->GetYSize(), poBand->GetYSize());
levels.push_back(nOvFactor);
}
}
}
}

if (levels.empty())
{
const int nXSize = poDS->GetRasterXSize();
const int nYSize = poDS->GetRasterYSize();
int nOvrFactor = 1;
while (DIV_ROUND_UP(nXSize, nOvrFactor) > m_minSize ||
DIV_ROUND_UP(nYSize, nOvrFactor) > m_minSize)
{
nOvrFactor *= 2;
levels.push_back(nOvrFactor);
}
}

return levels.empty() ||
GDALBuildOverviews(GDALDataset::ToHandle(poDS), resampling.c_str(),
static_cast<int>(levels.size()), levels.data(), 0,
nullptr, pfnProgress, pProgressData) == CE_None;
}

//! @endcond
53 changes: 53 additions & 0 deletions apps/gdalalg_raster_overview_add.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/******************************************************************************
*
* Project: GDAL
* Purpose: gdal "raster overview add" subcommand
* Author: Even Rouault <even dot rouault at spatialys.com>
*
******************************************************************************
* Copyright (c) 2025, Even Rouault <even dot rouault at spatialys.com>
*
* SPDX-License-Identifier: MIT
****************************************************************************/

#ifndef GDALALG_RASTER_OVERVIEW_ADD_INCLUDED
#define GDALALG_RASTER_OVERVIEW_ADD_INCLUDED

#include "gdalalgorithm.h"

//! @cond Doxygen_Suppress

/************************************************************************/
/* GDALRasterOverviewAlgorithmAdd */
/************************************************************************/

class GDALRasterOverviewAlgorithmAdd final : public GDALAlgorithm
{
public:
static constexpr const char *NAME = "add";
static constexpr const char *DESCRIPTION = "Adding overviews.";
static constexpr const char *HELP_URL =
"/programs/gdal_raster_overview_add.html";

static std::vector<std::string> GetAliases()
{
return {};
}

GDALRasterOverviewAlgorithmAdd();

private:
bool RunImpl(GDALProgressFunc, void *) override;

GDALArgDatasetValue m_dataset{};
std::vector<std::string> m_openOptions{};
std::vector<std::string> m_inputFormats{};
std::string m_resampling{};
std::vector<int> m_levels{};
int m_minSize = 256;
bool m_readOnly = false;
};

//! @endcond

#endif
56 changes: 56 additions & 0 deletions apps/gdalalg_raster_overview_delete.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/******************************************************************************
*
* Project: GDAL
* Purpose: gdal "raster overview delete" subcommand
* Author: Even Rouault <even dot rouault at spatialys.com>
*
******************************************************************************
* Copyright (c) 2025, Even Rouault <even dot rouault at spatialys.com>
*
* SPDX-License-Identifier: MIT
****************************************************************************/

#include "gdalalg_raster_overview_delete.h"

#include "gdal_priv.h"

//! @cond Doxygen_Suppress

#ifndef _
#define _(x) (x)
#endif

/************************************************************************/
/* GDALRasterOverviewAlgorithmDelete() */
/************************************************************************/

GDALRasterOverviewAlgorithmDelete::GDALRasterOverviewAlgorithmDelete()
: GDALAlgorithm(NAME, DESCRIPTION, HELP_URL)
{
AddProgressArg();
AddOpenOptionsArg(&m_openOptions);
AddArg("dataset", 0, _("Dataset (in-place updated, unless --read-only)"),
&m_dataset, GDAL_OF_RASTER | GDAL_OF_UPDATE)
.SetPositional()
.SetRequired();
AddArg(GDAL_ARG_NAME_READ_ONLY, 0, _("Open the dataset in read-only mode"),
&m_readOnly)
.AddHiddenAlias("ro");
}

/************************************************************************/
/* GDALRasterOverviewAlgorithmDelete::RunImpl() */
/************************************************************************/

bool GDALRasterOverviewAlgorithmDelete::RunImpl(GDALProgressFunc pfnProgress,
void *pProgressData)
{
auto poDS = m_dataset.GetDatasetRef();
CPLAssert(poDS);

return GDALBuildOverviews(GDALDataset::ToHandle(poDS), "NONE", 0, nullptr,
0, nullptr, pfnProgress,
pProgressData) == CE_None;
}

//! @endcond
Loading

0 comments on commit ac7f7a0

Please sign in to comment.