[GIS] pyQGIS changing Paletted Raster Layers to Grayscale

colorpyqgispythonqgisraster

I've written a plugin which imports a number of colour geoTifs (map tiles) and works correctly but it would be great to display these as Grayscale after loading in.

The geoTifs load as paletted images (under Render Type) and I am looking to have them display as they do when you manually change the layer properties to set Grayscale to any of the three options (by lightness, by luminosity, by averaqe).

I've tried many things which haven't worked including things like layer.setDrawingStyle('PalettedSingleBandGray') which gives a very strange looking image – I assume it's only using information from a single colour channel?

I understand that these Grayscale options are relatively new to QGIS and hence their implementation through pyQGIS may not be straightforward, but I'm completely stuck with this now.

Following the response from xunilk, I've had a further play with this and whilst this does work, it doesn't quite do what I'm after.

Running xunilk's script for a colour tif gives:

d

Desired result (settings in image 3):

d

Setting grayscale OR desaturating the image as in image 3 give result like that in image 2.

d

Importantly, note that when SingleBandGrayRenderer is used (manually selected or through the script), even the manual selection of the grayscale option as in image 3 above gives a result that looks like image 1.

It seems that it needs to be loaded using QgsPalettedRasterRenderer with relevant rendering options specified?

Best Answer

Next script works for me.

layer=iface.activeLayer()

myGrayRenderer = QgsSingleBandGrayRenderer(layer.dataProvider(), 
                                           1)

layer.setRenderer(myGrayRenderer)

renderer = layer.renderer()
provider = layer.dataProvider()

layer_extent = layer.extent()
uses_band = renderer.usesBands()

myType = renderer.dataType(uses_band[0])

stats = provider.bandStatistics(uses_band[0], 
                                QgsRasterBandStats.All, 
                                layer_extent, 
                                0)

myEnhancement = QgsContrastEnhancement(myType)

contrast_enhancement = QgsContrastEnhancement.StretchToMinimumMaximum

myEnhancement.setContrastEnhancementAlgorithm(contrast_enhancement,True)
myEnhancement.setMinimumValue(stats.minimumValue)
myEnhancement.setMaximumValue(stats.maximumValue)

layer.renderer().setContrastEnhancement(myEnhancement)
layer.triggerRepaint()

I tested it for changing an object of QgsSingleBandPseudoColorRenderer class (in your case it would be a QgsPalettedRasterRenderer object) in a QgsSingleBandGrayRenderer class object.

Before running the script at the Python Console:

enter image description here

After running the script:

enter image description here

Editing Note:

I tested the script with the same raster and a paletted render type (see next image) and it worked too.

enter image description here

Related Question