gpt4 book ai didi

python - 如何结合 PIL 和 cairosvg 从 svg 创建模式?

转载 作者:行者123 更新时间:2023-12-05 03:21:16 26 4
gpt4 key购买 nike

我想知道是否可以加载像形状这样的 svg 格式并使用循环重复使用 for 循环以获得某种通用模式。我在网上进行的大部分研究都是从 svg 转换为 png 或其他格式,但我想知道是否可以在转换为某种格式 (jpg) 之前进行操作?

我曾尝试结合 cairosvg 和 PIL,但我没有走得太远。

from cairosvg import svg2png
from PIL import Image, ImageDraw

white = (255,255,255)
img = Image.new('RGB', (300,300), white)
draw = ImageDraw.Draw(img)

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

通常我会用这样的东西......

for x in range(0, 300, 25):
draw.svg_code??

但这不起作用...知道如何加载 svg 格式并将其与其他模块一起使用吗?

提前致谢!

最佳答案

要求

  • 加载 svg 格式的形状
  • 创建背景图案
  • 在使用 PIL 转换为 jpg 之前进行操作

斯基亚

Google Chrome、Android、Flutter 和其他使用开源 2D 图形库 Skia,它也有一个 Python 绑定(bind)。

Skia 允许创建一个带有平铺模式规则的着色器来填充绘制区域。另外可以提供一个矩阵,它允许例如。回转。优点是即使目标图像很大并且构成图案的元素数量非常多,这也能非常有效地执行。

因此可以很容易地创建这样的模式,例如使用以下代码:

def pattern(canvas, image_element, rotation):
matrix = skia.Matrix()
matrix.preRotate(rotation)
canvas.drawPaint({
'Shader': image_element.makeShader(
skia.TileMode.kRepeat,
skia.TileMode.kRepeat,
matrix,
)
})

所以一个完整的方法可能是这样的:

  • 将 SVG 字符串(或文件)转换为具有适当大小的 Skia 图像
  • 创建图案作为背景
  • 通过绘制矩形/文本等其他元素来操纵它
  • 将其转换为PIL图像并保存

许多用例的一个重要特征是 SVG 绘图是在透明背景上完成的。

但是,JPEG 不支持透明度。您可以使用 .convert('RGB') 将图像从具有透明度的类型 (RBGA) 转换为不具有透明度的类型。但在这种情况下,黑色背景上会有黑色元素。转换时,可以使用背景预设创建新图像并将透明图像粘贴到其中。

独立的 Python 示例

考虑到以上几点的自包含示例可能类似于以下程序。

它只是根据您的 SVG 示例创建一个图案,并在其上的灰色矩形上绘制红色文本。它输出两个图像:一个是所需的 JPEG 图像,另一个是 PNG 图像,以便能够显示提到的透明度选项。

import io
import skia
from PIL import Image


def image_from_svg(svg, element_size):
stream = skia.MemoryStream()
stream.setMemory(bytes(svg, 'UTF-8'))
svg = skia.SVGDOM.MakeFromStream(stream)
width, height = svg.containerSize()
surface = skia.Surface(element_size, element_size)
with surface as canvas:
canvas.scale(element_size / width, element_size / height)
svg.render(canvas)
return surface.makeImageSnapshot()


def pattern_image_with_title(image_element, width, height, rotation, title):
surface = skia.Surface(width, height)
with surface as canvas:
pattern(canvas, image_element, rotation)
rectangle(canvas, width)
draw_title(canvas, title)
return surface.makeImageSnapshot()


def draw_title(canvas, title):
paint = skia.Paint(AntiAlias=True, Color=skia.ColorRED)
canvas.drawString(title, 48, 76, skia.Font(None, 32), paint)


def rectangle(canvas, width):
rect = skia.Rect(32, 32, width - 32, 96)
paint = skia.Paint(
Color=skia.ColorGRAY,
Style=skia.Paint.kFill_Style)
canvas.drawRect(rect, paint)


def pattern(canvas, image_element, rotation):
matrix = skia.Matrix()
matrix.preRotate(rotation)
canvas.drawPaint({
'Shader': image_element.makeShader(
skia.TileMode.kRepeat,
skia.TileMode.kRepeat,
matrix,
)
})


def write_png(file_name, skia_image):
with io.BytesIO(skia_image.encodeToData()) as f:
pil_image = Image.open(f)
pil_image.save(file_name, 'PNG')


def write_jpeg(file_name, skia_image, background):
with io.BytesIO(skia_image.encodeToData()) as f:
pil_image = Image.open(f)
new_image = Image.new("RGBA", pil_image.size, background)
new_image.paste(pil_image, (0, 0), pil_image)
new_image = new_image.convert('RGB')
new_image.save(file_name, 'JPEG')


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

if __name__ == "__main__":
img = image_from_svg(svg_code, 50)
img = pattern_image_with_title(img, 300, 300, 45, 'hello world!')
write_png('result.png', img)
write_jpeg('result.jpg', img, 'WHITE')

结果

作为上述程序的结果,您会得到两张图片。左边是白色背景的 JPEG 图片,右边是透明的 PNG 图片。

example result

关于python - 如何结合 PIL 和 cairosvg 从 svg 创建模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73013439/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com