अजगर में SVG को PNG में बदलें


99

मैं किसी को परिवर्तित करना svgकरने के लिए png, अजगर में? मैं svgएक उदाहरण में संग्रहीत कर रहा हूँ StringIO। क्या मुझे पाइकाइरो लाइब्रेरी का उपयोग करना चाहिए? मैं उस कोड को कैसे लिखूं?



2
उस धागे ने समस्या को अनसुलझा कर दिया। स्वीकृत उत्तर पूछने वाले से आया जो अपने असफल कोड प्रयास को साझा कर रहा था। दूसरे उत्तर ने ImageMagick का सुझाव दिया लेकिन एक टिप्पणीकार ने कहा कि ImageMagick "SVG की व्याख्या करने का एक भयानक काम करता है।" मैं नहीं चाहता कि मेरे pngs भयानक दिखें इसलिए मैं फिर से सवाल पूछ रहा हूं।
ram1


उस लिंक के उदाहरण Win32 के लिए विशिष्ट हैं। मैं linux चला रहा हूँ।
ram1

इस ब्लॉग पोस्ट पर एक नज़र डालें , ऐसा लगता है कि यह वही हो सकता है जिसकी आपको आवश्यकता है।
giodamelio

जवाबों:


60

जवाब " pyrsvg " है - librsvg के लिए एक पायथन बाइंडिंग ।

इसमें उबंटू पायथन-आरएसवीजी पैकेज उपलब्ध है। Google को इसके नाम के लिए खोज करना खराब है क्योंकि इसका स्रोत कोड "gnome-python-desktop" Gnome प्रोजेक्ट GIT रिपॉजिटरी के अंदर समाहित होता है।

मैंने एक न्यूनतम "हैलो वर्ल्ड" बनाया जो एसवीजी को एक काइरो सतह तक पहुंचाता है और इसे डिस्क पर लिखता है:

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

अपडेट : 2014 के रूप में फेडोरा लिनक्स वितरण के लिए आवश्यक पैकेज है: gnome-python2-rsvg। उपरोक्त स्निपेट सूची अभी भी काम करती है।


1
महान, अच्छी तरह से काम करता है। लेकिन क्या cairoतस्वीर के HEIGHT और WIDTH को अपने आप निर्धारित करने का कोई तरीका है ? मैंने *.svgफ़ाइल को देखा है , वहां से HEIGHT और WIDTH निकालने के लिए, लेकिन यह दोनों पर सेट है 100%। बेशक, मैं तस्वीर के गुणों को देख सकता हूं, लेकिन चूंकि यह छवि प्रसंस्करण में केवल एक कदम है, यह वह नहीं है जो मैं चाहता हूं।
quapka

1
यदि आपकी फ़ाइलों की "चौड़ाई" और "ऊंचाई" 100% पर सेट है, तो कोई जादू काहिरा या आरएसवीजी आकार का अनुमान लगाने के लिए नहीं कर सकता है: ऐसी एसवीजी फाइलें निर्माता सॉफ्टवेयर (/ व्यक्ति) द्वारा स्वतंत्र आकार छोड़ दी गई थीं। एसवीजी फ़ाइल आयात करने के लिए आसपास का HTML कोड भौतिक आकार की आपूर्ति करेगा। हालाँकि, rsvg की "हैंडल" ऑब्जेक्ट में एक .get_dimension_data()विधि है जो मेरे उदाहरण फ़ाइल (एक अच्छी तरह से व्यवहार किए गए SVG) के लिए काम करती है - इसे आज़माएं।
jsbueno

1
2014 के रूप में, ubuntu के लिए, आप उपयोग कर सकते हैं: apt-get install
अजगर-rsvg

1
क्या छवि के लिए एक सफेद पृष्ठभूमि जोड़ने के लिए एक त्वरित आदेश है यदि इसकी वर्तमान पृष्ठभूमि पारदर्शी है?
फिएटजफ

@jsbueno मैं विंडोज 8.1 और अजगर 2.7.11 का उपयोग करता हूं मैं कैरो और आरएसवीजी को कैसे स्थापित कर सकता हूं और इसे काम कर सकता हूं। मैं यह काम करने के लिए संघर्ष कर रहा था। आपके विस्तृत विवरण के लिए BTW +1।
मार्लोन एबेकून

88

यहाँ मैं 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 दस्तावेज़


5
नमस्ते। क्या आप जानते हैं कि मैं ऐसा कैसे कर सकता हूं लेकिन बिना किसी फाइल को लिखे? मुझे वेबसर्वर से ब्राउज़र में png सामग्री को पुश करने की आवश्यकता है, ताकि उपयोगकर्ता छवि को डाउनलोड कर सके। Png फाइल को सेव करना हमारे प्रोजेक्ट में मान्य विकल्प नहीं है, इसीलिए मुझे इसकी आवश्यकता है। धन्यवाद
estemendoza

4
मैं खुद ऐसा कर रहा हूं। यह मूल रूप से इस बात पर निर्भर करता है कि आपके वेब अनुरोधों को संभालते समय आपके पास कौन से टूल या फ्रेमवर्क हैं, लेकिन कोई फर्क नहीं पड़ता है, मूल विचार यह है कि पैरामीटर svg2pngमें कोई streamऑब्जेक्ट लेता है write_to, और यह या तो आपकी HTTP रिस्पांस ऑब्जेक्ट हो सकता है (जो में है) अधिकांश चौखटे एक फ़ाइल की तरह वस्तु) या कुछ अन्य स्ट्रीम है, जो आप तब Content-Dispositionहेडर का उपयोग करके ब्राउज़र में सेवा करते हैं । यहाँ देखें: stackoverflow.com/questions/1012437/…
nemesisfixx

4
उन लोगों के लिए जो उस कोड के साथ समस्याओं का अनुभव करते हैं, जैसा कि मैं था: 1)। bytestringबाइट्स स्वीकार करता है, इसलिए पहले स्ट्रिंग को bytestring=bytes(svg,'UTF-8') 2 से बदलें )। फ़ाइल मोड द्विआधारी होना चाहिए, इसलिएopen('output.png','wb')
सर्ज ज़हरचेंको

3
साइरोवग केवल पायथन 3.4+ का समर्थन करता है। उन्होंने पायथन 2 का समर्थन छोड़ दिया है
मार्लोन एबेकून

1
svg2pngमेरे लिए नहीं था , मुझे इस्तेमाल करना था cairosvg.surface.PNGSurface.convert(svg_str, write_to='output.png')
टोबटॉब्स

39

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}

यदि आप एसवीजी फ़ाइल में केवल एक ऑब्जेक्ट दिखाना चाहते हैं, तो आप -iउस ऑब्जेक्ट आईडी के साथ पैरामीटर निर्दिष्ट कर सकते हैं जिसे आपने एसवीजी में सेटअप किया है। यह बाकी सब कुछ छिपाता है।

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

2
+1 क्योंकि यह शेल स्क्रिप्टिंग के लिए भी बेहद उपयोगी है। Inkscape की कमांड लाइन पर पूर्ण डॉक्स के लिए inkscape.org/doc/inkscape-man.html देखें ।
प्रधान

धन्यवाद, यह ऐसा करने का सबसे आसान तरीका था। विंडोज पर, इसे बनाने के लिए ताकि आपको हर बार Inkscape के लिए पूर्ण पथ में टाइप न करना पड़े, आप इसे अपने पथ में पर्यावरण चर में जोड़ सकते हैं
एलेक्स एस

3
यह कोई उत्तर नहीं है। यह एक वर्कअराउंड है। ओपी ने पायथन समाधान के लिए कहा।
लैमिनो

31

मैं कुछ सुंदर उन्नत SVGs आयात करने के लिए Wand-py (ImageMagick के आसपास Wand आवरण का एक कार्यान्वयन) का उपयोग कर रहा हूं और अब तक शानदार परिणाम देखे हैं! यह सब कोड है जो इसे लेता है:

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

मुझे आज ही यह पता चला है, और ऐसा लगा कि यह किसी और के लिए साझा करने के लायक था, जो इस उत्तर के लिए संघर्ष कर सकता है क्योंकि इनमें से अधिकांश प्रश्नों के उत्तर दिए जाने के कुछ समय हो चुके हैं।

नोट: तकनीकी रूप से परीक्षण में मैंने पाया कि आपको वास्तव में ImageMagick के लिए प्रारूप पैरामीटर में पास नहीं करना है, इसलिए with wand.image.Image( blob=svg_file.read() ) as image: यह सब वास्तव में आवश्यक था।

EDIT: 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)

2
वांड मेरे पीएनजी के लिए काहिरा से बहुत बेहतर काम करते थे ।
प्रातः

3
मुझे त्रुटि है image.read(blob=svg_file.read(), format="svg") NameError: name 'svg_file' is not defined
adrienlucca.wordpress.com

2
svg_fileइस उदाहरण में एक "फ़ाइल" ऑब्जेक्ट माना जाता है, सेटिंग svg_fileकुछ इस तरह दिखाई देगी:svg_file = File.open(file_name, "r")
सड़क पर जूल

2
धन्यवाद, cairoऔर rsvg'स्वीकृत' विधि मेरे पीडीएफ के लिए काम नहीं करती थी। pip install wandऔर आपके स्निपेट ने चाल
चली

5
आप एक svg है, तो strउसके बाद आप पहली बार इस तरह द्विआधारी में एन्कोड करने की जरूरत है: svg_blob = svg_str.encode('utf-8')। अब आप को बदल कर उपरोक्त विधि का उपयोग कर सकते blob=svg_file.read()के साथ blob=svg_blob
अशरबार

12

इसे इस्तेमाल करे: http://cairosvg.org/

साइट कहती है:

काहोसिव्स शुद्ध अजगर में लिखा गया है और केवल पाइकाइरो पर निर्भर करता है। यह पायथन 2.6 और 2.7 पर काम करने के लिए जाना जाता है।

अपडेट 25 नवंबर, 2016 :

2.0.0 एक नया प्रमुख संस्करण है, इसके चैंज में शामिल हैं:

  • पायथन 2 समर्थन को गिराएं

दुर्भाग्य से, इसके साथ दो समस्या है। सबसे पहले, यह संभाल नहीं है <clipPath><rect ... /></clipPath>। दूसरा, यह -d (DPI) विकल्प नहीं लेता है।
रे

2
@ रे, कायरोएसवीजी ट्रैकर पर बग रिपोर्ट / सुविधा अनुरोध भेजें !
साइमन सैपिन

@ साइमन, क्या आप इसे कर सकते हैं? मैं बहुत व्यस्त हूं और मैं अगले 1-2 महीने में रहूंगा।
रे

2
@ रे, वास्तव में -d / -dpi विकल्प में अभी कुछ समय है, और मुझे बताया गया है कि <clippath> के लिए समर्थन कुछ हफ्तों पहले git संस्करण में जोड़ा गया था।
साइमन सैपिन

@Simon, अच्छा! धन्यवाद! :)
रे

6

एक और समाधान मैंने अभी यहां पाया है कि एक स्केल एसवीजी को क्यूमैज को कैसे प्रस्तुत किया जाए?

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 को विंडोज में बाइनरी पैकेज से आसानी से इंस्टॉल किया जाता है (और मैं इसे अन्य चीजों के लिए उपयोग करता हूं इसलिए मेरे लिए यह आसान है)।

हालाँकि, मैंने विकिमीडिया से देश के झंडे को परिवर्तित करते समय कुछ समस्याएं देखीं, इसलिए शायद सबसे मजबूत svg parser / रेंडरर नहीं।


5

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 __name__ == '__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)

मैं svg चौड़ाई और ऊंचाई निष्कर्षण का इस्तेमाल किया। मैं svg मानक के बारे में निश्चित नहीं हूं, लेकिन मेरी कुछ svg फाइलों में चौड़ाई या ऊँचाई एक गैर-संख्यात्मक स्ट्रिंग जैसे कि 'mm' या 'px' (उदा: '250mm') के बाद आती है। इंट ('250 मिमी') एक अपवाद फेंकता है और मुझे कुछ अतिरिक्त मोड़ बनाने पड़े।
WigglyWorld

5

मुझे कोई भी उत्तर संतोषजनक नहीं लगा। सभी उल्लिखित पुस्तकालयों में कुछ समस्या है या अन्य जैसे अजगर 3.6 के लिए समर्थन छोड़ने (उन्होंने कुछ 3 साल पहले अजगर 2 समर्थन को गिरा दिया!)। इसके अलावा, मैक पर उल्लिखित पुस्तकालयों को स्थापित करना एक दर्द था।

अंत में, मुझे सबसे अच्छा समाधान मिला svglib + reportlab । दोनों ने एक अड़चन के बिना पाइप का उपयोग करके स्थापित किया और svg से png में परिवर्तित होने के लिए पहली कॉल को खूबसूरती से काम किया! समाधान से बहुत खुश हैं।

बस 2 आदेशों की चाल है:

from svglib.svglib import svg2rlg
from reportlab.graphics import renderPM
drawing = svg2rlg("my.svg")
renderPM.drawToFile(drawing, "my.png", fmt="PNG")

क्या इन सीमाओं से मुझे अवगत होना चाहिए?


हाँ, मार्कर-एंड समर्थित नहीं है, और नहीं होगा, github.com/deeplook/svglib/issues/177
Rainald62

2

एसवीजी स्केलिंग और पीएनजी प्रतिपादन

पाइकाइरो और लाइब्र्सवग का उपयोग करना मैं SVG स्केलिंग और एक बिटमैप को प्रदान करने में सक्षम था। अपने एसवीजी को 256x256 पिक्सेल, वांछित आउटपुट नहीं मानते हुए, आप SVG में rsvg का उपयोग करके काहिरा के संदर्भ में पढ़ सकते हैं और फिर इसे स्केल करके 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 बाइंडिंग

कुछ मामूली संशोधन के साथ कारियो वेबसाइट से। पायथन से सी-लाइब्रेरी को कैसे कॉल करें, इसका भी एक अच्छा उदाहरण है

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)

इसके लिए धन्यवाद, यह मेरी एक परियोजना में बहुत उपयोगी साबित हुआ। हालांकि Handle.get_dimension_dataमेरे लिए काम नहीं किया। मैं का एक सरल प्राप्त कर रहा है के साथ बदलना पड़ा self.props.widthऔर self.props.height। मैंने पहली बार RsvgDimensionDataकाइरो वेबसाइट पर वर्णित संरचना को परिभाषित करने की कोशिश की , लेकिन सफलता के बिना।
जीन ऑलिवियर

मैं इसे एक परियोजना में उपयोग करने की कोशिश कर रहा हूं। मुझे आवश्यक dll फ़ाइलों को कैसे प्राप्त करना चाहिए?
एंडू

0

यहाँ एक दृष्टिकोण है जहाँ Inkscape को पायथन ने बुलाया है।

ध्यान दें कि यह कुछ गंभीर उत्पादन को दबा देता है जो इंकस्केप सामान्य त्रुटि-मुक्त ऑपरेशन के दौरान कंसोल (विशेष रूप से, stderr और stdout) को लिखता है। आउटपुट दो स्ट्रिंग चर में कैप्चर किया गया है, outऔर err

import subprocess               # May want to use subprocess32 instead

cmd_list = [ '/full/path/to/inkscape', '-z', 
             '--export-png', '/path/to/output.png',
             '--export-width', 100,
             '--export-height', 100,
             '/path/to/input.svg' ]

# Invoke the command.  Divert output that normally goes to stdout or stderr.
p = subprocess.Popen( cmd_list, stdout=subprocess.PIPE, stderr=subprocess.PIPE )

# Below, < out > and < err > are strings or < None >, derived from stdout and stderr.
out, err = p.communicate()      # Waits for process to terminate

# Maybe do something with stdout output that is in < out >
# Maybe do something with stderr output that is in < err >

if p.returncode:
    raise Exception( 'Inkscape error: ' + (err or '?')  )

उदाहरण के लिए, मेरे मैक ओएस सिस्टम पर एक विशेष कार्य चलाने पर, outसमाप्त हो रहा है:

Background RRGGBBAA: ffffff00
Area 0:0:339:339 exported to 100 x 100 pixels (72.4584 dpi)
Bitmap saved as: /path/to/output.png

(इनपुट svg फ़ाइल का आकार 339 पिक्सल 339 था।)


यदि आप इंकस्केप पर भरोसा करते हैं तो यह एंड-टू-एंड पायथन नहीं है।
जोएल

1
@ जॉयल: आपकी आपत्ति को दूर करने के लिए पहली पंक्ति को संशोधित किया गया है। लेकिन निश्चित रूप से, यहां तक ​​कि एक "शुद्ध" पायथन समाधान मूल भाषा के बाहर के तत्वों पर निर्भर करता है, और अंततः मशीन भाषा के साथ चलाया जाता है, इसलिए शायद अंत-टू-एंड जैसी कोई चीज नहीं है!
आयरन तकिया

0

वास्तव में, मैं किसी और चीज़ पर निर्भर नहीं रहना चाहता था, लेकिन पायथन (काहिरा, इंक .. आदि) मेरी आवश्यकताओं को जितना संभव हो उतना सरल होना चाहिए, कम से कम, एक सरल pip install "savior"पर्याप्त होगा, यही कारण है कि उपर्युक्त में से कोई भी नहीं ' मेरे लिए टी सूट

मैं इसके माध्यम से आया था (अनुसंधान पर स्टैकओवरफ़्लो से आगे जा रहा था)। https://www.tutorialexample.com/best-practice-to-python-convert-svg-to-png-with-svglib-python-tutorial/

अच्छा लग रहा है, अब तक। इसलिए मैं इसे उसी स्थिति में किसी को भी साझा करता हूं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.