Skip to content

Commit abe9935

Browse files
committed
CLI: make it possible to use pixel-info in 'gdal pipeline'
1 parent 7041600 commit abe9935

File tree

7 files changed

+212
-78
lines changed

7 files changed

+212
-78
lines changed

apps/gdalalg_pipeline.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "gdalalg_raster_footprint.h"
3232
#include "gdalalg_raster_polygonize.h"
3333
#include "gdalalg_raster_info.h"
34+
#include "gdalalg_raster_pixel_info.h"
3435
#include "gdalalg_raster_tile.h"
3536
#include "gdalalg_vector_grid.h"
3637
#include "gdalalg_vector_info.h"
@@ -498,6 +499,7 @@ GDALPipelineAlgorithm::GDALPipelineAlgorithm()
498499
m_stepRegistry.Register<GDALRasterAsFeaturesAlgorithm>();
499500
m_stepRegistry.Register<GDALRasterContourAlgorithm>();
500501
m_stepRegistry.Register<GDALRasterFootprintAlgorithm>();
502+
m_stepRegistry.Register<GDALRasterPixelInfoAlgorithm>();
501503
m_stepRegistry.Register<GDALRasterPolygonizeAlgorithm>();
502504
m_stepRegistry.Register<GDALRasterZonalStatsAlgorithm>();
503505
m_stepRegistry.Register<GDALVectorGridAlgorithm>();

apps/gdalalg_raster.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ GDALRasterAlgorithm::GDALRasterAlgorithm()
9696
RegisterSubAlgorithm<GDALRasterNeighborsAlgorithmStandalone>();
9797
RegisterSubAlgorithm<GDALRasterOverviewAlgorithmStandalone>();
9898
RegisterSubAlgorithm<GDALRasterPipelineAlgorithm>();
99-
RegisterSubAlgorithm<GDALRasterPixelInfoAlgorithm>();
99+
RegisterSubAlgorithm<GDALRasterPixelInfoAlgorithmStandalone>();
100100
RegisterSubAlgorithm<GDALRasterProximityAlgorithmStandalone>();
101101
RegisterSubAlgorithm<GDALRasterRGBToPaletteAlgorithmStandalone>();
102102
RegisterSubAlgorithm<GDALRasterReclassifyAlgorithmStandalone>();

apps/gdalalg_raster_pixel_info.cpp

Lines changed: 116 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -35,65 +35,94 @@
3535
/* GDALRasterPixelInfoAlgorithm::GDALRasterPixelInfoAlgorithm() */
3636
/************************************************************************/
3737

38-
GDALRasterPixelInfoAlgorithm::GDALRasterPixelInfoAlgorithm()
39-
: GDALAlgorithm(NAME, DESCRIPTION, HELP_URL)
38+
GDALRasterPixelInfoAlgorithm::GDALRasterPixelInfoAlgorithm(bool standaloneStep)
39+
: GDALPipelineStepAlgorithm(
40+
NAME, DESCRIPTION, HELP_URL,
41+
ConstructorOptions()
42+
.SetStandaloneStep(standaloneStep)
43+
.SetAddAppendLayerArgument(false)
44+
.SetAddOverwriteLayerArgument(false)
45+
.SetAddUpdateArgument(false)
46+
.SetAddUpsertArgument(false)
47+
.SetAddSkipErrorsArgument(false)
48+
.SetOutputFormatCreateCapability(GDAL_DCAP_CREATE))
4049
{
41-
AddOutputFormatArg(&m_format, false, false,
42-
_("Output format (default is 'GeoJSON' if "
43-
"'position-dataset' not specified)"))
44-
.AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES,
45-
{GDAL_DCAP_VECTOR, GDAL_DCAP_CREATE});
46-
AddOpenOptionsArg(&m_openOptions);
47-
AddInputFormatsArg(&m_inputFormats)
48-
.AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES, {GDAL_DCAP_RASTER});
49-
AddInputDatasetArg(&m_rasterDataset, GDAL_OF_RASTER).AddAlias("dataset");
50+
if (standaloneStep)
51+
{
52+
AddOutputFormatArg(&m_format, false, false,
53+
_("Output format (default is 'GeoJSON' if "
54+
"'position-dataset' not specified)"))
55+
.AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES,
56+
{GDAL_DCAP_VECTOR, GDAL_DCAP_CREATE});
57+
AddOpenOptionsArg(&m_openOptions);
58+
AddInputFormatsArg(&m_inputFormats)
59+
.AddMetadataItem(GAAMDI_REQUIRED_CAPABILITIES, {GDAL_DCAP_RASTER});
60+
}
61+
62+
AddInputDatasetArg(&m_inputDataset, GDAL_OF_RASTER,
63+
/* positionalAndRequired = */ standaloneStep)
64+
.AddAlias("dataset")
65+
.SetMinCount(1)
66+
.SetMaxCount(1)
67+
.SetHiddenForCLI(!standaloneStep);
5068

5169
{
5270
auto &coordinateDatasetArg =
5371
AddArg("position-dataset", '\0',
5472
_("Vector dataset with coordinates"), &m_vectorDataset,
5573
GDAL_OF_VECTOR)
5674
.SetMutualExclusionGroup("position-dataset-pos");
75+
if (!standaloneStep)
76+
coordinateDatasetArg.SetPositional().SetRequired();
5777

5878
SetAutoCompleteFunctionForFilename(coordinateDatasetArg,
5979
GDAL_OF_VECTOR);
6080

6181
auto &layerArg = AddArg(GDAL_ARG_NAME_INPUT_LAYER, 'l',
62-
_("Input layer name"), &m_inputLayerName)
82+
_("Input layer name"), &m_inputLayerNames)
83+
.SetMaxCount(1)
6384
.AddAlias("layer");
6485
SetAutoCompleteFunctionForLayerName(layerArg, coordinateDatasetArg);
6586
}
6687

6788
AddOutputDatasetArg(&m_outputDataset, GDAL_OF_VECTOR,
68-
/* positionalAndRequired = */ false);
69-
AddCreationOptionsArg(&m_creationOptions);
70-
AddLayerCreationOptionsArg(&m_layerCreationOptions);
71-
AddOverwriteArg(&m_overwrite);
72-
73-
AddOutputStringArg(&m_outputString);
89+
/* positionalAndRequired = */ false)
90+
.SetHiddenForCLI(!standaloneStep);
91+
if (standaloneStep)
92+
{
93+
AddCreationOptionsArg(&m_creationOptions);
94+
AddLayerCreationOptionsArg(&m_layerCreationOptions);
95+
AddOverwriteArg(&m_overwrite);
96+
AddOutputStringArg(&m_outputString).SetHiddenForCLI(!standaloneStep);
97+
}
7498

7599
AddBandArg(&m_band);
76100
AddArg("overview", 0, _("Which overview level of source file must be used"),
77101
&m_overview)
78102
.SetMinValueIncluded(0);
79103

80-
AddArg("position", 'p', _("Pixel position"), &m_pos)
81-
.AddAlias("pos")
82-
.SetMetaVar("<column,line> or <X,Y>")
83-
.SetPositional()
84-
.SetMutualExclusionGroup("position-dataset-pos")
85-
.AddValidationAction(
86-
[this]
87-
{
88-
if ((m_pos.size() % 2) != 0)
104+
if (standaloneStep)
105+
{
106+
AddArg("position", 'p', _("Pixel position"), &m_pos)
107+
.AddAlias("pos")
108+
.SetMetaVar("<column,line> or <X,Y>")
109+
.SetPositional()
110+
.SetMutualExclusionGroup("position-dataset-pos")
111+
.AddValidationAction(
112+
[this]
89113
{
90-
ReportError(CE_Failure, CPLE_IllegalArg,
91-
"An even number of values must be specified "
92-
"for 'position' argument");
93-
return false;
94-
}
95-
return true;
96-
});
114+
if ((m_pos.size() % 2) != 0)
115+
{
116+
ReportError(
117+
CE_Failure, CPLE_IllegalArg,
118+
"An even number of values must be specified "
119+
"for 'position' argument");
120+
return false;
121+
}
122+
return true;
123+
});
124+
}
125+
97126
AddArg("position-crs", 0,
98127
_("CRS of position (default is 'pixel' if 'position-dataset' not "
99128
"specified)"),
@@ -121,30 +150,34 @@ GDALRasterPixelInfoAlgorithm::GDALRasterPixelInfoAlgorithm()
121150
AddValidationAction(
122151
[this]
123152
{
124-
if (auto poSrcDS = m_rasterDataset.GetDatasetRef())
153+
if (m_inputDataset.size() == 1)
125154
{
126-
const int nOvrCount =
127-
poSrcDS->GetRasterBand(1)->GetOverviewCount();
128-
if (m_overview >= 0 && poSrcDS->GetRasterCount() > 0 &&
129-
m_overview >= nOvrCount)
155+
if (auto poSrcDS = m_inputDataset[0].GetDatasetRef())
130156
{
131-
if (nOvrCount == 0)
132-
{
133-
ReportError(
134-
CE_Failure, CPLE_IllegalArg,
135-
"Source dataset has no overviews. "
136-
"Argument 'overview' must not be specified.");
137-
}
138-
else
157+
const int nOvrCount =
158+
poSrcDS->GetRasterBand(1)->GetOverviewCount();
159+
if (m_overview >= 0 && poSrcDS->GetRasterCount() > 0 &&
160+
m_overview >= nOvrCount)
139161
{
140-
ReportError(
141-
CE_Failure, CPLE_IllegalArg,
142-
"Source dataset has only %d overview level%s. "
143-
"'overview' "
144-
"value must be strictly lower than this number.",
145-
nOvrCount, nOvrCount > 1 ? "s" : "");
162+
if (nOvrCount == 0)
163+
{
164+
ReportError(
165+
CE_Failure, CPLE_IllegalArg,
166+
"Source dataset has no overviews. "
167+
"Argument 'overview' must not be specified.");
168+
}
169+
else
170+
{
171+
ReportError(
172+
CE_Failure, CPLE_IllegalArg,
173+
"Source dataset has only %d overview level%s. "
174+
"'overview' "
175+
"value must be strictly lower than this "
176+
"number.",
177+
nOvrCount, nOvrCount > 1 ? "s" : "");
178+
}
179+
return false;
146180
}
147-
return false;
148181
}
149182
}
150183
return true;
@@ -168,9 +201,22 @@ GDALRasterPixelInfoAlgorithm::~GDALRasterPixelInfoAlgorithm()
168201
/* GDALRasterPixelInfoAlgorithm::RunImpl() */
169202
/************************************************************************/
170203

171-
bool GDALRasterPixelInfoAlgorithm::RunImpl(GDALProgressFunc, void *)
204+
bool GDALRasterPixelInfoAlgorithm::RunImpl(GDALProgressFunc pfnProgress,
205+
void *pProgressData)
172206
{
173-
auto poSrcDS = m_rasterDataset.GetDatasetRef();
207+
GDALPipelineStepRunContext stepCtxt;
208+
stepCtxt.m_pfnProgress = pfnProgress;
209+
stepCtxt.m_pProgressData = pProgressData;
210+
return RunPreStepPipelineValidations() && RunStep(stepCtxt);
211+
}
212+
213+
/************************************************************************/
214+
/* GDALRasterPixelInfoAlgorithm::RunStep() */
215+
/************************************************************************/
216+
217+
bool GDALRasterPixelInfoAlgorithm::RunStep(GDALPipelineStepRunContext &)
218+
{
219+
auto poSrcDS = m_inputDataset[0].GetDatasetRef();
174220
CPLAssert(poSrcDS);
175221

176222
auto poVectorSrcDS = m_vectorDataset.GetDatasetRef();
@@ -183,7 +229,11 @@ bool GDALRasterPixelInfoAlgorithm::RunImpl(GDALProgressFunc, void *)
183229
return false;
184230
}
185231

186-
if (m_outputDataset.GetName().empty())
232+
if (!m_standaloneStep)
233+
{
234+
m_format = "MEM";
235+
}
236+
else if (m_outputDataset.GetName().empty())
187237
{
188238
if (m_format.empty())
189239
{
@@ -217,7 +267,7 @@ bool GDALRasterPixelInfoAlgorithm::RunImpl(GDALProgressFunc, void *)
217267

218268
if (poVectorSrcDS)
219269
{
220-
if (m_inputLayerName.empty())
270+
if (m_inputLayerNames.empty())
221271
{
222272
const int nLayerCount = poVectorSrcDS->GetLayerCount();
223273
if (nLayerCount == 0)
@@ -240,20 +290,20 @@ bool GDALRasterPixelInfoAlgorithm::RunImpl(GDALProgressFunc, void *)
240290
else
241291
{
242292
poSrcLayer =
243-
poVectorSrcDS->GetLayerByName(m_inputLayerName.c_str());
293+
poVectorSrcDS->GetLayerByName(m_inputLayerNames[0].c_str());
244294
}
245295
if (!poSrcLayer)
246296
{
247297
ReportError(
248298
CE_Failure, CPLE_AppDefined, "Cannot find layer '%s' in '%s'",
249-
m_inputLayerName.c_str(), poVectorSrcDS->GetDescription());
299+
m_inputLayerNames[0].c_str(), poVectorSrcDS->GetDescription());
250300
return false;
251301
}
252302
if (poSrcLayer->GetGeomType() == wkbNone)
253303
{
254304
ReportError(CE_Failure, CPLE_AppDefined,
255305
"Layer '%s' of '%s' has no geometry column",
256-
m_inputLayerName.c_str(),
306+
m_inputLayerNames[0].c_str(),
257307
poVectorSrcDS->GetDescription());
258308
return false;
259309
}
@@ -370,7 +420,7 @@ bool GDALRasterPixelInfoAlgorithm::RunImpl(GDALProgressFunc, void *)
370420
}
371421
}
372422

373-
if (!osOutFilename.empty())
423+
if (!osOutFilename.empty() || !m_standaloneStep)
374424
{
375425
if (bIsGeoJSON)
376426
{
@@ -1038,7 +1088,7 @@ bool GDALRasterPixelInfoAlgorithm::RunImpl(GDALProgressFunc, void *)
10381088
}
10391089
else if (poOutDS)
10401090
{
1041-
if (m_outputDataset.GetName().empty())
1091+
if (m_outputDataset.GetName().empty() && m_standaloneStep)
10421092
{
10431093
poOutDS.reset();
10441094
if (!isInteractive)
@@ -1073,4 +1123,7 @@ bool GDALRasterPixelInfoAlgorithm::RunImpl(GDALProgressFunc, void *)
10731123
return bRet;
10741124
}
10751125

1126+
GDALRasterPixelInfoAlgorithmStandalone::
1127+
~GDALRasterPixelInfoAlgorithmStandalone() = default;
1128+
10761129
//! @endcond

apps/gdalalg_raster_pixel_info.h

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
#ifndef GDALALG_RASTER_PIXEL_INFO_INCLUDED
1414
#define GDALALG_RASTER_PIXEL_INFO_INCLUDED
1515

16-
#include "gdalalgorithm.h"
16+
#include "gdalalg_abstract_pipeline.h"
17+
1718
#include "cpl_vsi_virtual.h"
1819

1920
//! @cond Doxygen_Suppress
@@ -22,7 +23,8 @@
2223
/* GDALRasterPixelInfoAlgorithm */
2324
/************************************************************************/
2425

25-
class GDALRasterPixelInfoAlgorithm final : public GDALAlgorithm
26+
class GDALRasterPixelInfoAlgorithm /* non final */
27+
: public GDALPipelineStepAlgorithm
2628
{
2729
public:
2830
static constexpr const char *NAME = "pixel-info";
@@ -31,27 +33,36 @@ class GDALRasterPixelInfoAlgorithm final : public GDALAlgorithm
3133
static constexpr const char *HELP_URL =
3234
"/programs/gdal_raster_pixel_info.html";
3335

34-
GDALRasterPixelInfoAlgorithm();
36+
GDALRasterPixelInfoAlgorithm(bool standaloneStep = false);
3537
~GDALRasterPixelInfoAlgorithm() override;
3638

39+
bool IsNativelyStreamingCompatible() const override
40+
{
41+
// It could potentially be made fully streamable in pipeline mode since
42+
// we read coordinates from an input vector dataset. "Just" needs some
43+
// code reorganization.
44+
return false;
45+
}
46+
47+
int GetInputType() const override
48+
{
49+
return GDAL_OF_RASTER;
50+
}
51+
52+
int GetOutputType() const override
53+
{
54+
return GDAL_OF_VECTOR;
55+
}
56+
3757
private:
58+
bool RunStep(GDALPipelineStepRunContext &ctxt) override;
3859
bool RunImpl(GDALProgressFunc pfnProgress, void *pProgressData) override;
3960

40-
GDALArgDatasetValue m_rasterDataset{};
41-
std::vector<std::string> m_openOptions{};
42-
std::vector<std::string> m_inputFormats{};
43-
4461
GDALArgDatasetValue m_vectorDataset{};
45-
std::string m_inputLayerName{};
4662
std::vector<std::string> m_includeFields{"ALL"};
4763

48-
std::string m_format{};
49-
GDALArgDatasetValue m_outputDataset{};
50-
std::vector<std::string> m_creationOptions{};
51-
std::vector<std::string> m_layerCreationOptions{};
52-
bool m_overwrite = false;
53-
5464
std::string m_outputString{};
65+
5566
std::vector<int> m_band{};
5667
int m_overview = -1;
5768
std::vector<double> m_pos{};
@@ -63,6 +74,22 @@ class GDALRasterPixelInfoAlgorithm final : public GDALAlgorithm
6374
std::string m_osTmpFilename{};
6475
};
6576

77+
/************************************************************************/
78+
/* GDALRasterPixelInfoAlgorithmStandalone */
79+
/************************************************************************/
80+
81+
class GDALRasterPixelInfoAlgorithmStandalone final
82+
: public GDALRasterPixelInfoAlgorithm
83+
{
84+
public:
85+
GDALRasterPixelInfoAlgorithmStandalone()
86+
: GDALRasterPixelInfoAlgorithm(/* standaloneStep = */ true)
87+
{
88+
}
89+
90+
~GDALRasterPixelInfoAlgorithmStandalone() override;
91+
};
92+
6693
//! @endcond
6794

6895
#endif

0 commit comments

Comments
 (0)