Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to make the png background transparent? #171

Open
gotounix opened this issue Jan 25, 2019 · 14 comments
Open

How to make the png background transparent? #171

gotounix opened this issue Jan 25, 2019 · 14 comments

Comments

@gotounix
Copy link

No description provided.

@deeplook
Copy link
Owner

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.

@gotounix
Copy link
Author

@deeplook So there are no ways to generate transparent pngs?

@deeplook
Copy link
Owner

@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...)

@MrBitBucket
Copy link

MrBitBucket commented Jan 25, 2019

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.

@Akuli
Copy link

Akuli commented Feb 27, 2019

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.

@replabrobin
Copy link
Contributor

The renderPM canvas has a background option as does renderPM.drawToFile; bg=0xff00ff would make the background red.

@liangqi
Copy link

liangqi commented Oct 30, 2019

Not sure whether this change is related or not,

https://bitbucket.org/rptlab/reportlab/commits/7df61e325601580bc36db042c6d6a8a776f62eef

@James-E-A
Copy link

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?

@Akuli
Copy link

Akuli commented May 23, 2021

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.

@replabrobin
Copy link
Contributor

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.

@James-E-A
Copy link

James-E-A commented Jun 5, 2021

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()

@tsoos99dev
Copy link

tsoos99dev commented Jan 26, 2022

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')

@donkirkby
Copy link
Contributor

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')

@M4a1x
Copy link

M4a1x commented Oct 22, 2022

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")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants