मैं किसी को परिवर्तित करना svg
करने के लिए png
, अजगर में? मैं svg
एक उदाहरण में संग्रहीत कर रहा हूँ StringIO
। क्या मुझे पाइकाइरो लाइब्रेरी का उपयोग करना चाहिए? मैं उस कोड को कैसे लिखूं?
मैं किसी को परिवर्तित करना svg
करने के लिए png
, अजगर में? मैं svg
एक उदाहरण में संग्रहीत कर रहा हूँ StringIO
। क्या मुझे पाइकाइरो लाइब्रेरी का उपयोग करना चाहिए? मैं उस कोड को कैसे लिखूं?
जवाबों:
जवाब " 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
। उपरोक्त स्निपेट सूची अभी भी काम करती है।
cairo
तस्वीर के HEIGHT और WIDTH को अपने आप निर्धारित करने का कोई तरीका है ? मैंने *.svg
फ़ाइल को देखा है , वहां से HEIGHT और WIDTH निकालने के लिए, लेकिन यह दोनों पर सेट है 100%
। बेशक, मैं तस्वीर के गुणों को देख सकता हूं, लेकिन चूंकि यह छवि प्रसंस्करण में केवल एक कदम है, यह वह नहीं है जो मैं चाहता हूं।
.get_dimension_data()
विधि है जो मेरे उदाहरण फ़ाइल (एक अच्छी तरह से व्यवहार किए गए SVG) के लिए काम करती है - इसे आज़माएं।
यहाँ मैं 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 दस्तावेज़
svg2png
में कोई stream
ऑब्जेक्ट लेता है write_to
, और यह या तो आपकी HTTP रिस्पांस ऑब्जेक्ट हो सकता है (जो में है) अधिकांश चौखटे एक फ़ाइल की तरह वस्तु) या कुछ अन्य स्ट्रीम है, जो आप तब Content-Disposition
हेडर का उपयोग करके ब्राउज़र में सेवा करते हैं । यहाँ देखें: stackoverflow.com/questions/1012437/…
bytestring
बाइट्स स्वीकार करता है, इसलिए पहले स्ट्रिंग को bytestring=bytes(svg,'UTF-8')
2 से बदलें )। फ़ाइल मोड द्विआधारी होना चाहिए, इसलिएopen('output.png','wb')
svg2png
मेरे लिए नहीं था , मुझे इस्तेमाल करना था cairosvg.surface.PNGSurface.convert(svg_str, write_to='output.png')
।
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}
मैं कुछ सुंदर उन्नत 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)
image.read(blob=svg_file.read(), format="svg") NameError: name 'svg_file' is not defined
svg_file
इस उदाहरण में एक "फ़ाइल" ऑब्जेक्ट माना जाता है, सेटिंग svg_file
कुछ इस तरह दिखाई देगी:svg_file = File.open(file_name, "r")
cairo
और rsvg
'स्वीकृत' विधि मेरे पीडीएफ के लिए काम नहीं करती थी। pip install wand
और आपके स्निपेट ने चाल
str
उसके बाद आप पहली बार इस तरह द्विआधारी में एन्कोड करने की जरूरत है: svg_blob = svg_str.encode('utf-8')
। अब आप को बदल कर उपरोक्त विधि का उपयोग कर सकते blob=svg_file.read()
के साथ blob=svg_blob
।
इसे इस्तेमाल करे: http://cairosvg.org/
साइट कहती है:
काहोसिव्स शुद्ध अजगर में लिखा गया है और केवल पाइकाइरो पर निर्भर करता है। यह पायथन 2.6 और 2.7 पर काम करने के लिए जाना जाता है।
अपडेट 25 नवंबर, 2016 :
2.0.0 एक नया प्रमुख संस्करण है, इसके चैंज में शामिल हैं:
- पायथन 2 समर्थन को गिराएं
<clipPath><rect ... /></clipPath>
। दूसरा, यह -d (DPI) विकल्प नहीं लेता है।
एक और समाधान मैंने अभी यहां पाया है कि एक स्केल एसवीजी को क्यूमैज को कैसे प्रस्तुत किया जाए?
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 / रेंडरर नहीं।
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)
मुझे कोई भी उत्तर संतोषजनक नहीं लगा। सभी उल्लिखित पुस्तकालयों में कुछ समस्या है या अन्य जैसे अजगर 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")
क्या इन सीमाओं से मुझे अवगत होना चाहिए?
पाइकाइरो और लाइब्र्सवग का उपयोग करना मैं SVG स्केलिंग और एक बिटमैप को प्रदान करने में सक्षम था। अपने एसवीजी को 256x256 पिक्सेल, वांछित आउटपुट नहीं मानते हुए, आप SVG में rsvg का उपयोग करके काहिरा के संदर्भ में पढ़ सकते हैं और फिर इसे स्केल करके PNG को लिख सकते हैं।
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')
कुछ मामूली संशोधन के साथ कारियो वेबसाइट से। पायथन से सी-लाइब्रेरी को कैसे कॉल करें, इसका भी एक अच्छा उदाहरण है
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
काइरो वेबसाइट पर वर्णित संरचना को परिभाषित करने की कोशिश की , लेकिन सफलता के बिना।
यहाँ एक दृष्टिकोण है जहाँ 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 था।)
वास्तव में, मैं किसी और चीज़ पर निर्भर नहीं रहना चाहता था, लेकिन पायथन (काहिरा, इंक .. आदि) मेरी आवश्यकताओं को जितना संभव हो उतना सरल होना चाहिए, कम से कम, एक सरल pip install "savior"
पर्याप्त होगा, यही कारण है कि उपर्युक्त में से कोई भी नहीं ' मेरे लिए टी सूट
मैं इसके माध्यम से आया था (अनुसंधान पर स्टैकओवरफ़्लो से आगे जा रहा था)। https://www.tutorialexample.com/best-practice-to-python-convert-svg-to-png-with-svglib-python-tutorial/
अच्छा लग रहा है, अब तक। इसलिए मैं इसे उसी स्थिति में किसी को भी साझा करता हूं।