TransWikia.com

Exporting a raster map to PNG in QGIS keeping the exact legend colors

Geographic Information Systems Asked by Asfixia on April 3, 2021

I’m developing a plugin for QGIS called ‘Mappia_Example’ to allows the community to publish its maps online. But i need some help, i am trying to export a map in QGIS to PNG but its using aproximated colors instead of the ones defined on legend entries.

You can export a map using the interface by clicking: Project -> Import/Export -> Export as image. and the issue is the same.

The problem is that the legend has a value but the PNG file has other colors. I need a way to export the map using the color in legend, not approximated colors. I’ve already set the ResamplingMethod to ‘Nearest’ but without success.

How to export a tif map to PNG in QGIS, and it keep using the exact colors of legend entries? If someone can please help.

Examples of wrong pixel color values:

  1. Issue on a gray entry (178,178,178) drawn as (177,177,177):

Legend (178,178,178) gray as ‘No Forest’ contrast, brightness and saturation are 0:
Legend (178,178,178) gray as 'No Forest' contrast, brightness and saturation are 0
Drawn as (177,177,177) pixel: Getting the RGB value of the gray rendered entry as (177,177,177)

  1. Issue on a yellow entry (255,178, 0) drawn as (250,225,5):

Another example of difference in a legend entry with color (255,178, 0) representing ’43-48′ interval.
Legend color (255,178, 0) representing 43-48
Drawn as (250,225,5) pixel:
This legend is drawn as (250,225,5)

A Working code that i made trying to export using pyQgis tested in 3.14 but should work from 3.4 version:

from qgis.core import (QgsCoordinateTransform, QgsCoordinateReferenceSystem, QgsProject)

#Configure the rendering settings for the WMS tiles.
def createLayerRenderSettings(layer, dest_crs, outputFormat):
    settings = QgsMapSettings()
    settings.setFlag(QgsMapSettings.Flag.Antialiasing, False)
    settings.setFlag(QgsMapSettings.Flag.UseRenderingOptimization, False)
    #settings.setFlag(QgsMapSettings.Flag.LosslessImageRendering, True) #not available yet 
    settings.setFlag(QgsMapSettings.Flag.UseAdvancedEffects, False)
    
    settings.setOutputImageFormat(outputFormat)
    settings.setDestinationCrs(dest_crs)
    settings.setLayers([layer])
    dpi = 256
    settings.setOutputDpi(dpi)
    color = QColor(0, 0, 0, 0)
    settings.setBackgroundColor(color)
    layer.resampleFilter().setZoomedInResampler(None)
    layer.resampleFilter().setZoomedOutResampler(None)
    layer.resampleFilter().setOn(False)
    return settings

def getMapExtent(layer, projection):
    mapExtent = layer.extent()
    projection.validate()
    layer.crs().validate()
    src_to_proj = QgsCoordinateTransform(layer.crs(), projection, QgsProject.instance())
    return src_to_proj.transformBoundingBox(mapExtent)

#Return the rendered map (QImage) for the metatile zoom level.
def renderMetatile(dest_crs, renderSettings, transformContext, sourceCrs, extents, width, height):
    wgs_to_dest = QgsCoordinateTransform(sourceCrs, dest_crs, transformContext)
    renderSettings.setExtent(wgs_to_dest.transformBoundingBox(extents)) #QgsRectangle(*extents)))
    size = QSize(width, height)
    renderSettings.setOutputSize(size)
    image = QImage(size, renderSettings.outputImageFormat())
    image.fill(Qt.transparent)
    painter = QPainter(image)
    job = QgsMapRendererCustomPainterJob(renderSettings, painter)
    job.renderSynchronously()
    painter.end()
    return image


layer = QgsProject.instance().mapLayersByName("phylogenetic_composition")[0]
dest_crs = QgsCoordinateReferenceSystem('EPSG:3857')
wgs_crs = QgsCoordinateReferenceSystem('EPSG:4326')
extent = getMapExtent(layer, wgs_crs)
outputFormat = QImage.Format_ARGB32
layerRenderSettings = createLayerRenderSettings(layer, dest_crs, outputFormat)
tileHeight = tileWidth = 256
mapRendered = renderMetatile(dest_crs, layerRenderSettings, layer.transformContext(), wgs_crs, extent, tileWidth, tileHeight)
quality = 100
mapRendered.save('C:tmptile.png', 'PNG', quality)
#no success with paleted png either
mapRendered.convertToFormat(QImage.Format_Indexed8, Qt.ColorOnly | Qt.ThresholdDither | Qt.AvoidDither).save("C:/tmp/2a.png", "PNG", -1)

Example data:

  1. Can download the map i’m using: https://github.com/asfixia/Mappia_Example/releases/download/Map_Download/phylogenetic_composition.zip
  2. Or access the map "phylogenetic_composition" online in: https://maps.csr.ufmg.br/calculator/?map=&queryid=152&listRepository=Repository&storeurl=https://github.com/asfixia/Mappia_Example/

PS: I’ve tried setting the QgsMapSettings.Flag.LosslessImageRendering in QGIS 3.15 but the results still the same.

Edit: The exact style i am using: https://github.com/asfixia/Mappia_Example/releases/download/Map_Download/phylogenetic_composition.qml

Edit2: I had to change the "Min / Max " interpolation method to "discrete" so the colors are now exact. The fixed QML style can be downloaded at: https://github.com/asfixia/Mappia_Example/releases/download/Map_Download/phylogenetic_composition_fixed.qml

One Answer

As @Asfixia mentioned in the comments, setting the interpolation method to Discrete in rasters Symbology parameters solved the problem:

enter image description here

Correct answer by Comrade Che on April 3, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP