svglib
svglib copied to clipboard
How to make the png background transparent?
I usually appreciate an illustrating code snippet, but I would hope @replabrobin might want to comment about the transparency features available for PNGs created with reportlab, before anybody does some code digging.
@deeplook So there are no ways to generate transparent pngs?
@gotounix Have you tried renderPM.drawToFile(drawing, filename, fmt='GIF', configPIL={....})
? See https://github.com/eduardocereto/reportlab/blob/master/src/reportlab/graphics/renderPM.py (old reportlab mirror on GitHub...)
At the moment the renderPM canvas is three colour only. I looked at various backends to replace, but have little time to really get into that. Libart lgpl is pretty much dead so unless anyone has suggestions for a replacement it's not likely to change soon.
Is there some way to specify the color that the transparency is replaced with? It seems to replace everything transparent with white. I'd like to use a different color instead to make that less noticable.
The renderPM canvas has a background option as does renderPM.drawToFile; bg=0xff00ff would make the background red.
Not sure whether this change is related or not,
https://bitbucket.org/rptlab/reportlab/commits/7df61e325601580bc36db042c6d6a8a776f62eef
This is still present with svglib 1.1.0 and reportlab 3.5.67 / Pillow 7.0.0
I require support for transparent SVGs -- does anyone know of a good alternative library?
A hack I can think of: call svglib
twice with different background colors, and if a pixel comes out with two different colors, make it transparent instead.
Hi, because of problems claudep found in the existing graphics state I added an alternate gstate based on py cairo (package rlPyCairo). It supports 32 bit colour and theoretically I believe you could get a transparent background to work. However, the defaults are set towards the existing three colour mechanisms so extension of the rlPyCairo code might be needed.
For now, it looks like CairoSVG works for people who must have transparency and can't wait for this project to support it
import cairosvg.surface
from PIL import Image
from io import BytesIO
def svg2pil(*args, dpi=96, **kwargs):
t = cairosvg.surface.Tree(*args, **kwargs)
f = BytesIO()
cairosvg.surface.PNGSurface(t, f, dpi).finish()
return Image.open(f)
# svg2pil(url='input.svg').show()
Following up on @Akuli 's answer:
from reportlab.graphics import renderPM
from reportlab.lib.colors import red, green
from PIL import ImageChops, Image
def drawing2png(drawing: Drawing, fp: Union[str, bytes]) -> None:
red_img = renderPM.drawToPIL(drawing, bg=red, configPIL={'transparent': red})
green_img = renderPM.drawToPIL(drawing, bg=green, configPIL={'transparent': green})
bg_mask = ImageChops.difference(red_img, green_img).convert('1', dither=Image.NONE)
bg_mask = ImageChops.invert(bg_mask)
red_img.putalpha(bg_mask)
red_img.save(fp, fmt='png')
Here's one line equivalent to @JamesTheAwesomeDude's CairoSVG example:
from cairosvg import svg2png
svg2png(file_obj=StringIO(svg_text),
write_to=png_file_name,
background_color='transparent')
Unfortunately, @Akuli's/@tsoos99dev's suggestion didn't work for me due to antialiasing. There would've probably been a way to prevent the ghosting by inverting the blending with the background, but I gave up on that since that still suffers from the scaling issue
A workaround I posted on a related issue also supports transparency. It uses pyMuPdf
that comes with precompiled wheels for Windows/Linux/MacOS so no fiddling with external dependencies is needed.
Install packages:
pip install pymupdf svglib
Run the code:
import fitz
from svglib import svglib
from reportlab.graphics import renderPDF
# Convert svg to pdf in memory with svglib+reportlab
# directly rendering to png does not support transparency nor scaling
drawing = svglib.svg2rlg(path="input.svg")
pdf = renderPDF.drawToString(drawing)
# Open pdf with fitz (pyMuPdf) to convert to PNG
doc = fitz.Document(stream=pdf)
pix = doc.load_page(0).get_pixmap(alpha=True, dpi=300)
pix.save("output.png")