Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GDAL 4 : * Purpose: "resize" step of "raster pipeline" 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_resize.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 : /* GDALRasterResizeAlgorithm::GDALRasterResizeAlgorithm() */ 26 : /************************************************************************/ 27 : 28 42 : GDALRasterResizeAlgorithm::GDALRasterResizeAlgorithm(bool standaloneStep) 29 : : GDALRasterPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL, 30 42 : standaloneStep) 31 : { 32 : AddArg("resolution", 0, _("Target resolution (in destination CRS units)"), 33 84 : &m_resolution) 34 42 : .SetMinCount(2) 35 42 : .SetMaxCount(2) 36 42 : .SetMinValueExcluded(0) 37 42 : .SetRepeatedArgAllowed(false) 38 42 : .SetDisplayHintAboutRepetition(false) 39 84 : .SetMetaVar("<xres>,<yres>") 40 42 : .SetMutualExclusionGroup("resolution-size"); 41 : 42 : AddArg("size", 0, 43 : _("Target size in pixels (or percentage if using '%' suffix)"), 44 84 : &m_size) 45 42 : .SetMinCount(2) 46 42 : .SetMaxCount(2) 47 42 : .SetRequired() 48 42 : .SetMinValueIncluded(0) 49 42 : .SetRepeatedArgAllowed(false) 50 42 : .SetDisplayHintAboutRepetition(false) 51 84 : .SetMetaVar("<width[%]>,<height[%]>") 52 84 : .SetMutualExclusionGroup("resolution-size") 53 : .AddValidationAction( 54 19 : [this]() 55 : { 56 32 : for (const auto &s : m_size) 57 : { 58 23 : char *endptr = nullptr; 59 23 : const double val = CPLStrtod(s.c_str(), &endptr); 60 23 : bool ok = false; 61 23 : if (endptr == s.c_str() + s.size()) 62 : { 63 15 : if (val >= 0 && val <= INT_MAX && 64 13 : static_cast<int>(val) == val) 65 : { 66 12 : ok = true; 67 : } 68 : } 69 16 : else if (endptr && ((endptr[0] == ' ' && endptr[1] == '%' && 70 3 : endptr + 2 == s.c_str() + s.size()) || 71 5 : (endptr[0] == '%' && 72 11 : endptr + 1 == s.c_str() + s.size()))) 73 : { 74 6 : if (val >= 0) 75 : { 76 6 : ok = true; 77 : } 78 : } 79 23 : if (!ok) 80 : { 81 5 : ReportError(CE_Failure, CPLE_IllegalArg, 82 : "Invalid size value: %s'", s.c_str()); 83 5 : return false; 84 : } 85 : } 86 9 : return true; 87 42 : }); 88 84 : AddArg("resampling", 'r', _("Resampling method"), &m_resampling) 89 : .SetChoices("nearest", "bilinear", "cubic", "cubicspline", "lanczos", 90 42 : "average", "mode") 91 42 : .SetDefault("nearest") 92 42 : .SetHiddenChoices("near"); 93 42 : } 94 : 95 : /************************************************************************/ 96 : /* GDALRasterResizeAlgorithm::RunStep() */ 97 : /************************************************************************/ 98 : 99 4 : bool GDALRasterResizeAlgorithm::RunStep(GDALPipelineStepRunContext &) 100 : { 101 4 : const auto poSrcDS = m_inputDataset[0].GetDatasetRef(); 102 4 : CPLAssert(poSrcDS); 103 4 : CPLAssert(m_outputDataset.GetName().empty()); 104 4 : CPLAssert(!m_outputDataset.GetDatasetRef()); 105 : 106 8 : CPLStringList aosOptions; 107 4 : aosOptions.AddString("-of"); 108 4 : aosOptions.AddString("VRT"); 109 4 : if (!m_size.empty()) 110 : { 111 3 : aosOptions.AddString("-outsize"); 112 3 : aosOptions.AddString(m_size[0]); 113 3 : aosOptions.AddString(m_size[1]); 114 : } 115 4 : if (!m_resolution.empty()) 116 : { 117 1 : aosOptions.AddString("-tr"); 118 1 : aosOptions.AddString(CPLSPrintf("%.17g", m_resolution[0])); 119 1 : aosOptions.AddString(CPLSPrintf("%.17g", m_resolution[1])); 120 : } 121 4 : if (!m_resampling.empty()) 122 : { 123 4 : aosOptions.AddString("-r"); 124 4 : aosOptions.AddString(m_resampling.c_str()); 125 : } 126 : 127 : GDALTranslateOptions *psOptions = 128 4 : GDALTranslateOptionsNew(aosOptions.List(), nullptr); 129 : 130 : auto poOutDS = std::unique_ptr<GDALDataset>(GDALDataset::FromHandle( 131 4 : GDALTranslate("", GDALDataset::ToHandle(poSrcDS), psOptions, nullptr))); 132 4 : GDALTranslateOptionsFree(psOptions); 133 4 : const bool bRet = poOutDS != nullptr; 134 4 : if (poOutDS) 135 : { 136 4 : m_outputDataset.Set(std::move(poOutDS)); 137 : } 138 : 139 8 : return bRet; 140 : } 141 : 142 : GDALRasterResizeAlgorithmStandalone::~GDALRasterResizeAlgorithmStandalone() = 143 : default; 144 : 145 : //! @endcond