deeplook / svglib

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

svg2rlg cause black background #209

Open jason40418 opened 4 years ago

jason40418 commented 4 years ago

I use plotly to draw a mesh3D and use "to_image()" to transfer into svg byte file. If use plotly "write_image()" to generate svg and png could success to export what I needed. However, when I use "io.BytesIO()" to read and "svg2rlg()" would cause black background.

Code

Plotly Layout Setting

self.__figure.update_layout(
            margin=dict(l=0, r=0, t=0, b=20),
            height=800,
            autosize=True,
            scene = dict(
                xaxis_title='trade',
                yaxis_title='inter',
                zaxis_title='Net Profit',
                xaxis = dict(nticks=15, range=[1, 30],),
                yaxis = dict(nticks=8, range=[1, 30],),
                zaxis = dict(nticks=8, range=[min_z-100000.0, max_z+100000.0],),
            )
        )

svg2rlg

from reportlab.graphics import renderPDF, renderPM

image = figure.to_image(format='svg')
figure.write_image("fig1.svg")
figure.write_image("fig1.png")
drawing = svg2rlg(io.BytesIO(image))
scaleFactor = 527/drawing.width
drawing.width *= scaleFactor
drawing.height *= scaleFactor
drawing.scale(scaleFactor, scaleFactor)

renderPM.drawToFile(drawing, 'svg_demo.png', 'PNG')

Result

Environments

claudep commented 4 years ago

For renderPM, it looks like there is a bg option, read https://github.com/deeplook/svglib/issues/171#issuecomment-468239750. For renderPDF, the _PDFRenderer.drawImage method is using canvas.drawInlineImage instead of canvas.drawImage, and the former doesn't expose the mask parameter. I don't see what svglib can do.

jason40418 commented 4 years ago

After trying I found that Plotly layout have bgcolor in scene and it default is rgba(0, 0, 0, 0). If I change it to rgba(255, 255, 255, 0) it would not cause black background. So, I assume that some method would cause lost alpha value and finally result it.

jayceslesar commented 3 years ago

Still getting this issue...It only happens with time series plots on plotly in my case, or maybe it only happens on graphs with more than x data points. I want to think it is a plotly issue because svg2rlg works fine on histograms as well as bar graphs that are also generated from plotly....

James-E-A commented 3 years ago

For renderPM, it looks like there is a bg option

Sadly, renderPM.drawTo_anything_(svglib.svg2rlg(fn), bg=0x00000000) doesn't work/allow leaving the Alpha channel low, so this workaround only works for those who need a solid, non-tranparent background.

(That said, should this issue #209 be closed as a duplicate of #171?)

rapto commented 2 years ago

I seem to get the same bug when converting into pdf. A black background appears. My svg is generated by mapnik and seems to have an embedded raster image.

ronak1009 commented 1 year ago

I too have the same issue with Python 3.9 and following packages: plotly==5.10.0 svglib==1.4.1 kaleido==0.1.0.post1

The svg does not have transparent background but svglib makes it black Attached svg

svgviewer-output

LuighiV commented 8 months ago

For renderPM, it looks like there is a bg option, read #171 (comment). For renderPDF, the _PDFRenderer.drawImage method is using canvas.drawInlineImage instead of canvas.drawImage, and the former doesn't expose the mask parameter. I don't see what svglib can do.

I totally agree with @claudep. Had a same problem when generating with BaseDocTemplate. I just needed to change the source code of reportlab, and it worked flawlessly. For anyone interested, it is located in /usr/lib/python3.11/site-packages/reportlab/graphics/renderPDF.py:

    def drawImage(self, image):
        path = image.path
        # currently not implemented in other renderers
        if path and (hasattr(path,'mode') or os.path.exists(image.path)):
-            self._canvas.drawInlineImage(
+            self._canvas.drawImage(
                    path,
                    image.x, image.y,
                    image.width, image.height,
+                   mask='auto'
                    )