diff --git a/python/plugins/processing/algs/gdal/merge.py b/python/plugins/processing/algs/gdal/merge.py index df8b44d9ad2..ee615bb412d 100644 --- a/python/plugins/processing/algs/gdal/merge.py +++ b/python/plugins/processing/algs/gdal/merge.py @@ -48,6 +48,7 @@ class merge(GdalAlgorithm): PCT = 'PCT' SEPARATE = 'SEPARATE' OPTIONS = 'OPTIONS' + EXTRA = 'EXTRA' DATA_TYPE = 'DATA_TYPE' NODATA_INPUT = 'NODATA_INPUT' NODATA_OUTPUT = 'NODATA_OUTPUT' @@ -95,6 +96,13 @@ class merge(GdalAlgorithm): 'class': 'processing.algs.gdal.ui.RasterOptionsWidget.RasterOptionsWidgetWrapper'}}) self.addParameter(options_param) + extra_param = QgsProcessingParameterString(self.EXTRA, + self.tr('Additional command-line parameters'), + defaultValue=None, + optional=True) + extra_param.setFlags(extra_param.flags() | QgsProcessingParameterDefinition.FlagAdvanced) + self.addParameter(extra_param) + self.addParameter(QgsProcessingParameterEnum(self.DATA_TYPE, self.tr('Output data type'), self.TYPES, @@ -153,6 +161,10 @@ class merge(GdalAlgorithm): if options: arguments.extend(GdalUtils.parseCreationOptions(options)) + if self.EXTRA in parameters and parameters[self.EXTRA] not in (None, ''): + extra = self.parameterAsString(parameters, self.EXTRA, context) + arguments.append(extra) + arguments.append('-o') arguments.append(out) diff --git a/python/plugins/processing/tests/GdalAlgorithmsTest.py b/python/plugins/processing/tests/GdalAlgorithmsTest.py index 82bd09c884d..0685463b77a 100644 --- a/python/plugins/processing/tests/GdalAlgorithmsTest.py +++ b/python/plugins/processing/tests/GdalAlgorithmsTest.py @@ -62,6 +62,7 @@ from processing.algs.gdal.sieve import sieve from processing.algs.gdal.gdal2xyz import gdal2xyz from processing.algs.gdal.polygonize import polygonize from processing.algs.gdal.pansharp import pansharp +from processing.algs.gdal.merge import merge from processing.tools.system import isWindows @@ -2680,6 +2681,61 @@ class TestGdalAlgorithms(unittest.TestCase, AlgorithmsTestBase.AlgorithmsTest): source + ' ' + outdir + '/check.jpg']) + def testMerge(self): + context = QgsProcessingContext() + feedback = QgsProcessingFeedback() + source = [os.path.join(testDataPath, 'dem1.tif'), os.path.join(testDataPath, 'dem1.tif')] + alg = merge() + alg.initAlgorithm() + + with tempfile.TemporaryDirectory() as outdir: + # this algorithm creates temporary text file with input layers + # so we strip its path, leaving only filename + cmd = alg.getConsoleCommands({'INPUT': source, + 'OUTPUT': outdir + '/check.tif'}, context, feedback) + t = cmd[1] + cmd[1] = t[:t.find('--optfile') + 10] + t[t.find('mergeInputFiles.txt'):] + self.assertEqual(cmd, + ['gdal_merge.py', + '-ot Float32 -of GTiff ' + + '-o ' + outdir + '/check.tif ' + + '--optfile mergeInputFiles.txt']) + # separate + cmd = alg.getConsoleCommands({'INPUT': source, + 'SEPARATE': True, + 'OUTPUT': outdir + '/check.tif'}, context, feedback) + t = cmd[1] + cmd[1] = t[:t.find('--optfile') + 10] + t[t.find('mergeInputFiles.txt'):] + self.assertEqual(cmd, + ['gdal_merge.py', + '-separate -ot Float32 -of GTiff ' + + '-o ' + outdir + '/check.tif ' + + '--optfile mergeInputFiles.txt']) + + # assign nodata + cmd = alg.getConsoleCommands({'INPUT': source, + 'EXTRA': '-tap -ps 0.1 0.1', + 'OUTPUT': outdir + '/check.tif'}, context, feedback) + t = cmd[1] + cmd[1] = t[:t.find('--optfile') + 10] + t[t.find('mergeInputFiles.txt'):] + self.assertEqual(cmd, + ['gdal_merge.py', + '-ot Float32 -of GTiff -tap -ps 0.1 0.1 ' + + '-o ' + outdir + '/check.tif ' + + '--optfile mergeInputFiles.txt']) + + # additional parameters + cmd = alg.getConsoleCommands({'INPUT': source, + 'NODATA_OUTPUT': -9999, + 'OUTPUT': outdir + '/check.tif'}, context, feedback) + t = cmd[1] + cmd[1] = t[:t.find('--optfile') + 10] + t[t.find('mergeInputFiles.txt'):] + self.assertEqual(cmd, + ['gdal_merge.py', + '-a_nodata -9999 -ot Float32 -of GTiff ' + + '-o ' + outdir + '/check.tif ' + + '--optfile mergeInputFiles.txt']) + def testRearrangeBands(self): context = QgsProcessingContext() feedback = QgsProcessingFeedback()