Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GDAL 4 : * Purpose: "select" 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_select.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 : /* GDALRasterSelectAlgorithm::GDALRasterSelectAlgorithm() */ 26 : /************************************************************************/ 27 : 28 12 : GDALRasterSelectAlgorithm::GDALRasterSelectAlgorithm(bool standaloneStep) 29 : : GDALRasterPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL, 30 12 : standaloneStep) 31 : { 32 : { 33 : auto &arg = 34 : AddArg("band", 'b', 35 : _("Band(s) (1-based index, 'mask' or 'mask:<band>')"), 36 24 : &m_bands) 37 12 : .SetPositional() 38 12 : .SetRequired() 39 12 : .SetMinCount(1); 40 : arg.AddValidationAction( 41 3 : [&arg]() 42 : { 43 3 : const auto &val = arg.Get<std::vector<std::string>>(); 44 8 : for (const auto &v : val) 45 : { 46 11 : if (!STARTS_WITH(v.c_str(), "mask") && 47 5 : !(CPLGetValueType(v.c_str()) == CPL_VALUE_INTEGER && 48 4 : atoi(v.c_str()) >= 1)) 49 : { 50 1 : CPLError(CE_Failure, CPLE_AppDefined, 51 : "Invalid band specification."); 52 1 : return false; 53 : } 54 : } 55 2 : return true; 56 12 : }); 57 : } 58 : { 59 : auto &arg = AddArg( 60 : "mask", 0, 61 : _("Mask band (1-based index, 'mask', 'mask:<band>' or 'none')"), 62 12 : &m_mask); 63 : arg.AddValidationAction( 64 2 : [&arg]() 65 : { 66 2 : const auto &v = arg.Get<std::string>(); 67 2 : if (!STARTS_WITH(v.c_str(), "mask") && 68 4 : !EQUAL(v.c_str(), "none") && 69 2 : !(CPLGetValueType(v.c_str()) == CPL_VALUE_INTEGER && 70 1 : atoi(v.c_str()) >= 1)) 71 : { 72 1 : CPLError(CE_Failure, CPLE_AppDefined, 73 : "Invalid mask band specification."); 74 1 : return false; 75 : } 76 1 : return true; 77 12 : }); 78 : } 79 12 : } 80 : 81 : /************************************************************************/ 82 : /* GDALRasterSelectAlgorithm::RunStep() */ 83 : /************************************************************************/ 84 : 85 2 : bool GDALRasterSelectAlgorithm::RunStep(GDALProgressFunc, void *) 86 : { 87 2 : CPLAssert(m_inputDataset.GetDatasetRef()); 88 2 : CPLAssert(m_outputDataset.GetName().empty()); 89 2 : CPLAssert(!m_outputDataset.GetDatasetRef()); 90 : 91 4 : CPLStringList aosOptions; 92 2 : aosOptions.AddString("-of"); 93 2 : aosOptions.AddString("VRT"); 94 7 : for (const std::string &v : m_bands) 95 : { 96 5 : aosOptions.AddString("-b"); 97 5 : aosOptions.AddString(CPLString(v).replaceAll(':', ',').c_str()); 98 : } 99 2 : if (!m_mask.empty()) 100 : { 101 1 : aosOptions.AddString("-mask"); 102 1 : aosOptions.AddString(CPLString(m_mask).replaceAll(':', ',').c_str()); 103 : } 104 : 105 : GDALTranslateOptions *psOptions = 106 2 : GDALTranslateOptionsNew(aosOptions.List(), nullptr); 107 : 108 : auto poOutDS = std::unique_ptr<GDALDataset>(GDALDataset::FromHandle( 109 : GDALTranslate("", GDALDataset::ToHandle(m_inputDataset.GetDatasetRef()), 110 2 : psOptions, nullptr))); 111 2 : GDALTranslateOptionsFree(psOptions); 112 2 : const bool bRet = poOutDS != nullptr; 113 2 : if (poOutDS) 114 : { 115 2 : m_outputDataset.Set(std::move(poOutDS)); 116 : } 117 : 118 4 : return bRet; 119 : } 120 : 121 : //! @endcond