skia-python icon indicating copy to clipboard operation
skia-python copied to clipboard

(Question) Rendering SVGs to bitmap?

Open Spooghetti420 opened this issue 3 years ago • 7 comments

I had heard that skia was used in browsers in order to rasterise SVGs; is there a way to load an SVG image like you can bitmap images, and draw that to a canvas, and then export it as a PNG, for instance? I'm currently trying:

surface = skia.Surface(678, 960)
with surface as canv:
    svg =  skia.Image.open("0001.svg")
    canv.drawImage(svg, 0, 0)
image = surface.makeImageSnapshot()
image.save("0001.png", skia.kPNG)

...but this doesn't work: RuntimeError: Failed to decode an image. Thanks for creating this library, by the way; it's much appreciated. :)

Spooghetti420 avatar Jul 30 '21 08:07 Spooghetti420

See the tutorial https://kyamagu.github.io/skia-python/tutorial/canvas.html#svg

kyamagu avatar Jul 30 '21 09:07 kyamagu

For rasterization, there is the experimental SVGDOM api.

kyamagu avatar Jul 30 '21 09:07 kyamagu

I've tried that. Works very well: https://github.com/0lru/p3ui/blob/main/demos/canvas/svg.py. Also rendered material icons locally, reading binaries from a ZipFile. Example:

        bytes = someZipFile.read(icon.path.as_posix())
        stream = skia.MemoryStream(bytes, True) # True means "copy", False means "move"
        dom = skia.SVGDOM.MakeFromStream(stream

md

You can render to any backend. I'm using OpenGL..

0lru avatar Dec 10 '21 13:12 0lru

This is working end to end example:

import skia

stream = skia.FILEStream.MakeFromFile('./input.svg')
dom = skia.SVGDOM.MakeFromStream(stream)
# is there a way to query the bounding box from the loaded SVG?

dom.setContainerSize(skia.Size(128, 128))
surface = skia.Surface(512, 512)
with surface as canvas:
    canvas.scale(10, 10)
    dom.render(canvas)

image = surface.makeImageSnapshot()
image.save('/output.png', skia.kPNG)

By default the SVG is tiny. I would want to automatically want to fill it to the entire surface. I've found I can use scale for that. However, I'm sure by how much I need to scale it. @kyamagu is there a way to get the bounds or dimensions from the loaded SVG?

animanathome avatar Jan 12 '22 16:01 animanathome

@animanathome Please check if there is a relevant API in the documentation. skia-python is merely a wrapper

kyamagu avatar Jan 13 '22 01:01 kyamagu

You use to SetContainerSize() method for the SVGDOM class to set the svg's containerize to the same as the surface you want to out it to, if you want to fill it.

HinTak avatar Jul 09 '23 18:07 HinTak

The containSize() method supposedly returns the "default" (designed) size of the SVG.

HinTak avatar Jul 09 '23 18:07 HinTak