/src/gdal/apps/gdalalg_raster_sieve.cpp
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Project: GDAL |
4 | | * Purpose: gdal "raster sieve" subcommand |
5 | | * Author: Alessandro Pasotti <elpaso at itopen dot it> |
6 | | * |
7 | | ****************************************************************************** |
8 | | * Copyright (c) 2025, Alessandro Pasotti <elpaso at itopen dot it> |
9 | | * |
10 | | * SPDX-License-Identifier: MIT |
11 | | ****************************************************************************/ |
12 | | |
13 | | #include "gdalalg_raster_sieve.h" |
14 | | |
15 | | #include "cpl_conv.h" |
16 | | #include "cpl_vsi_virtual.h" |
17 | | |
18 | | #include "gdal_alg.h" |
19 | | #include "gdal_priv.h" |
20 | | #include "gdal_utils.h" |
21 | | #include "commonutils.h" |
22 | | |
23 | | //! @cond Doxygen_Suppress |
24 | | |
25 | | #ifndef _ |
26 | 0 | #define _(x) (x) |
27 | | #endif |
28 | | |
29 | | /************************************************************************/ |
30 | | /* GDALRasterSieveAlgorithm::GDALRasterSieveAlgorithm() */ |
31 | | /************************************************************************/ |
32 | | |
33 | | GDALRasterSieveAlgorithm::GDALRasterSieveAlgorithm(bool standaloneStep) |
34 | 0 | : GDALRasterPipelineNonNativelyStreamingAlgorithm(NAME, DESCRIPTION, |
35 | 0 | HELP_URL, standaloneStep) |
36 | 0 | { |
37 | 0 | auto &mask{ |
38 | 0 | AddArg("mask", 0, |
39 | 0 | _("Use the first band of the specified file as a " |
40 | 0 | "validity mask (all pixels with a value other than zero " |
41 | 0 | "will be considered suitable for inclusion in polygons)"), |
42 | 0 | &m_maskDataset, GDAL_OF_RASTER)}; |
43 | |
|
44 | 0 | SetAutoCompleteFunctionForFilename(mask, GDAL_OF_RASTER); |
45 | |
|
46 | 0 | AddBandArg(&m_band); |
47 | 0 | AddArg("size-threshold", 's', _("Minimum size of polygons to keep"), |
48 | 0 | &m_sizeThreshold) |
49 | 0 | .SetDefault(m_sizeThreshold); |
50 | |
|
51 | 0 | AddArg("connect-diagonal-pixels", 'c', |
52 | 0 | _("Consider diagonal pixels as connected"), &m_connectDiagonalPixels) |
53 | 0 | .SetDefault(m_connectDiagonalPixels); |
54 | 0 | } |
55 | | |
56 | | /************************************************************************/ |
57 | | /* GDALRasterSieveAlgorithm::RunStep() */ |
58 | | /************************************************************************/ |
59 | | |
60 | | bool GDALRasterSieveAlgorithm::RunStep(GDALPipelineStepRunContext &ctxt) |
61 | 0 | { |
62 | 0 | auto pfnProgress = ctxt.m_pfnProgress; |
63 | 0 | auto pProgressData = ctxt.m_pProgressData; |
64 | 0 | auto poSrcDS = m_inputDataset[0].GetDatasetRef(); |
65 | 0 | std::unique_ptr<void, decltype(&GDALDestroyScaledProgress)> pScaledData( |
66 | 0 | GDALCreateScaledProgress(0.0, 0.5, pfnProgress, pProgressData), |
67 | 0 | GDALDestroyScaledProgress); |
68 | 0 | auto poTmpDS = CreateTemporaryCopy( |
69 | 0 | this, poSrcDS, m_band, true, pScaledData ? GDALScaledProgress : nullptr, |
70 | 0 | pScaledData.get()); |
71 | 0 | if (!poTmpDS) |
72 | 0 | return false; |
73 | | |
74 | 0 | GDALRasterBand *maskBand{nullptr}; |
75 | 0 | if (m_maskDataset.GetDatasetRef()) |
76 | 0 | { |
77 | 0 | maskBand = m_maskDataset.GetDatasetRef()->GetRasterBand(1); |
78 | 0 | if (!maskBand) |
79 | 0 | { |
80 | 0 | ReportError(CE_Failure, CPLE_AppDefined, "Cannot get mask band."); |
81 | 0 | return false; |
82 | 0 | } |
83 | 0 | } |
84 | | |
85 | | // Get the output band |
86 | 0 | GDALRasterBand *dstBand = poTmpDS->GetRasterBand(1); |
87 | 0 | CPLAssert(dstBand); |
88 | | |
89 | 0 | pScaledData.reset( |
90 | 0 | GDALCreateScaledProgress(0.5, 1.0, pfnProgress, pProgressData)); |
91 | 0 | const CPLErr err = GDALSieveFilter( |
92 | 0 | dstBand, maskBand, dstBand, m_sizeThreshold, |
93 | 0 | m_connectDiagonalPixels ? 8 : 4, nullptr, |
94 | 0 | pScaledData ? GDALScaledProgress : nullptr, pScaledData.get()); |
95 | 0 | if (err == CE_None) |
96 | 0 | { |
97 | 0 | if (pfnProgress) |
98 | 0 | pfnProgress(1.0, "", pProgressData); |
99 | 0 | m_outputDataset.Set(std::move(poTmpDS)); |
100 | 0 | } |
101 | |
|
102 | 0 | return err == CE_None; |
103 | 0 | } |
104 | | |
105 | 0 | GDALRasterSieveAlgorithmStandalone::~GDALRasterSieveAlgorithmStandalone() = |
106 | | default; |
107 | | |
108 | | //! @endcond |