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