Skip to content

SVG export: linearGradient not exported correctly #1849

@paulmueller

Description

@paulmueller

I am using a custom colorbar (derived from https://gist.github.com/maedoc/b61090021d2a5161c5b9) to show a simple colorbar next to my plots. When exporting the colorbar as SVG (PNG works), the gradient is not shown correctly. The linearGradient tag in the resulting SVG file contains the right steps, but there is some issue with the way it is scaled, probably due to a bad usage of gradientUnits="userSpaceOnUse".

Short description

On SVG export, the linearGradient is not set correctly. This looks like a bad combination of gradientUnits="userSpaceOnUse" and SVG coordinates.

Code to reproduce

This is a minimal working example. Run the script and export the entire scene as SVG.

import numpy as np
import pyqtgraph as pg
from pyqtgraph.graphicsItems.GradientEditorItem import Gradients



class ColorGradient(pg.GraphicsObject):

    def __init__(self, cmap, width, height):
        pg.GraphicsObject.__init__(self)

        # handle args
        w, h = width, height
        stops, colors = cmap.getStops('float')
        smn, spp = stops.min(), stops.ptp()
        stops = (stops - stops.min())/stops.ptp()

        # setup picture
        self.pic = pg.QtGui.QPicture()
        p = pg.QtGui.QPainter(self.pic)

        # draw bar with gradient following colormap
        p.setPen(pg.mkPen('k'))
        grad = pg.QtGui.QLinearGradient(w/2.0, 0.0, w/2.0, h*1.0)
        for stop, color in zip(stops, colors):
            grad.setColorAt(1.0 - stop, pg.QtGui.QColor(*[c for c in color]))
        p.setBrush(pg.QtGui.QBrush(grad))
        p.drawRect(pg.QtCore.QRectF(0, 0, w, h))

        # done
        p.end()

        
    def paint(self, p, *args):
        # paint underlying mask
        p.setPen(pg.QtGui.QColor(255, 255, 255, 0))
        p.setBrush(pg.QtGui.QColor(255, 255, 255, 200))
        
        # paint colorbar
        p.drawPicture(0, 0, self.pic)
        
    def boundingRect(self):
        return pg.QtCore.QRectF(self.pic.boundingRect())

if __name__ == '__main__':
    app = pg.mkQApp()

    # use less ink
    pg.setConfigOption('background', 'w')
    pg.setConfigOption('foreground', 'k')

    pw = pg.plot()


    cm = pg.ColorMap(*zip(*Gradients["viridis"]["ticks"]))
    stops, colors = cm.getStops('float')

    
    # make colorbar, placing by hand
    cb = ColorGradient(cm, 200, 200)
    pw.scene().addItem(cb)
    cb.translate(100, 100)
    cb.setZValue(100)


    app.exec_()

Expected behavior

This is a screenshot (PNG export works as well):
image

Real behavior

This is a screenshot of the exported SVG opened in inkscape:
image

This is the linearGradient-part in the (larger) SVG file. Note the usage of gradientUnits="userSpaceOnUse". If you removed this and put all corrdinates in % everywhere, the linearGradient is reproduced correctly.

<linearGradient gradientUnits="userSpaceOnUse" x1="100" y1="0" x2="100" y2="200" id="gradient1">
    
    
    <stop offset="0" stop-color="#fde724" stop-opacity="1"/>
    
    
    <stop offset="0.25" stop-color="#5ec961" stop-opacity="1"/>
    
    
    <stop offset="0.5" stop-color="#20908c" stop-opacity="1"/>
    
    
    <stop offset="0.75" stop-color="#3a528b" stop-opacity="1"/>
    
    
    <stop offset="1" stop-color="#440154" stop-opacity="1"/>

</linearGradient>

Tested environment(s)

  • PyQtGraph version: 0.12.1
  • Qt Python binding: 'PyQt5 5.15.1 Qt 5.15.1'
  • Python version: 3.8.5 (default, May 27 2021, 13:30:53)
  • NumPy version: '1.18.5'
  • Operating system: Ubuntu 20.04
  • Installation method: pip

Additional context

https://github.com/ZELLMECHANIK-DRESDEN/ShapeOut2/issues/87

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugexportersIssue relating to exportershelp wantedAssistance resolving this issue is wantedsvg

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions