Coverage Report

Created: 2025-11-15 08:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/apps/gdalalg_raster_index.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  GDAL
4
 * Purpose:  gdal "raster index" 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_index.h"
14
15
#include "cpl_conv.h"
16
#include "gdal_priv.h"
17
#include "gdal_utils_priv.h"
18
#include "ogrsf_frmts.h"
19
20
//! @cond Doxygen_Suppress
21
22
#ifndef _
23
0
#define _(x) (x)
24
#endif
25
26
/************************************************************************/
27
/*          GDALRasterIndexAlgorithm::GDALRasterIndexAlgorithm()        */
28
/************************************************************************/
29
30
GDALRasterIndexAlgorithm::GDALRasterIndexAlgorithm()
31
0
    : GDALVectorOutputAbstractAlgorithm(NAME, DESCRIPTION, HELP_URL)
32
0
{
33
0
    AddProgressArg();
34
0
    AddInputDatasetArg(&m_inputDatasets, GDAL_OF_RASTER)
35
0
        .SetAutoOpenDataset(false)
36
0
        .SetDatasetInputFlags(GADV_NAME);
37
0
    GDALVectorOutputAbstractAlgorithm::AddAllOutputArgs();
38
39
0
    AddCommonOptions();
40
41
0
    AddArg("source-crs-field-name", 0,
42
0
           _("Name of the field to store the CRS of each dataset"),
43
0
           &m_sourceCrsName)
44
0
        .SetMinCharCount(1);
45
0
    AddArg("source-crs-format", 0,
46
0
           _("Format in which the CRS of each dataset must be written"),
47
0
           &m_sourceCrsFormat)
48
0
        .SetMinCharCount(1)
49
0
        .SetDefault(m_sourceCrsFormat)
50
0
        .SetChoices("auto", "WKT", "EPSG", "PROJ");
51
0
}
52
53
/************************************************************************/
54
/*          GDALRasterIndexAlgorithm::GDALRasterIndexAlgorithm()        */
55
/************************************************************************/
56
57
GDALRasterIndexAlgorithm::GDALRasterIndexAlgorithm(
58
    const std::string &name, const std::string &description,
59
    const std::string &helpURL)
60
0
    : GDALVectorOutputAbstractAlgorithm(name, description, helpURL)
61
0
{
62
0
}
63
64
/************************************************************************/
65
/*              GDALRasterIndexAlgorithm::AddCommonOptions()            */
66
/************************************************************************/
67
68
void GDALRasterIndexAlgorithm::AddCommonOptions()
69
0
{
70
0
    AddArg("recursive", 0,
71
0
           _("Whether input directories should be explored recursively."),
72
0
           &m_recursive);
73
0
    AddArg("filename-filter", 0,
74
0
           _("Pattern that the filenames in input directories should follow "
75
0
             "('*' and '?' wildcard)"),
76
0
           &m_filenameFilter);
77
0
    AddArg("min-pixel-size", 0,
78
0
           _("Minimum pixel size in term of geospatial extent per pixel "
79
0
             "(resolution) that a raster should have to be selected."),
80
0
           &m_minPixelSize)
81
0
        .SetMinValueExcluded(0);
82
0
    AddArg("max-pixel-size", 0,
83
0
           _("Maximum pixel size in term of geospatial extent per pixel "
84
0
             "(resolution) that a raster should have to be selected."),
85
0
           &m_maxPixelSize)
86
0
        .SetMinValueExcluded(0);
87
0
    AddArg("location-name", 0, _("Name of the field with the raster path"),
88
0
           &m_locationName)
89
0
        .SetDefault(m_locationName)
90
0
        .SetMinCharCount(1);
91
0
    AddAbsolutePathArg(
92
0
        &m_writeAbsolutePaths,
93
0
        _("Whether the path to the input datasets should be stored as an "
94
0
          "absolute path"));
95
0
    AddArg("dst-crs", 0, _("Destination CRS"), &m_crs)
96
0
        .SetIsCRSArg()
97
0
        .AddHiddenAlias("t_srs");
98
99
0
    {
100
0
        auto &arg =
101
0
            AddArg("metadata", 0, _("Add dataset metadata item"), &m_metadata)
102
0
                .SetMetaVar("<KEY>=<VALUE>")
103
0
                .SetPackedValuesAllowed(false);
104
0
        arg.AddValidationAction([this, &arg]()
105
0
                                { return ParseAndValidateKeyValue(arg); });
106
0
        arg.AddHiddenAlias("mo");
107
0
    }
108
109
0
    AddArg("skip-errors", 0, _("Skip errors related to input datasets"),
110
0
           &m_skipErrors);
111
0
}
112
113
/************************************************************************/
114
/*                   GDALRasterIndexAlgorithm::RunImpl()                */
115
/************************************************************************/
116
117
bool GDALRasterIndexAlgorithm::RunImpl(GDALProgressFunc pfnProgress,
118
                                       void *pProgressData)
119
0
{
120
0
    CPLStringList aosSources;
121
0
    for (auto &srcDS : m_inputDatasets)
122
0
    {
123
0
        if (srcDS.GetDatasetRef())
124
0
        {
125
0
            ReportError(
126
0
                CE_Failure, CPLE_IllegalArg,
127
0
                "Input datasets must be provided by name, not as object");
128
0
            return false;
129
0
        }
130
0
        aosSources.push_back(srcDS.GetName());
131
0
    }
132
133
0
    auto setupRet = SetupOutputDataset();
134
0
    if (!setupRet.outDS)
135
0
        return false;
136
137
0
    if (!SetDefaultOutputLayerNameIfNeeded(setupRet.outDS))
138
0
        return false;
139
140
0
    CPLStringList aosOptions;
141
0
    aosOptions.push_back("--invoked-from-gdal-raster-index");
142
143
0
    if (m_skipErrors)
144
0
    {
145
0
        aosOptions.push_back("-skip_errors");
146
0
    }
147
0
    if (m_recursive)
148
0
    {
149
0
        aosOptions.push_back("-recursive");
150
0
    }
151
0
    for (const std::string &s : m_filenameFilter)
152
0
    {
153
0
        aosOptions.push_back("-filename_filter");
154
0
        aosOptions.push_back(s);
155
0
    }
156
0
    if (m_minPixelSize > 0)
157
0
    {
158
0
        aosOptions.push_back("-min_pixel_size");
159
0
        aosOptions.push_back(CPLSPrintf("%.17g", m_minPixelSize));
160
0
    }
161
0
    if (m_maxPixelSize > 0)
162
0
    {
163
0
        aosOptions.push_back("-max_pixel_size");
164
0
        aosOptions.push_back(CPLSPrintf("%.17g", m_maxPixelSize));
165
0
    }
166
167
0
    if (!m_outputLayerName.empty())
168
0
    {
169
0
        aosOptions.push_back("-lyr_name");
170
0
        aosOptions.push_back(m_outputLayerName);
171
0
    }
172
173
0
    aosOptions.push_back("-tileindex");
174
0
    aosOptions.push_back(m_locationName);
175
176
0
    if (m_writeAbsolutePaths)
177
0
    {
178
0
        aosOptions.push_back("-write_absolute_path");
179
0
    }
180
0
    if (m_crs.empty())
181
0
    {
182
0
        if (m_sourceCrsName.empty())
183
0
            aosOptions.push_back("-skip_different_projection");
184
0
    }
185
0
    else
186
0
    {
187
0
        aosOptions.push_back("-t_srs");
188
0
        aosOptions.push_back(m_crs);
189
0
    }
190
0
    if (!m_sourceCrsName.empty())
191
0
    {
192
0
        aosOptions.push_back("-src_srs_name");
193
0
        aosOptions.push_back(m_sourceCrsName);
194
195
0
        aosOptions.push_back("-src_srs_format");
196
0
        aosOptions.push_back(CPLString(m_sourceCrsFormat).toupper());
197
0
    }
198
199
0
    for (const std::string &s : m_metadata)
200
0
    {
201
0
        aosOptions.push_back("-mo");
202
0
        aosOptions.push_back(s);
203
0
    }
204
205
0
    if (!AddExtraOptions(aosOptions))
206
0
        return false;
207
208
0
    std::unique_ptr<GDALTileIndexOptions, decltype(&GDALTileIndexOptionsFree)>
209
0
        options(GDALTileIndexOptionsNew(aosOptions.List(), nullptr),
210
0
                GDALTileIndexOptionsFree);
211
212
0
    if (options)
213
0
    {
214
0
        GDALTileIndexOptionsSetProgress(options.get(), pfnProgress,
215
0
                                        pProgressData);
216
0
    }
217
218
0
    const bool ret =
219
0
        options && GDALTileIndexInternal(m_outputDataset.GetName().c_str(),
220
0
                                         GDALDataset::ToHandle(setupRet.outDS),
221
0
                                         OGRLayer::ToHandle(setupRet.layer),
222
0
                                         aosSources.size(), aosSources.List(),
223
0
                                         options.get(), nullptr) != nullptr;
224
225
0
    if (ret && setupRet.newDS)
226
0
    {
227
0
        m_outputDataset.Set(std::move(setupRet.newDS));
228
0
    }
229
230
0
    return ret;
231
0
}
232
233
//! @endcond