diff --git a/python/plugins/processing/algs/gdal/buildvrt.py b/python/plugins/processing/algs/gdal/buildvrt.py index 893df01dfe3..26c2fd26cda 100644 --- a/python/plugins/processing/algs/gdal/buildvrt.py +++ b/python/plugins/processing/algs/gdal/buildvrt.py @@ -55,6 +55,7 @@ class buildvrt(GdalAlgorithm): ASSIGN_CRS = 'ASSIGN_CRS' RESAMPLING = 'RESAMPLING' SRC_NODATA = 'SRC_NODATA' + EXTRA = 'EXTRA' def __init__(self): super().__init__() @@ -131,6 +132,13 @@ class buildvrt(GdalAlgorithm): src_nodata_param.setFlags(src_nodata_param.flags() | QgsProcessingParameterDefinition.FlagAdvanced) self.addParameter(src_nodata_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(ParameterVrtDestination(self.OUTPUT, QCoreApplication.translate("ParameterVrtDestination", 'Virtual'))) def name(self): @@ -172,6 +180,10 @@ class buildvrt(GdalAlgorithm): nodata = self.parameterAsString(parameters, self.SRC_NODATA, context) arguments.append('-srcnodata "{}"'.format(nodata)) + if self.EXTRA in parameters and parameters[self.EXTRA] not in (None, ''): + extra = self.parameterAsString(parameters, self.EXTRA, context) + arguments.append(extra) + # Always write input files to a text file in case there are many of them and the # length of the command will be longer then allowed in command prompt list_file = GdalUtils.writeLayerParameterToTextFile(filename='buildvrtInputFiles.txt', alg=self, parameters=parameters, parameter_name=self.INPUT, context=context, executing=executing, quote=False) diff --git a/python/plugins/processing/tests/GdalAlgorithmsTest.py b/python/plugins/processing/tests/GdalAlgorithmsTest.py index 4e51fc8cb06..4a6a5963b3a 100644 --- a/python/plugins/processing/tests/GdalAlgorithmsTest.py +++ b/python/plugins/processing/tests/GdalAlgorithmsTest.py @@ -1084,162 +1084,127 @@ class TestGdalAlgorithms(unittest.TestCase, AlgorithmsTestBase.AlgorithmsTest): alg.initAlgorithm() with tempfile.TemporaryDirectory() as outdir: - commands = alg.getConsoleCommands({'LAYERS': [source], - 'OUTPUT': outdir + '/test.vrt'}, context, feedback) - self.assertEqual(len(commands), 2) - self.assertEqual(commands[0], 'gdalbuildvrt') - self.assertIn('-resolution average', commands[1]) - self.assertIn('-separate', commands[1]) - self.assertNotIn('-allow_projection_difference', commands[1]) - self.assertNotIn('-add_alpha', commands[1]) - self.assertNotIn('-a_srs', commands[1]) - self.assertIn('-r nearest', commands[1]) - self.assertIn('-input_file_list', commands[1]) - self.assertIn(outdir + '/test.vrt', commands[1]) - - commands = alg.getConsoleCommands({'LAYERS': [source], - 'RESOLUTION': 2, - 'OUTPUT': outdir + '/test.vrt'}, context, feedback) - self.assertEqual(len(commands), 2) - self.assertEqual(commands[0], 'gdalbuildvrt') - self.assertIn('-resolution lowest', commands[1]) - self.assertIn('-separate', commands[1]) - self.assertNotIn('-allow_projection_difference', commands[1]) - self.assertNotIn('-add_alpha', commands[1]) - self.assertNotIn('-a_srs', commands[1]) - self.assertIn('-r nearest', commands[1]) - self.assertIn('-input_file_list', commands[1]) - self.assertIn(outdir + '/test.vrt', commands[1]) - - commands = alg.getConsoleCommands({'LAYERS': [source], - 'SEPARATE': False, - 'OUTPUT': outdir + '/test.vrt'}, context, feedback) - self.assertEqual(len(commands), 2) - self.assertEqual(commands[0], 'gdalbuildvrt') - self.assertIn('-resolution average', commands[1]) - self.assertNotIn('-allow_projection_difference', commands[1]) - self.assertNotIn('-separate', commands[1]) - self.assertNotIn('-add_alpha', commands[1]) - self.assertNotIn('-a_srs', commands[1]) - self.assertIn('-r nearest', commands[1]) - self.assertIn('-input_file_list', commands[1]) - self.assertIn(outdir + '/test.vrt', commands[1]) - - commands = alg.getConsoleCommands({'LAYERS': [source], - 'PROJ_DIFFERENCE': True, - 'OUTPUT': outdir + '/test.vrt'}, context, feedback) - self.assertEqual(len(commands), 2) - self.assertEqual(commands[0], 'gdalbuildvrt') - self.assertIn('-resolution average', commands[1]) - self.assertIn('-allow_projection_difference', commands[1]) - self.assertIn('-separate', commands[1]) - self.assertNotIn('-add_alpha', commands[1]) - self.assertNotIn('-a_srs', commands[1]) - self.assertIn('-r nearest', commands[1]) - self.assertIn('-input_file_list', commands[1]) - self.assertIn(outdir + '/test.vrt', commands[1]) - - commands = alg.getConsoleCommands({'LAYERS': [source], - 'ADD_ALPHA': True, - 'OUTPUT': outdir + '/test.vrt'}, context, feedback) - self.assertEqual(len(commands), 2) - self.assertEqual(commands[0], 'gdalbuildvrt') - self.assertIn('-resolution average', commands[1]) - self.assertIn('-separate', commands[1]) - self.assertNotIn('-allow_projection_difference', commands[1]) - self.assertNotIn('-add_alpha', commands[1]) - self.assertNotIn('-a_srs', commands[1]) - self.assertIn('-r nearest', commands[1]) - self.assertIn('-input_file_list', commands[1]) - self.assertIn(outdir + '/test.vrt', commands[1]) - - commands = alg.getConsoleCommands({'LAYERS': [source], - 'ASSIGN_CRS': 'EPSG:3111', - 'OUTPUT': outdir + '/test.vrt'}, context, feedback) - self.assertEqual(len(commands), 2) - self.assertEqual(commands[0], 'gdalbuildvrt') - self.assertIn('-resolution average', commands[1]) - self.assertIn('-separate', commands[1]) - self.assertNotIn('-allow_projection_difference', commands[1]) - self.assertNotIn('-add_alpha', commands[1]) - self.assertIn('-a_srs EPSG:3111', commands[1]) - self.assertIn('-r nearest', commands[1]) - self.assertIn('-input_file_list', commands[1]) - self.assertIn(outdir + '/test.vrt', commands[1]) + # defaults + cmd = alg.getConsoleCommands({'INPUT': [source], + 'OUTPUT': outdir + '/check.vrt'}, context, feedback) + t = cmd[1] + cmd[1] = t[:t.find('-input_file_list') + 17] + t[t.find('buildvrtInputFiles.txt'):] + self.assertEqual(cmd, + ['gdalbuildvrt', + '-resolution average -separate -r nearest ' + + '-input_file_list buildvrtInputFiles.txt ' + + outdir + '/check.vrt']) + # custom resolution + cmd = alg.getConsoleCommands({'INPUT': [source], + 'RESOLUTION': 2, + 'OUTPUT': outdir + '/check.vrt'}, context, feedback) + t = cmd[1] + cmd[1] = t[:t.find('-input_file_list') + 17] + t[t.find('buildvrtInputFiles.txt'):] + self.assertEqual(cmd, + ['gdalbuildvrt', + '-resolution lowest -separate -r nearest ' + + '-input_file_list buildvrtInputFiles.txt ' + + outdir + '/check.vrt']) + # single layer + cmd = alg.getConsoleCommands({'INPUT': [source], + 'SEPARATE': False, + 'OUTPUT': outdir + '/check.vrt'}, context, feedback) + t = cmd[1] + cmd[1] = t[:t.find('-input_file_list') + 17] + t[t.find('buildvrtInputFiles.txt'):] + self.assertEqual(cmd, + ['gdalbuildvrt', + '-resolution average -r nearest ' + + '-input_file_list buildvrtInputFiles.txt ' + + outdir + '/check.vrt']) + # projection difference + cmd = alg.getConsoleCommands({'INPUT': [source], + 'PROJ_DIFFERENCE': True, + 'OUTPUT': outdir + '/check.vrt'}, context, feedback) + t = cmd[1] + cmd[1] = t[:t.find('-input_file_list') + 17] + t[t.find('buildvrtInputFiles.txt'):] + self.assertEqual(cmd, + ['gdalbuildvrt', + '-resolution average -separate -allow_projection_difference -r nearest ' + + '-input_file_list buildvrtInputFiles.txt ' + + outdir + '/check.vrt']) + # add alpha band + cmd = alg.getConsoleCommands({'INPUT': [source], + 'ADD_ALPHA': True, + 'OUTPUT': outdir + '/check.vrt'}, context, feedback) + t = cmd[1] + cmd[1] = t[:t.find('-input_file_list') + 17] + t[t.find('buildvrtInputFiles.txt'):] + self.assertEqual(cmd, + ['gdalbuildvrt', + '-resolution average -separate -addalpha -r nearest ' + + '-input_file_list buildvrtInputFiles.txt ' + + outdir + '/check.vrt']) + # assign CRS + cmd = alg.getConsoleCommands({'INPUT': [source], + 'ASSIGN_CRS': 'EPSG:3111', + 'OUTPUT': outdir + '/check.vrt'}, context, feedback) + t = cmd[1] + cmd[1] = t[:t.find('-input_file_list') + 17] + t[t.find('buildvrtInputFiles.txt'):] + self.assertEqual(cmd, + ['gdalbuildvrt', + '-resolution average -separate -a_srs EPSG:3111 -r nearest ' + + '-input_file_list buildvrtInputFiles.txt ' + + outdir + '/check.vrt']) custom_crs = 'proj4: +proj=utm +zone=36 +south +a=6378249.145 +b=6356514.966398753 +towgs84=-143,-90,-294,0,0,0,0 +units=m +no_defs' - commands = alg.getConsoleCommands({'LAYERS': [source], - 'ASSIGN_CRS': custom_crs, - 'OUTPUT': outdir + '/test.vrt'}, context, feedback) - self.assertEqual(len(commands), 2) - self.assertEqual(commands[0], 'gdalbuildvrt') - self.assertIn('-resolution average', commands[1]) - self.assertIn('-separate', commands[1]) - self.assertNotIn('-allow_projection_difference', commands[1]) - self.assertNotIn('-add_alpha', commands[1]) - self.assertIn('-a_srs EPSG:20936', commands[1]) - self.assertIn('-r nearest', commands[1]) - self.assertIn('-input_file_list', commands[1]) - self.assertIn(outdir + '/test.vrt', commands[1]) + cmd = alg.getConsoleCommands({'INPUT': [source], + 'ASSIGN_CRS': custom_crs, + 'OUTPUT': outdir + '/check.vrt'}, context, feedback) + t = cmd[1] + cmd[1] = t[:t.find('-input_file_list') + 17] + t[t.find('buildvrtInputFiles.txt'):] + self.assertEqual(cmd, + ['gdalbuildvrt', + '-resolution average -separate -a_srs EPSG:20936 -r nearest ' + + '-input_file_list buildvrtInputFiles.txt ' + + outdir + '/check.vrt']) + # source NODATA + cmd = alg.getConsoleCommands({'INPUT': [source], + 'SRC_NODATA': '-9999', + 'OUTPUT': outdir + '/check.vrt'}, context, feedback) + t = cmd[1] + cmd[1] = t[:t.find('-input_file_list') + 17] + t[t.find('buildvrtInputFiles.txt'):] + self.assertEqual(cmd, + ['gdalbuildvrt', + '-resolution average -separate -r nearest -srcnodata "-9999" ' + + '-input_file_list buildvrtInputFiles.txt ' + + outdir + '/check.vrt']) - commands = alg.getConsoleCommands({'LAYERS': [source], - 'RESAMPLING': 4, - 'OUTPUT': outdir + '/test.vrt'}, context, feedback) - self.assertEqual(len(commands), 2) - self.assertEqual(commands[0], 'gdalbuildvrt') - self.assertIn('-resolution average', commands[1]) - self.assertIn('-separate', commands[1]) - self.assertNotIn('-allow_projection_difference', commands[1]) - self.assertNotIn('-add_alpha', commands[1]) - self.assertNotIn('-a_srs', commands[1]) - self.assertIn('-r lanczos', commands[1]) - self.assertIn('-input_file_list', commands[1]) - self.assertIn(outdir + '/test.vrt', commands[1]) + cmd = alg.getConsoleCommands({'INPUT': [source], + 'SRC_NODATA': '-9999 9999', + 'OUTPUT': outdir + '/check.vrt'}, context, feedback) + t = cmd[1] + cmd[1] = t[:t.find('-input_file_list') + 17] + t[t.find('buildvrtInputFiles.txt'):] + self.assertEqual(cmd, + ['gdalbuildvrt', + '-resolution average -separate -r nearest -srcnodata "-9999 9999" ' + + '-input_file_list buildvrtInputFiles.txt ' + + outdir + '/check.vrt']) - commands = alg.getConsoleCommands({'LAYERS': [source], - 'SRC_NODATA': '-9999', - 'OUTPUT': outdir + '/test.vrt'}, context, feedback) - self.assertEqual(len(commands), 2) - self.assertEqual(commands[0], 'gdalbuildvrt') - self.assertIn('-resolution average', commands[1]) - self.assertIn('-separate', commands[1]) - self.assertNotIn('-allow_projection_difference', commands[1]) - self.assertNotIn('-add_alpha', commands[1]) - self.assertNotIn('-a_srs', commands[1]) - self.assertIn('-r nearest', commands[1]) - self.assertIn('-srcnodata "-9999"', commands[1]) - self.assertIn('-input_file_list', commands[1]) - self.assertIn(outdir + '/test.vrt', commands[1]) - - commands = alg.getConsoleCommands({'LAYERS': [source], - 'SRC_NODATA': '-9999 9999', - 'OUTPUT': outdir + '/test.vrt'}, context, feedback) - self.assertEqual(len(commands), 2) - self.assertEqual(commands[0], 'gdalbuildvrt') - self.assertIn('-resolution average', commands[1]) - self.assertIn('-separate', commands[1]) - self.assertNotIn('-allow_projection_difference', commands[1]) - self.assertNotIn('-add_alpha', commands[1]) - self.assertNotIn('-a_srs', commands[1]) - self.assertIn('-r nearest', commands[1]) - self.assertIn('-srcnodata "-9999 9999"', commands[1]) - self.assertIn('-input_file_list', commands[1]) - self.assertIn(outdir + '/test.vrt', commands[1]) - - commands = alg.getConsoleCommands({'LAYERS': [source], - 'SRC_NODATA': '', - 'OUTPUT': outdir + '/test.vrt'}, context, feedback) - self.assertEqual(len(commands), 2) - self.assertEqual(commands[0], 'gdalbuildvrt') - self.assertIn('-resolution average', commands[1]) - self.assertIn('-separate', commands[1]) - self.assertNotIn('-allow_projection_difference', commands[1]) - self.assertNotIn('-add_alpha', commands[1]) - self.assertNotIn('-a_srs', commands[1]) - self.assertIn('-r nearest', commands[1]) - self.assertNotIn('-srcnodata', commands[1]) - self.assertIn('-input_file_list', commands[1]) - self.assertIn(outdir + '/test.vrt', commands[1]) + cmd = alg.getConsoleCommands({'INPUT': [source], + 'SRC_NODATA': '', + 'OUTPUT': outdir + '/check.vrt'}, context, feedback) + t = cmd[1] + cmd[1] = t[:t.find('-input_file_list') + 17] + t[t.find('buildvrtInputFiles.txt'):] + self.assertEqual(cmd, + ['gdalbuildvrt', + '-resolution average -separate -r nearest ' + + '-input_file_list buildvrtInputFiles.txt ' + + outdir + '/check.vrt']) + # additional parameters + cmd = alg.getConsoleCommands({'INPUT': [source], + 'EXTRA': '-overwrite -optim RASTER -vrtnodata -9999', + 'OUTPUT': outdir + '/check.vrt'}, context, feedback) + t = cmd[1] + cmd[1] = t[:t.find('-input_file_list') + 17] + t[t.find('buildvrtInputFiles.txt'):] + self.assertEqual(cmd, + ['gdalbuildvrt', + '-resolution average -separate -r nearest -overwrite -optim RASTER -vrtnodata -9999 ' + + '-input_file_list buildvrtInputFiles.txt ' + + outdir + '/check.vrt']) def testGdalInfo(self): context = QgsProcessingContext()