web-dev-qa-db-ja.com

PythonでSVGをPNGに変換する

Pythonでsvgpngに変換するにはどうすればよいですか? svgのインスタンスにStringIOを保存しています。 pyCairoライブラリを使用する必要がありますか?そのコードをどのように書くのですか?

87
ram1

答えは「 pyrsvg "-a Python binding for librsvg

Ubuntu python-rsvgパッケージ が提供されています。 Googleの名前の検索は、ソースコードが「gnome-python-desktop」GnomeプロジェクトGITリポジトリ内に含まれているように見えるため、貧弱です。

SVGをカイロサーフェスにレンダリングしてディスクに書き込むミニマリストの「hello world」を作成しました。

import cairo
import rsvg

img = cairo.ImageSurface(cairo.FORMAT_ARGB32, 640,480)

ctx = cairo.Context(img)

## handle = rsvg.Handle(<svg filename>)
# or, for in memory SVG data:
handle= rsvg.Handle(None, str(<svg data>))

handle.render_cairo(ctx)

img.write_to_png("svg.png")

Update:2014年時点で、Fedora Linuxディストリビューションに必要なパッケージはgnome-python2-rsvg。上記のスニペットリストはそのまま機能します。

55
jsbueno

cairosvg を使用して行ったことを次に示します。

from cairosvg import svg2png

svg_code = """
    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
        <circle cx="12" cy="12" r="10"/>
        <line x1="12" y1="8" x2="12" y2="12"/>
        <line x1="12" y1="16" x2="12" y2="16"/>
    </svg>
"""

svg2png(bytestring=svg_code,write_to='output.png')

そして、それは魅力のように機能します!

詳細を参照してください: cairosvg document

57
nemesisfixx

Inkscapeをインストールし、コマンドラインとして呼び出します。

${INKSCAPE_PATH} -z -f ${source_svg} -w ${width} -j -e ${dest_png}

パラメーター-jを使用してのみ特定の長方形領域をスナップすることもできます。座標「0:125:451:217」

${INKSCAPE_PATH} -z -f ${source_svg} -w ${width} -j -a ${coordinates} -e ${dest_png}

SVGファイルに1つのオブジェクトのみを表示する場合は、SVGでセットアップしたオブジェクトIDでパラメーター-iを指定できます。それは他のすべてを隠します。

${INKSCAPE_PATH} -z -f ${source_svg} -w ${width} -i ${object} -j -a ${coordinates} -e ${dest_png}
39
blj

Wand-py (ImageMagickのWandラッパーの実装)を使用して、非常に高度なSVGをインポートしていますが、これまでのところ素晴らしい結果が得られています!これは必要なすべてのコードです:

_    with wand.image.Image( blob=svg_file.read(), format="svg" ) as image:
        png_image = image.make_blob("png")
_

私は今日これを発見したばかりで、これらの質問のほとんどが回答されてからしばらく経ったので、この回答に出くわすかもしれない他の人のために共有する価値があると感じました。

注:技術的にテストした結果、ImageMagickのformatパラメーターを実際に渡す必要さえないことがわかりました。したがって、with wand.image.Image( blob=svg_file.read() ) as image:はすべてが本当に必要でした。

編集:qrisによる編集の試行から、透明な背景を持つSVGでImageMagickを使用できる便利なコードを次に示します。

_from wand.api import library
import wand.color
import wand.image

with wand.image.Image() as image:
    with wand.color.Color('transparent') as background_color:
        library.MagickSetBackgroundColor(image.wand, 
                                         background_color.resource) 
    image.read(blob=svg_file.read(), format="svg")
    png_image = image.make_blob("png32")

with open(output_filename, "wb") as out:
    out.write(png_image)
_
26
streetlogics

これを試してください: http://cairosvg.org/

サイトは言う:

CairoSVGは、純粋なpythonで記述され、Pycairoのみに依存します。Python 2.6および2.7。

更新2016年11月25日

2.0.0は新しいメジャーバージョンであり、その変更ログには以下が含まれます。

  • ドロップPython 2サポート
11
user732592

ここで見つけた別の解決策 スケーリングされたSVGをQImageにレンダリングする方法?

from PySide.QtSvg import *
from PySide.QtGui import *


def convertSvgToPng(svgFilepath,pngFilepath,width):
    r=QSvgRenderer(svgFilepath)
    height=r.defaultSize().height()*width/r.defaultSize().width()
    i=QImage(width,height,QImage.Format_ARGB32)
    p=QPainter(i)
    r.render(p)
    i.save(pngFilepath)
    p.end()

PySideはWindowsのバイナリパッケージから簡単にインストールできます(他のことにも使用しているので簡単です)。

ただし、Wikimediaから国旗を変換する際にいくつかの問題に気づいたため、おそらく最も堅牢なsvgパーサー/レンダラーではありません。

6
Adam Kerz

Jsbuenoの答えの小さな拡張:

#!/usr/bin/env python

import cairo
import rsvg
from xml.dom import minidom


def convert_svg_to_png(svg_file, output_file):
    # Get the svg files content
    with open(svg_file) as f:
        svg_data = f.read()

    # Get the width / height inside of the SVG
    doc = minidom.parse(svg_file)
    width = int([path.getAttribute('width') for path
                 in doc.getElementsByTagName('svg')][0])
    height = int([path.getAttribute('height') for path
                  in doc.getElementsByTagName('svg')][0])
    doc.unlink()

    # create the png
    img = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
    ctx = cairo.Context(img)
    handler = rsvg.Handle(None, str(svg_data))
    handler.render_cairo(ctx)
    img.write_to_png(output_file)

if __== '__main__':
    from argparse import ArgumentParser

    parser = ArgumentParser()

    parser.add_argument("-f", "--file", dest="svg_file",
                        help="SVG input file", metavar="FILE")
    parser.add_argument("-o", "--output", dest="output", default="svg.png",
                        help="PNG output file", metavar="FILE")
    args = parser.parse_args()

    convert_svg_to_png(args.svg_file, args.output)
4
Martin Thoma

SVGスケーリングとPNGレンダリング

pycairo および librsvg を使用すると、SVGスケーリングとビットマップへのレンダリングを実現できました。 SVGが目的の出力である256x256ピクセルではない場合、rsvgを使用してSVGをCairoコンテキストに読み込み、スケーリングしてPNGに書き込むことができます。

main.py

import cairo
import rsvg

width = 256
height = 256

svg = rsvg.Handle('cool.svg')
unscaled_width = svg.props.width
unscaled_height = svg.props.height

svg_surface = cairo.SVGSurface(None, width, height)
svg_context = cairo.Context(svg_surface)
svg_context.save()
svg_context.scale(width/unscaled_width, height/unscaled_height)
svg.render_cairo(svg_context)
svg_context.restore()

svg_surface.write_to_png('cool.png')

RSVG Cバインディング

若干の小さな修正を加えたカリオのウェブサイトから。また、PythonからCライブラリを呼び出す方法の良い例

from ctypes import CDLL, POINTER, Structure, byref, util
from ctypes import c_bool, c_byte, c_void_p, c_int, c_double, c_uint32, c_char_p


class _PycairoContext(Structure):
    _fields_ = [("PyObject_HEAD", c_byte * object.__basicsize__),
                ("ctx", c_void_p),
                ("base", c_void_p)]


class _RsvgProps(Structure):
    _fields_ = [("width", c_int), ("height", c_int),
                ("em", c_double), ("ex", c_double)]


class _GError(Structure):
    _fields_ = [("domain", c_uint32), ("code", c_int), ("message", c_char_p)]


def _load_rsvg(rsvg_lib_path=None, gobject_lib_path=None):
    if rsvg_lib_path is None:
        rsvg_lib_path = util.find_library('rsvg-2')
    if gobject_lib_path is None:
        gobject_lib_path = util.find_library('gobject-2.0')
    l = CDLL(rsvg_lib_path)
    g = CDLL(gobject_lib_path)
    g.g_type_init()

    l.rsvg_handle_new_from_file.argtypes = [c_char_p, POINTER(POINTER(_GError))]
    l.rsvg_handle_new_from_file.restype = c_void_p
    l.rsvg_handle_render_cairo.argtypes = [c_void_p, c_void_p]
    l.rsvg_handle_render_cairo.restype = c_bool
    l.rsvg_handle_get_dimensions.argtypes = [c_void_p, POINTER(_RsvgProps)]

    return l


_librsvg = _load_rsvg()


class Handle(object):
    def __init__(self, path):
        lib = _librsvg
        err = POINTER(_GError)()
        self.handle = lib.rsvg_handle_new_from_file(path.encode(), byref(err))
        if self.handle is None:
            gerr = err.contents
            raise Exception(gerr.message)
        self.props = _RsvgProps()
        lib.rsvg_handle_get_dimensions(self.handle, byref(self.props))

    def get_dimension_data(self):
        svgDim = self.RsvgDimensionData()
        _librsvg.rsvg_handle_get_dimensions(self.handle, byref(svgDim))
        return (svgDim.width, svgDim.height)

    def render_cairo(self, ctx):
        """Returns True is drawing succeeded."""
        z = _PycairoContext.from_address(id(ctx))
        return _librsvg.rsvg_handle_render_cairo(self.handle, z.ctx)