Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GDAL 4 : * Purpose: "nodata-to-alpha" 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_nodata_to_alpha.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 : /* GDALRasterNoDataToAlphaAlgorithm::GDALRasterNoDataToAlphaAlgorithm() */ 26 : /************************************************************************/ 27 : 28 27 : GDALRasterNoDataToAlphaAlgorithm::GDALRasterNoDataToAlphaAlgorithm( 29 27 : bool standaloneStep) 30 : : GDALRasterPipelineStepAlgorithm(NAME, DESCRIPTION, HELP_URL, 31 27 : standaloneStep) 32 : { 33 : AddArg("nodata", 0, 34 : _("Override nodata value of input band(s) " 35 : "(numeric value, 'nan', 'inf', '-inf')"), 36 27 : &m_nodata); 37 27 : } 38 : 39 : /************************************************************************/ 40 : /* GDALRasterNoDataToAlphaAlgorithm::RunStep() */ 41 : /************************************************************************/ 42 : 43 5 : bool GDALRasterNoDataToAlphaAlgorithm::RunStep(GDALPipelineStepRunContext &) 44 : { 45 5 : GDALDataset *poSrcDS = m_inputDataset[0].GetDatasetRef(); 46 5 : CPLAssert(poSrcDS); 47 5 : CPLAssert(m_outputDataset.GetName().empty()); 48 5 : CPLAssert(!m_outputDataset.GetDatasetRef()); 49 : 50 5 : if (!m_nodata.empty()) 51 : { 52 3 : CPLStringList aosOptions; 53 3 : aosOptions.AddString("-of"); 54 3 : aosOptions.AddString("VRT"); 55 : 56 3 : if (m_nodata.size() == 1) 57 : { 58 1 : aosOptions.AddString("-a_nodata"); 59 1 : aosOptions.AddString(CPLSPrintf("%.17g", m_nodata[0])); 60 : } 61 : else 62 : { 63 2 : if (m_nodata.size() != 64 2 : static_cast<size_t>(poSrcDS->GetRasterCount())) 65 : { 66 1 : ReportError(CE_Failure, CPLE_IllegalArg, 67 : "There should be %d nodata values given the input " 68 : "dataset has %d bands", 69 : poSrcDS->GetRasterCount(), 70 : poSrcDS->GetRasterCount()); 71 1 : return false; 72 : } 73 1 : aosOptions.AddString("-mo"); 74 2 : std::string nodataValues("NODATA_VALUES="); 75 4 : for (size_t i = 0; i < m_nodata.size(); ++i) 76 : { 77 3 : if (i > 0) 78 2 : nodataValues += ' '; 79 3 : nodataValues += CPLSPrintf("%.17g", m_nodata[i]); 80 : } 81 1 : aosOptions.AddString(nodataValues.c_str()); 82 : } 83 : 84 : GDALTranslateOptions *psOptions = 85 2 : GDALTranslateOptionsNew(aosOptions.List(), nullptr); 86 2 : if (psOptions) 87 : { 88 2 : m_tempDS.reset(GDALDataset::FromHandle(GDALTranslate( 89 : "", GDALDataset::ToHandle(poSrcDS), psOptions, nullptr))); 90 2 : GDALTranslateOptionsFree(psOptions); 91 : } 92 2 : poSrcDS = m_tempDS.get(); 93 : } 94 : 95 4 : bool bRet = poSrcDS != nullptr; 96 4 : if (poSrcDS) 97 : { 98 8 : CPLStringList aosOptions; 99 4 : aosOptions.AddString("-of"); 100 4 : aosOptions.AddString("VRT"); 101 : 102 4 : if (poSrcDS->GetRasterCount() > 0 && 103 7 : poSrcDS->GetRasterBand(1)->GetMaskFlags() != GMF_ALL_VALID && 104 3 : poSrcDS->GetRasterBand(1)->GetMaskFlags() != 105 : (GMF_ALPHA | GMF_PER_DATASET)) 106 : { 107 3 : aosOptions.AddString("-a_nodata"); 108 3 : aosOptions.AddString("none"); 109 : 110 8 : for (int i = 1; i <= poSrcDS->GetRasterCount(); ++i) 111 : { 112 5 : aosOptions.AddString("-b"); 113 5 : aosOptions.AddString(CPLSPrintf("%d", i)); 114 : } 115 3 : aosOptions.AddString("-b"); 116 3 : aosOptions.AddString("mask"); 117 : 118 : aosOptions.AddString( 119 3 : CPLSPrintf("-colorinterp_%d", poSrcDS->GetRasterCount() + 1)); 120 3 : aosOptions.AddString("alpha"); 121 : } 122 : 123 4 : std::unique_ptr<GDALDataset> poOutDS; 124 : GDALTranslateOptions *psOptions = 125 4 : GDALTranslateOptionsNew(aosOptions.List(), nullptr); 126 4 : if (psOptions) 127 : { 128 4 : poOutDS.reset(GDALDataset::FromHandle(GDALTranslate( 129 : "", GDALDataset::ToHandle(poSrcDS), psOptions, nullptr))); 130 4 : GDALTranslateOptionsFree(psOptions); 131 : 132 4 : poOutDS->GetRasterBand(1)->GetMaskFlags(); 133 : } 134 4 : bRet = poOutDS != nullptr; 135 4 : if (poOutDS) 136 : { 137 4 : m_outputDataset.Set(std::move(poOutDS)); 138 : } 139 : } 140 : 141 4 : return bRet; 142 : } 143 : 144 : GDALRasterNoDataToAlphaAlgorithmStandalone:: 145 : ~GDALRasterNoDataToAlphaAlgorithmStandalone() = default; 146 : 147 : //! @endcond