我想知道是否有可能加载svg格式,比如shape和with循环来重复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格式并与其他模块一起使用吗?
提前感谢!
发布于 2022-07-22 10:34:40
需求
Skia
Google,Android,Flutter等使用开源的2D图形库Skia,其中也有Python绑定。
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绘图是在透明的背景下完成的。
但是,JPEG不支持透明性。您可以使用RBGA
将图像从具有透明度的类型( .convert('RGB')
)转换为没有透明度的类型。但在这种情况下,黑色背景上将有黑色元素。转换时,可以在预置的背景下创建新图像,并将透明图像粘贴到图像中。
自带的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图像。
发布于 2022-07-22 10:59:03
我知道这个问题被标记为ImageMagick-based,但是我提供了一个python
的答案,因为:
请注意,如果您希望看到一些示例,可以通过将wand
放入[wand]
搜索框中,找到标记为StackOverflow的问题和答案。
因此,如果将SVG保存在名为image.svg
的文件中,则可以在终端(Linux/macOS)或命令提示符(Windows)中运行以下ImageMagick命令:
magick -background none image.svg -write mpr:tile +delete \
-size 400x200 tile:mpr:tile result.gif
或者:
magick -background yellow image.svg -write mpr:tile +delete \
-size 400x200 tile:mpr:tile result.gif
或者,如果你想要一个特定数量的拷贝,比如21张“toto”重复的每一行3张图像:
magick -background magenta image.svg -duplicate 20 miff: | magick montage -tile 3x -geometry +0+0 miff:- result.gif
或20 "in toto",间隔稍小,排列成2排:
magick -background cyan image.svg -duplicate 19 miff: | magick montage -background cyan -tile x2 -geometry +5+5 miff:- result.gif
如果在上面的命令中有一个旧的ImageMagick,,则需要:
magick montage
替换为montage
,并且magick
替换为convert
请注意,有很多有趣的材料关于瓷砖/重复背景安东尼蒂森这里。
https://stackoverflow.com/questions/73013439
复制相似问题