fillnodata.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. """
  2. ***************************************************************************
  3. fillnodata.py
  4. ---------------------
  5. Date : August 2012
  6. Copyright : (C) 2012 by Victor Olaya
  7. Email : volayaf at gmail dot com
  8. ***************************************************************************
  9. * *
  10. * This program is free software; you can redistribute it and/or modify *
  11. * it under the terms of the GNU General Public License as published by *
  12. * the Free Software Foundation; either version 2 of the License, or *
  13. * (at your option) any later version. *
  14. * *
  15. ***************************************************************************
  16. """
  17. __author__ = 'Victor Olaya'
  18. __date__ = 'August 2012'
  19. __copyright__ = '(C) 2012, Victor Olaya'
  20. import os
  21. from qgis.core import (QgsProcessingAlgorithm,
  22. QgsRasterFileWriter,
  23. QgsProcessingException,
  24. QgsProcessingParameterDefinition,
  25. QgsProcessingParameterRasterLayer,
  26. QgsProcessingParameterBand,
  27. QgsProcessingParameterNumber,
  28. QgsProcessingParameterBoolean,
  29. QgsProcessingParameterString,
  30. QgsProcessingParameterRasterDestination)
  31. from processing.algs.gdal.GdalAlgorithm import GdalAlgorithm
  32. from processing.tools.system import isWindows
  33. from processing.algs.gdal.GdalUtils import GdalUtils
  34. pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
  35. class fillnodata(GdalAlgorithm):
  36. INPUT = 'INPUT'
  37. BAND = 'BAND'
  38. DISTANCE = 'DISTANCE'
  39. ITERATIONS = 'ITERATIONS'
  40. NO_MASK = 'NO_MASK'
  41. MASK_LAYER = 'MASK_LAYER'
  42. OPTIONS = 'OPTIONS'
  43. EXTRA = 'EXTRA'
  44. OUTPUT = 'OUTPUT'
  45. def __init__(self):
  46. super().__init__()
  47. def initAlgorithm(self, config=None):
  48. self.addParameter(QgsProcessingParameterRasterLayer(self.INPUT, self.tr('Input layer')))
  49. self.addParameter(QgsProcessingParameterBand(self.BAND,
  50. self.tr('Band number'),
  51. 1,
  52. parentLayerParameterName=self.INPUT))
  53. self.addParameter(QgsProcessingParameterNumber(self.DISTANCE,
  54. self.tr('Maximum distance (in pixels) to search out for values to interpolate'),
  55. type=QgsProcessingParameterNumber.Integer,
  56. minValue=0,
  57. defaultValue=10))
  58. self.addParameter(QgsProcessingParameterNumber(self.ITERATIONS,
  59. self.tr('Number of smoothing iterations to run after the interpolation'),
  60. type=QgsProcessingParameterNumber.Integer,
  61. minValue=0,
  62. defaultValue=0))
  63. # The -nomask option is no longer supported since GDAL 3.4 and
  64. # it doesn't work as expected even using GDAL < 3.4 https://github.com/OSGeo/gdal/pull/4201
  65. nomask_param = QgsProcessingParameterBoolean(self.NO_MASK,
  66. self.tr('Do not use the default validity mask for the input band'),
  67. defaultValue=False,
  68. optional=True)
  69. nomask_param.setFlags(nomask_param.flags() | QgsProcessingParameterDefinition.FlagHidden)
  70. self.addParameter(nomask_param)
  71. self.addParameter(QgsProcessingParameterRasterLayer(self.MASK_LAYER,
  72. self.tr('Validity mask'),
  73. optional=True))
  74. options_param = QgsProcessingParameterString(self.OPTIONS,
  75. self.tr('Additional creation options'),
  76. defaultValue='',
  77. optional=True)
  78. options_param.setFlags(options_param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
  79. options_param.setMetadata({
  80. 'widget_wrapper': {
  81. 'class': 'processing.algs.gdal.ui.RasterOptionsWidget.RasterOptionsWidgetWrapper'}})
  82. self.addParameter(options_param)
  83. extra_param = QgsProcessingParameterString(self.EXTRA,
  84. self.tr('Additional command-line parameters'),
  85. defaultValue=None,
  86. optional=True)
  87. extra_param.setFlags(extra_param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
  88. self.addParameter(extra_param)
  89. self.addParameter(QgsProcessingParameterRasterDestination(self.OUTPUT, self.tr('Filled')))
  90. def name(self):
  91. return 'fillnodata'
  92. def displayName(self):
  93. return self.tr('Fill nodata')
  94. def group(self):
  95. return self.tr('Raster analysis')
  96. def groupId(self):
  97. return 'rasteranalysis'
  98. def commandName(self):
  99. return 'gdal_fillnodata'
  100. def flags(self):
  101. return super().flags() | QgsProcessingAlgorithm.FlagDisplayNameIsLiteral
  102. def getConsoleCommands(self, parameters, context, feedback, executing=True):
  103. raster = self.parameterAsRasterLayer(parameters, self.INPUT, context)
  104. if raster is None:
  105. raise QgsProcessingException(self.invalidRasterError(parameters, self.INPUT))
  106. out = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
  107. self.setOutputValue(self.OUTPUT, out)
  108. arguments = [
  109. raster.source(),
  110. out,
  111. '-md',
  112. str(self.parameterAsInt(parameters, self.DISTANCE, context)),
  113. ]
  114. nIterations = self.parameterAsInt(parameters, self.ITERATIONS, context)
  115. if nIterations:
  116. arguments.append('-si')
  117. arguments.append(str(nIterations))
  118. arguments.append('-b')
  119. arguments.append(str(self.parameterAsInt(parameters, self.BAND, context)))
  120. mask = self.parameterAsRasterLayer(parameters, self.MASK_LAYER, context)
  121. if mask:
  122. arguments.append('-mask')
  123. arguments.append(mask.source())
  124. output_format = QgsRasterFileWriter.driverForExtension(os.path.splitext(out)[1])
  125. if not output_format:
  126. raise QgsProcessingException(self.tr('Output format is invalid'))
  127. arguments.append('-of')
  128. arguments.append(output_format)
  129. if self.EXTRA in parameters and parameters[self.EXTRA] not in (None, ''):
  130. extra = self.parameterAsString(parameters, self.EXTRA, context)
  131. arguments.append(extra)
  132. # Until https://github.com/OSGeo/gdal/issues/7651 is fixed, creation options should be latest argument
  133. options = self.parameterAsString(parameters, self.OPTIONS, context)
  134. if options:
  135. arguments.extend(GdalUtils.parseCreationOptions(options))
  136. return [self.commandName() + ('.bat' if isWindows() else '.py'), GdalUtils.escapeAndJoin(arguments)]