আমি কিভাবে একটি রূপান্তর করবেন svg
করতে png
, পাইথন মধ্যে? আমি svg
একটি উদাহরণে স্টোর করছি StringIO
। আমার পাইকাইরো লাইব্রেরি ব্যবহার করা উচিত? আমি কীভাবে এই কোডটি লিখব?
আমি কিভাবে একটি রূপান্তর করবেন svg
করতে png
, পাইথন মধ্যে? আমি svg
একটি উদাহরণে স্টোর করছি StringIO
। আমার পাইকাইরো লাইব্রেরি ব্যবহার করা উচিত? আমি কীভাবে এই কোডটি লিখব?
উত্তর:
উত্তরটি " পাইর্সভিগ " - লিবারসভিগের জন্য পাইথন বাইন্ডিং ।
এটি সরবরাহ করে একটি উবুন্টু পাইথন-আরএসভিজি প্যাকেজ রয়েছে। গুগল এর নামের জন্য অনুসন্ধান করা দুর্বল কারণ এর উত্স কোডটি "জিনোম-পাইথন-ডেস্কটপ" জিনোম প্রকল্প জিআইটি সংগ্রহস্থলের ভিতরে রয়েছে বলে মনে হচ্ছে।
আমি একটি মিনিমালিস্ট "হ্যালো ওয়ার্ল্ড" তৈরি করেছি যা এসভিজি কে কায়রো পৃষ্ঠে রেন্ডার করে এবং এটি ডিস্কে লিখে দেয়:
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
তার নিজের থেকে ছবির উচ্চতা এবং প্রস্থটি নির্ধারণ করার কোনও উপায় আছে কি? *.svg
সেখান থেকে উচ্চতা এবং প্রস্থটি বের করতে আমি ফাইলটি দেখেছি , তবে এটি উভয়ই সেট করা আছে 100%
। অবশ্যই, আমি ছবির বৈশিষ্ট্যগুলি খতিয়ে দেখতে পারি, তবে যেহেতু ইমেজ প্রসেসিংয়ের এটি কেবলমাত্র একটি পদক্ষেপ এটি আমি চাই না।
.get_dimension_data()
পদ্ধতি রয়েছে যা আমার উদাহরণ ফাইলের জন্য কাজ করেছে (একটি ভাল আচরণ করা এসভিজি) - চেষ্টা করে দেখুন।
কায়রোসভিগ ব্যবহার করে আমি এখানে যা করেছি :
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')
এবং এটি একটি মোহন মত কাজ করে!
আরও দেখুন: কায়রোসভিগ ডকুমেন্ট
svg2png
কোনও stream
অবজেক্টে নিয়ে যায় এবং এটি write_to
হয় আপনার এইচটিটিপি রেসপন্স অবজেক্ট (যা এতে আছে) বেশিরভাগ ফ্রেমওয়ার্কগুলি কোনও ফাইলের মতো বস্তু) বা অন্য কোনও স্ট্রিম হয়, যা আপনি পরে 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_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}
আমি বেশ কিছু উন্নত এসভিজি আমদানি করতে ওয়ান্ড- পাই (ইমেজম্যাগিকের চারপাশে ওয়ান্ড র্যাপারের প্রয়োগ) ব্যবহার করছি এবং এখনও পর্যন্ত দুর্দান্ত ফলাফল দেখেছি! এটি যা লাগে তা সমস্ত কোড:
with wand.image.Image( blob=svg_file.read(), format="svg" ) as image:
png_image = image.make_blob("png")
আমি আজই এটি আবিষ্কার করেছি এবং অনুভব করেছি যে এটি যে কারও পক্ষে ভাগ করে নেওয়া উচিত যারা এই উত্তরটি আটকে দিতে পারে কারণ বেশিরভাগ সময় এই প্রশ্নের উত্তর পাওয়া গেছে।
দ্রষ্টব্য: প্রযুক্তিগতভাবে পরীক্ষার সময় আমি আবিষ্কার করেছি যে এমনকি আপনাকে চিত্রম্যাগিকের ফর্ম্যাট প্যারামিটারেও পাস করতে হবে না, তাই with wand.image.Image( blob=svg_file.read() ) as image:
যা ছিল সত্যই প্রয়োজন ছিল।
সম্পাদনা: কুরিস দ্বারা সম্পাদিত চেষ্টা করার থেকে, এখানে এমন কিছু সহায়ক কোড যা আপনাকে স্বচ্ছ পটভূমিতে থাকা একটি এসভিজির সাথে চিত্রম্যাগিক ব্যবহার করতে দেয়:
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
'গ্রহণ' পদ্ধতি আমার PDF এর জন্য কাজ করে নি। pip install wand
এবং আপনার স্নিপেটটি কৌশলটি করেছে;)
str
তারপর আপনি প্রথমে এই মত বাইনারি এনকোড করেন প্রয়োজন: svg_blob = svg_str.encode('utf-8')
। এখন আপনি প্রতিস্থাপন করে উপরের পদ্ধতি ব্যবহার করতে পারেন blob=svg_file.read()
সঙ্গে blob=svg_blob
।
এটি ব্যবহার করে দেখুন: http://cairosvg.org/
সাইটটি বলে:
কায়রোএসভিজি খাঁটি অজগরে লেখা এবং এটি কেবল পাইকারোর উপর নির্ভর করে। এটি পাইথন ২.6 এবং ২.7 এ কাজ করার জন্য পরিচিত।
25 নভেম্বর, 2016 আপডেট করুন :
২.০.০ একটি নতুন প্রধান সংস্করণ, এর চেঞ্জলগ অন্তর্ভুক্ত:
- পাইথন 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()
পাইসাইড উইন্ডোজের বাইনারি প্যাকেজ থেকে সহজেই ইনস্টল করা হয় (এবং আমি এটি অন্যান্য জিনিসের জন্যও ব্যবহার করি তাই আমার পক্ষে সহজ)।
তবে, উইকিমিডিয়া থেকে দেশের পতাকা রূপান্তর করার সময় আমি কয়েকটি সমস্যা লক্ষ্য করেছি, তাই সম্ভবত সবচেয়ে শক্তিশালী এসভিজি পার্সার / রেন্ডারার নয়।
জসবুয়েনোর উত্তরে একটু বাড়ানো:
#!/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 + রিপোর্টল্যাব । উভয়ই পিচ ব্যবহার না করে একটি হাইচ ছাড়া ইনস্টল করেছেন এবং এসভিজি থেকে পিএনজি রূপান্তর করতে প্রথম কলটি সুন্দরভাবে কাজ করেছেন! সমাধান নিয়ে খুব খুশি।
মাত্র 2 কমান্ড কৌশলটি করেন:
from svglib.svglib import svg2rlg
from reportlab.graphics import renderPM
drawing = svg2rlg("my.svg")
renderPM.drawToFile(drawing, "my.png", fmt="PNG")
এগুলি সম্পর্কে আমার কি সীমাবদ্ধতা অবহিত হওয়া উচিত?
পাইকারো এবং লিবারসভিগ ব্যবহার করা আমি এসভিজি স্কেলিং অর্জন করতে এবং বিটম্যাপে রেন্ডারিং করতে সক্ষম হয়েছি। ধরে নিই যে আপনার এসভিজি ঠিক 256x256 পিক্সেল নয়, কাঙ্ক্ষিত আউটপুট, আপনি এসভিজিতে আরএসভিজি ব্যবহার করে একটি কায়রো প্রসঙ্গে পড়তে পারেন এবং তারপরে স্কেল করে এবং কোনও পিএনজিতে লিখতে পারেন।
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
কায়রো ওয়েবসাইটে বর্ণিত স্ট্রাকচারটি সংজ্ঞায়নের চেষ্টা করেছি , তবে সাফল্য ছাড়াই।
এখানে একটি অ্যাপ্রোচ দেওয়া আছে যেখানে ইনকস্কেপকে পাইথন বলে।
নোট করুন যে এটি কিছু নির্দিষ্ট ক্রুফিট আউটপুটকে দমন করে যা সাধারণ ত্রুটিমুক্ত অপারেশনের সময় ইনসকাপ কনসোলে (বিশেষত স্ট্যাডার এবং স্টাডআউট) লিখেছিল। আউটপুট দুটি স্ট্রিং ভেরিয়েবল 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
(ইনপুট এসভিজি ফাইলটির আকার 339 বাই 339 পিক্সেল ছিল))
আসলে, আমি পাইথন (কায়রো, কালি .. ইত্যাদি) ব্যতীত অন্য কোনও কিছুর উপর নির্ভরশীল হতে চাইনি আমার প্রয়োজনীয়তাগুলি যতটা সম্ভব সহজ হতে হবে, সর্বাধিক, সরল ছিল pip install "savior"
হতে হবে, যথেষ্ট ছিল, এই কারণেই উপরোক্তদের মধ্যে কেউই করেনি ' আমার জন্য টি মামলা।
আমি এটির মাধ্যমে এসেছি (গবেষণায় স্ট্যাকওভারফ্লো থেকে আরও এগিয়ে)। https://www.tutorialexample.com/best-pੈਕਟ-to-python-convert-svg-to-png-with-svglib-python-tutorial/
দেখতে এখন পর্যন্ত খুব ভাল লাগছে। সুতরাং আমি একই পরিস্থিতিতে কেউ যদি এটি ভাগ।