Python에서 SVG를 PNG로 변환
을 어떻게 합니까?svg
png
파이썬에서?저장 중입니다.svg
를 들어StringIO
제가 파이카이로 도서관을 이용해야 하나요?그 코드를 어떻게 작성합니까?
다음은 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 문서
정답은 "pyrsvg" - librsvg를 위한 파이썬 바인딩입니다.
이를 제공하는 Ubuntu python-rsvg 패키지가 있습니다.구글의 소스 코드가 "gnome-python-desktop" GIT 저장소에 포함되어 있는 것처럼 보이기 때문에 구글의 이름을 검색하는 것은 좋지 않습니다.
저는 SVG를 카이로 표면에 렌더링하고 디스크에 쓰는 미니멀리스트 "헬로 월드"를 만들었습니다.
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년 기준으로 Fedora Linux 배포에 필요한 패키지는 다음과 같습니다.gnome-python2-rsvg
위의 스니펫 목록은 여전히 그대로 작동합니다.
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 파일에 하나의 개체만 표시하려면 매개 변수를 지정할 수 있습니다.-i
사용자가 SVG에 설정한 개체 ID를 사용합니다.그것은 다른 모든 것을 숨깁니다.
${INKSCAPE_PATH} -z -f ${source_svg} -w ${width} -i ${object} -j -a ${coordinates} -e ${dest_png}
저는 꽤 발전된 SVG를 가져오기 위해 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:
정말 필요한 것은 그것뿐이었습니다.
편집: 큐리스가 시도한 편집에서 배경이 투명한 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)
저는 만족스러운 답을 찾지 못했습니다.언급된 모든 라이브러리는 카이로와 같은 몇 가지 문제가 있습니다. 파이썬 3.6에 대한 지원을 중단합니다. (그들은 약 3년 전에 파이썬 2 지원을 중단했습니다!)또한, 언급된 라이브러리를 맥에 설치하는 것은 고통스러웠습니다.
마지막으로 최고의 솔루션은 svglib + reportlab이었습니다.pip과 svg에서 png으로 변환하는 first call을 사용하여 문제없이 설치된 둘 다 잘 작동했습니다!솔루션에 매우 만족합니다.
두 가지 명령만 실행하면 됩니다.
from svglib.svglib import svg2rlg
from reportlab.graphics import renderPM
drawing = svg2rlg("my.svg")
renderPM.drawToFile(drawing, "my.png", fmt="PNG")
제가 알아야 할 제한 사항이 있습니까?
사용해 보십시오. http://cairosvg.org/
이 사이트에는 다음과 같은 내용이 있습니다.
카이로 SVG는 순수 파이썬으로 작성되었으며 Pycairo에만 의존합니다.파이썬 2.6과 2.7에서 작동하는 것으로 알려져 있습니다.
2.0.0은 새로운 메이저 버전이며 변경 로그에는 다음이 포함됩니다.
- Python 2 지원 중단
여기서 찾은 또 다른 솔루션 스케일 SVG를 QI 이미지로 렌더링하는 방법은 무엇입니까?
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 파서/렌더링러는 아닐 것입니다.
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)
다음은 rsvg를 사용하지 않는 다른 솔루션입니다(현재 윈도우즈에서는 사용할 수 없음).를 사용하여 합니다.pip install CairoSVG
svg2png.py
from cairosvg import svg2png
svg_code = open("input.svg", 'rt').read()
svg2png(bytestring=svg_code,write_to='output.png')
SVG 스케일링 및 PNG 렌더링
pycairo 및 librsvg를 사용하여 SVG 스케일링 및 비트맵 렌더링을 수행할 수 있었습니다.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')
RSVGC 바인딩
카리오 웹사이트에서 약간의 수정 사항이 있습니다.또한 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)
다음은 Python이 Inkscape를 호출하는 접근 방식입니다.
오류가 없는 정상 작동 중에 Inkscape가 콘솔(특히 stderr 및 stdout)에 쓰는 특정 Cruft 출력을 억제합니다.은 두 인 출은두개문변캡처다니됩으로 캡처됩니다.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 '?') )
시스템에서 할 때 "Mac OS 파일"을 합니다.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 x 339 픽셀이었습니다.)
다음 파이썬 스크립트를 사용해 보십시오.
cairosvg를 설치하는 것을 pip3 install cairosvg
#!/usr/bin/env python3
import os
import cairosvg
for file in os.listdir('.'):
if os.path.isfile(file) and file.endswith(".svg"):
name = file.split('.svg')[0]
cairosvg.svg2png(url=name+'.svg',write_to=name+'.png')
Gtk를 사용해 보십시오.이미지 및 Gdk.픽스버프
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gdk, Gtk
from PIL import Image
image = Gtk.Image()
image.set_from_file("path/to/image.svg")
pb = image.get_pixbuf()
pb.savev("path/to/convented/image.jpeg","jpeg",[],[])
im = Image.open("path/to/convented/image.jpeg")
pix = im.load()
print(pix[1,1])
이 StackOverflow 응답에서 내 코드를 게시하는 중입니다.하기 위한 해결책입니다.svglib
+reportlib
투명한 배경과 스케일링을 지원하지 않음(스케일링이 작동하지 않음에 대한 Github 문제와 투명성에 대한 이 문제뿐만 아니라 @sarang의 답변 및 @ualter-jr의 답변 참조)
이 기능은 다음과 같습니다.pyMuPDF
중pdf를에서 중간 .reportlab
PNG로.
가장 큰 장점은 외부 라이브러리가 필요하지 않다는 것입니다.pymupdf
Windows, Linux 및 MacOS용으로 사전 컴파일된 휠이 함께 제공됩니다.
모든 것은 매우 쉽습니다.
pip install pymupdf svglib
그런 다음 다음 다음 행을 실행합니다.
import fitz
from svglib import svglib
from reportlab.graphics import renderPDF
# Convert svg to pdf in memory with svglib+reportlab
# directly rendering to png does not support transparency nor scaling
drawing = svglib.svg2rlg(path="input.svg")
pdf = renderPDF.drawToString(drawing)
# Open pdf with fitz (pyMuPdf) to convert to PNG
doc = fitz.Document(stream=pdf)
pix = doc.load_page(0).get_pixmap(alpha=True, dpi=300)
pix.save("output.png")
사실 저는 파이썬(카이로, 잉크 등) 외에 다른 것에 의존하고 싶지 않았습니다.제 요구사항은 가능한 한 단순하고, 기껏해야 단순한 것이었습니다.pip install "savior"
충분할 것 같습니다, 그래서 위에 있는 것들 중 어떤 것도 저에게 맞지 않았습니다.
저는 (연구에서 스택 오버플로보다 더 멀리) 이것을 극복했습니다.https://www.tutorialexample.com/best-practice-to-python-convert-svg-to-png-with-svglib-python-tutorial/
좋아 보이네요, 지금까지는.그래서 같은 상황에 처한 사람이 있을 경우를 대비해 공유합니다.
여기에 있는 모든 답은 훌륭하지만 SVG의 파일을 베개 이미지 인스턴스로 로드하는 간단한 라이브러리를 만들어 내보냈습니다.blj의 답변처럼 잉크스케이프를 사용하지만 임시 파일이 만들어지지 않도록 stdout으로 렌더링합니다.README에는 몇 가지 기본적인 사용법이 있습니다.
https://github.com/jlwoolf/pillow-svg
편집:
제안된 대로 링크가 비활성화될 수 있으므로 다음은 간단한 설명입니다.
라이브러리는 python 하위 프로세스 라이브러리를 사용하여 이미지를 특정 크기의 png 또는 dpi로 변환하기 위해 잉크스케이프의 명령줄 인터페이스를 사용합니다.설정별--export-filename
-
inkscape는 출력을 stdout으로 리디렉션합니다.처음 두 줄은 폐기되고 나머지 출력은 다음으로 전달됩니다.PIL.Image.open
베개 이미지 인스턴스로 변환하는 중입니다.
import subprocess
from PIL import Image
options = ["inkscape", "--export-filename=-", "--export-type=png", "file.svg"]
pipe = subprocess.Popen(options, stdout=subprocess.PIPE)
pipe.stdout.readline()
pipe.stdout.readline()
img = Image.open(pipe.stdout)
여기서 필요한 베개 이미지 작업(예: jpg로 내보내기, 크기 조정, 자르기 등)을 수행할 수 있습니다.
2 편집 2:
방금 스키아-피톤에 대한 지원을 추가했습니다(완전히 테스트하지는 않았지만, 지금까지 작동하는 것으로 보입니다).이렇게 하면 한 번의 pip 설치만으로 svg를 png으로 변환할 수 있습니다(잉크스케이프를 사용할 필요가 없습니다).
다음은 라이브러리가 스키아피톤을 사용하는 방법에 대한 설명입니다.
을 svg 파일로 합니다.skia.SVGDOM
여기서있수다습의니수악을 할 수 .containerSize
그면러.skia.Surface
원하는 이미지 출력 크기가 생성됩니다.캔버스의 크기가 svg를 표면에 맞게 조정된 다음 svg가 렌더링됩니다.여기서 이미지 스냅샷을 만들 수 있으며, 이 스냅샷은 다음으로 전송될 수 있습니다.PIL.Image.open
.
import skia
from PIL import Image
skia_stream = skia.Stream.MakeFromFile("file.svg")
skia_svg = skia.SVGDOM.MakeFromStream(skia_stream)
svg_width, svg_height = skia_svg.containerSize()
surface_width, surface_height = 512, 512
surface = skia.Surface(surface_width, surface_height)
with surface as canvas:
canvas.scale(surface_width / svg_width, surface_height / svg_height)
skia_svg.render(canvas)
with io.BytesIO(surface.makeImageSnapshot().encodeToData()) as f:
img = Image.open(f)
img.load()
3편집 3:
저는 도서관을 훨씬 더 살찌웠습니다.이제 사용법을 설명하는 더 많은 문서와 함께 svg 변환을 쉽게 할 수 있는 명령줄 유틸리티가 있습니다.도움이 되길 바랍니다!
언급URL : https://stackoverflow.com/questions/6589358/convert-svg-to-png-in-python
'programing' 카테고리의 다른 글
중첩 함수는 하나의 함수에만 필요할 때 좋은 접근 방식입니까? (0) | 2023.07.19 |
---|---|
파이썬 람다 식에 여러 개의 문을 가질 수 있습니까? (0) | 2023.07.19 |
파이썬에서 멀티프로세싱 큐를 사용하는 방법은 무엇입니까? (0) | 2023.07.19 |
파이썬에서 열거형에 대한 일반적인 관행은 무엇입니까? (0) | 2023.07.19 |
이미지를 PIL에서 개방형 CV 형식으로 변환 (0) | 2023.07.19 |