deeplook / svglib

Read SVG files and convert them to other formats.
GNU Lesser General Public License v3.0
311 stars 80 forks source link

Weird black and white lines in SVG rendering to PNG #299

Open nganju98 opened 2 years ago

nganju98 commented 2 years ago

Hi, thanks for making this library for all of us!

I'm trying to use your library to convert an SVG to PNG. When I try the simple code:

from svglib.svglib import svg2rlg
from reportlab.graphics import renderPDF, renderPM

drawing = svg2rlg("svg.txt")
renderPM.drawToFile(drawing, "temp.png", fmt="PNG")

I get a lot of black and white lines in the PNG. I've attached both the source SVG and the generated PNG. I'm working on Windows, if that matters.

Here's the svg file: svg.txt

Here's the PNG generated: temp

deeplook commented 2 years ago

The PDF output seems fine, so it looks like an issue with the reportlab bitmap renderer for which @replabrobin is the authority. Can you generate a minimal file showing this behaviour?

replabrobin commented 2 years ago

Hi this is caused by our PM renderer backend based on libart_lgpl not coping with with complex paths. If you have a late model reportlab you can use a cairo based PM renderer which seems better. This involves 1) installing libcairo2 in the OS; then 2) pip install pycairo cairocffi rlPyCairo and finally 3) adding a settings override reportlab_settings.py (on the python path) and putting renderPMBackend='rlPyCairo' on a line in there. So far the only difference I have found is that the image pasting isn't identical. I have no idea if this can work on windows or OSX.

replabrobin commented 2 years ago

There are an infinite number of other graphics renderers and probably we should be using AGG or SKIA, but those a AGG is unmaintained and SKIA is just vast.

replabrobin commented 2 years ago

Also I have no real idea which is best pycairo or cairocffi; they both seem to use libcairo, but I just assumed cffi would be better as presumably it uses python + cffi rather than using a compiled extension.

eOperationsPN commented 2 years ago

Hi this is caused by our PM renderer backend based on libart_lgpl not coping with with complex paths. If you have a late model reportlab you can use a cairo based PM renderer which seems better. This involves 1) installing libcairo2 in the OS; then 2) pip install pycairo cairocffi rlPyCairo and finally 3) adding a settings override reportlab_settings.py (on the python path) and putting renderPMBackend='rlPyCairo' on a line in there. So far the only difference I have found is that the image pasting isn't identical. I have no idea if this can work on windows or OSX.

Before step 2) you need to follow https://stackoverflow.com/a/61164149/12579917

burhop commented 1 year ago

Just ran into this problem too. Scaling down some polygons to fit 256x256 results in very thin polygons in svg that stretch out to right end when converted to png. Here is a trivial example where the last path is displayed incorrectly after converting to png.

I'm generating a few thousand svg's thta I convert into png's. most are fine but there are a few buggy ones like below.

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

 <svg width="256px" height="256px" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg">

  <path d=" M 98.37 92.00 L 98.37 92.00 L 160.53 92.00 L 160.53 20.00 L 236.00 20.00 L 236.00 214.40 L 23.60 214.40 L 20.00 192.80 L 20.00 20.00 L 98.37 20.00 z"
    style="fill:#ff0000; fill-opacity:0.13; fill-rule:evenodd; stroke:#330000; stroke-opacity:1.00; stroke-width:1.00;"/>
  <path d=" M 98.37 92.00 L 98.37 92.00 L 160.54 92.00 L 160.54 20.00 L 236.00 20.00 L 236.00 214.40 L 23.60 214.40 L 20.00 192.80 L 20.00 20.00 L 98.37 20.00 z"
    style="fill:#00ff00; fill-opacity:0.13; fill-rule:evenodd; stroke:#00aa00; stroke-opacity:1.00; stroke-width:1.00;"/>
  <path d=" M 160.54 20.00 L 160.54 20.00 L 160.54 92.00 L 160.53 92.00 L 160.53 20.00 z M 98.37 92.00 L 98.37 92.00 L 98.37 92.00 L 98.37 20.00 L 98.37 20.00 z"
    style="fill:#0000ff; fill-opacity:1.00; fill-rule:evenodd; stroke:#0000aa; stroke-opacity:1.00; stroke-width:1.00;"/>
</svg>