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 15 : GDALRasterOverviewAlgorithmAdd::GDALRasterOverviewAlgorithmAdd()
29 15 : : GDALAlgorithm(NAME, DESCRIPTION, HELP_URL)
30 : {
31 15 : AddProgressArg();
32 15 : AddOpenOptionsArg(&m_openOptions);
33 : AddArg("dataset", 0,
34 : _("Dataset (to be updated in-place, unless --external)"), &m_dataset,
35 30 : GDAL_OF_RASTER | GDAL_OF_UPDATE)
36 15 : .SetPositional()
37 15 : .SetRequired();
38 30 : AddArg("external", 0, _("Add external overviews"), &m_readOnly)
39 30 : .AddHiddenAlias("ro")
40 15 : .AddHiddenAlias(GDAL_ARG_NAME_READ_ONLY);
41 :
42 30 : AddArg("resampling", 'r', _("Resampling method"), &m_resampling)
43 : .SetChoices("nearest", "average", "cubic", "cubicspline", "lanczos",
44 15 : "bilinear", "gauss", "average_magphase", "rms", "mode")
45 15 : .SetHiddenChoices("near", "none");
46 :
47 30 : AddArg("levels", 0, _("Levels / decimation factors"), &m_levels)
48 15 : .SetMinValueIncluded(2);
49 : AddArg("min-size", 0,
50 : _("Maximum width or height of the smallest overview level."),
51 30 : &m_minSize)
52 15 : .SetMinValueIncluded(1);
53 15 : }
54 :
55 : /************************************************************************/
56 : /* GDALRasterOverviewAlgorithmAdd::RunImpl() */
57 : /************************************************************************/
58 :
59 8 : bool GDALRasterOverviewAlgorithmAdd::RunImpl(GDALProgressFunc pfnProgress,
60 : void *pProgressData)
61 : {
62 8 : auto poDS = m_dataset.GetDatasetRef();
63 8 : CPLAssert(poDS);
64 :
65 16 : std::string resampling = m_resampling;
66 8 : if (resampling.empty() && poDS->GetRasterCount() > 0)
67 : {
68 5 : auto poBand = poDS->GetRasterBand(1);
69 5 : if (poBand->GetOverviewCount() > 0)
70 : {
71 : const char *pszResampling =
72 1 : poBand->GetOverview(0)->GetMetadataItem("RESAMPLING");
73 1 : if (pszResampling)
74 : {
75 1 : resampling = pszResampling;
76 1 : CPLDebug("GDAL",
77 : "Reusing resampling method %s from existing "
78 : "overview",
79 : pszResampling);
80 : }
81 : }
82 : }
83 8 : if (resampling.empty())
84 4 : resampling = "nearest";
85 :
86 8 : std::vector<int> levels = m_levels;
87 :
88 : // If no levels are specified, reuse the potentially existing ones.
89 8 : if (levels.empty() && poDS->GetRasterCount() > 0)
90 : {
91 5 : auto poBand = poDS->GetRasterBand(1);
92 5 : const int nExistingCount = poBand->GetOverviewCount();
93 5 : if (nExistingCount > 0)
94 : {
95 2 : for (int iOvr = 0; iOvr < nExistingCount; ++iOvr)
96 : {
97 1 : auto poOverview = poBand->GetOverview(iOvr);
98 1 : if (poOverview)
99 : {
100 1 : const int nOvFactor = GDALComputeOvFactor(
101 : poOverview->GetXSize(), poBand->GetXSize(),
102 1 : poOverview->GetYSize(), poBand->GetYSize());
103 1 : levels.push_back(nOvFactor);
104 : }
105 : }
106 : }
107 : }
108 :
109 8 : if (levels.empty())
110 : {
111 4 : const int nXSize = poDS->GetRasterXSize();
112 4 : const int nYSize = poDS->GetRasterYSize();
113 4 : int nOvrFactor = 1;
114 9 : while (DIV_ROUND_UP(nXSize, nOvrFactor) > m_minSize ||
115 4 : DIV_ROUND_UP(nYSize, nOvrFactor) > m_minSize)
116 : {
117 5 : nOvrFactor *= 2;
118 5 : levels.push_back(nOvrFactor);
119 : }
120 : }
121 :
122 16 : return levels.empty() ||
123 8 : GDALBuildOverviews(GDALDataset::ToHandle(poDS), resampling.c_str(),
124 8 : static_cast<int>(levels.size()), levels.data(), 0,
125 16 : nullptr, pfnProgress, pProgressData) == CE_None;
126 : }
127 :
128 : //! @endcond
|