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