Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL
4 : * Purpose: "reproject" step of "raster pipeline"
5 : * Author: Even Rouault <even dot rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "gdalalg_raster_reproject.h"
14 :
15 : #include "gdal_priv.h"
16 : #include "gdal_utils.h"
17 :
18 : //! @cond Doxygen_Suppress
19 :
20 : #ifndef _
21 : #define _(x) (x)
22 : #endif
23 :
24 : /************************************************************************/
25 : /* GDALRasterReprojectAlgorithm::GDALRasterReprojectAlgorithm() */
26 : /************************************************************************/
27 :
28 26 : GDALRasterReprojectAlgorithm::GDALRasterReprojectAlgorithm(bool standaloneStep)
29 : : GDALRasterPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL,
30 26 : standaloneStep)
31 : {
32 52 : AddArg("src-crs", 's', _("Source CRS"), &m_srsCrs)
33 26 : .SetIsCRSArg()
34 26 : .AddHiddenAlias("s_srs");
35 52 : AddArg("dst-crs", 'd', _("Destination CRS"), &m_dstCrs)
36 26 : .SetIsCRSArg()
37 26 : .AddHiddenAlias("t_srs");
38 52 : AddArg("resampling", 'r', _("Resampling method"), &m_resampling)
39 : .SetChoices("nearest", "bilinear", "cubic", "cubicspline", "lanczos",
40 : "average", "rms", "mode", "min", "max", "med", "q1", "q3",
41 26 : "sum")
42 26 : .SetHiddenChoices("near");
43 :
44 : auto &resArg =
45 : AddArg("resolution", 0,
46 52 : _("Target resolution (in destination CRS units)"), &m_resolution)
47 26 : .SetMinCount(2)
48 26 : .SetMaxCount(2)
49 26 : .SetRepeatedArgAllowed(false)
50 26 : .SetDisplayHintAboutRepetition(false)
51 26 : .SetMetaVar("<xres>,<yres>");
52 : resArg.AddValidationAction(
53 2 : [&resArg]()
54 : {
55 2 : const auto &val = resArg.Get<std::vector<double>>();
56 2 : CPLAssert(val.size() == 2);
57 2 : if (!(val[0] >= 0 && val[1] >= 0))
58 : {
59 1 : CPLError(CE_Failure, CPLE_AppDefined,
60 : "Target resolution should be strictly positive.");
61 1 : return false;
62 : }
63 1 : return true;
64 26 : });
65 :
66 26 : AddBBOXArg(&m_bbox, _("Target bounding box (in destination CRS units)"));
67 :
68 : AddArg("target-aligned-pixels", 0,
69 : _("Round target extent to target resolution"),
70 52 : &m_targetAlignedPixels)
71 26 : .AddHiddenAlias("tap");
72 26 : }
73 :
74 : /************************************************************************/
75 : /* GDALRasterReprojectAlgorithm::RunStep() */
76 : /************************************************************************/
77 :
78 5 : bool GDALRasterReprojectAlgorithm::RunStep(GDALProgressFunc, void *)
79 : {
80 5 : CPLAssert(m_inputDataset.GetDatasetRef());
81 5 : CPLAssert(m_outputDataset.GetName().empty());
82 5 : CPLAssert(!m_outputDataset.GetDatasetRef());
83 :
84 10 : CPLStringList aosOptions;
85 5 : aosOptions.AddString("-of");
86 5 : aosOptions.AddString("VRT");
87 5 : if (!m_srsCrs.empty())
88 : {
89 4 : aosOptions.AddString("-s_srs");
90 4 : aosOptions.AddString(m_srsCrs.c_str());
91 : }
92 5 : if (!m_dstCrs.empty())
93 : {
94 4 : aosOptions.AddString("-t_srs");
95 4 : aosOptions.AddString(m_dstCrs.c_str());
96 : }
97 5 : if (!m_resampling.empty())
98 : {
99 1 : aosOptions.AddString("-r");
100 1 : aosOptions.AddString(m_resampling.c_str());
101 : }
102 5 : if (!m_resolution.empty())
103 : {
104 1 : aosOptions.AddString("-tr");
105 1 : aosOptions.AddString(CPLSPrintf("%.17g", m_resolution[0]));
106 1 : aosOptions.AddString(CPLSPrintf("%.17g", m_resolution[1]));
107 : }
108 5 : if (!m_bbox.empty())
109 : {
110 1 : aosOptions.AddString("-te");
111 1 : aosOptions.AddString(CPLSPrintf("%.17g", m_bbox[0]));
112 1 : aosOptions.AddString(CPLSPrintf("%.17g", m_bbox[1]));
113 1 : aosOptions.AddString(CPLSPrintf("%.17g", m_bbox[2]));
114 1 : aosOptions.AddString(CPLSPrintf("%.17g", m_bbox[3]));
115 : }
116 5 : if (m_targetAlignedPixels)
117 : {
118 1 : aosOptions.AddString("-tap");
119 : }
120 : GDALWarpAppOptions *psOptions =
121 5 : GDALWarpAppOptionsNew(aosOptions.List(), nullptr);
122 :
123 5 : GDALDatasetH hSrcDS = GDALDataset::ToHandle(m_inputDataset.GetDatasetRef());
124 5 : auto poRetDS = GDALDataset::FromHandle(
125 : GDALWarp("", nullptr, 1, &hSrcDS, psOptions, nullptr));
126 5 : GDALWarpAppOptionsFree(psOptions);
127 5 : if (!poRetDS)
128 1 : return false;
129 :
130 4 : m_outputDataset.Set(std::unique_ptr<GDALDataset>(poRetDS));
131 :
132 4 : return true;
133 : }
134 :
135 : //! @endcond
|