如何在 Windows 10 (vscode) 上使用 python 3.6.5 在限制比例的同时调整 svg 的大小

how to resize svgs while constraining proportions using python 3.6.5 on Windows 10 (vscode)

我正在尝试缩小一些默认为 420 x 500 像素的 SVG,它们的尺寸并不完全相同,但我想在输出文件上保持 50 像素的宽度。

这是我到目前为止所管理的(来自 this):

import os
import svgutils


path = 'path/to/files'
svg_files = [f for f in os.listdir(path) if f.endswith('.svg')]

for i in svg_files:
    svg_file = os.path.join(path, i)
    svg = svgutils.transform.fromfile(svg_file)
    original = svgutils.compose.SVG(svg_file)
    original.scale(.1)
    svg_out = os.path.splitext(svg_file)[0] + '_scale.svg'
    new_svg = svgutils.compose.Figure(float(svg.height) * .1,
                                      float(svg.width) * .1, original)
    new_svg.save(svg_out)

但它只添加了带有变换的 <g>,并没有调整原始文件的大小。而且,最终结果不会在inkscape中打开。

知道我做错了什么吗?

编辑:

我仔细查看了一下,到目前为止,我已经设法使用 this sourceforge project 中的 librsvg-2.40.1-2-w32-bin.zip 调整了 svg 的大小,并将 /bin 文件夹添加到 windows 路径,这允许我执行以下操作:

rsvg-convert -a ".\infile.svg" -w "30" -f svg -o ".\outfile.svg"

但是,没有颜色信息被保留。所以我到目前为止。

编辑 2:

颜色问题发生在使用rsvg-convert的转换过程中,似乎它也在这个过程中将十六进制转换为rgb元组。部分查看器不支持(如MapboxGL studio)

这是我目前得到的一些东西:

# scale SVG images from files

import os
import re
import svgutils as su

SCALE = .1
path = 'E:/Slicke/Sitne'
svg_files = [f for f in os.listdir(path) if f.endswith('.svg')]

for i in svg_files:
    svg_file = os.path.join(path, i)

    # Get SVGFigure from file
    original = su.transform.fromfile(svg_file)

    # Original size is represetnted as string (examle: '600px'); convert to float
    original_width = float(re.sub('[^0-9]','', original.width))
    original_height = float(re.sub('[^0-9]','', original.width))

    scaled = su.transform.SVGFigure(original_width * SCALE, original_height * SCALE,)
    # Get the root element
    svg = original.getroot()

    # Scale the root element
    svg.scale_xy(SCALE, SCALE)

    # Add scaled svg element to figure
    scaled.append(svg)
    # Create the path and new file name
    svg_out = os.path.splitext(svg_file)[0] + '_scale.svg'
    print(svg_out)
    scaled.save(svg_out)

经过一番折腾,我终于成功了。虽然解决方案相当肮脏,但它完成了工作。

解决方法如下:

import os
import re
import subprocess
from webcolors import rgb_percent_to_hex

path = 'path/to/svgs'
svg_files = [f for f in os.listdir(path) if f.endswith('.svg')]

def cs(s): return rgb_percent_to_hex((s.group(1), s.group(2), s.group(3)))

# scaling the files
for i in svg_files:
    file_path = os.path.join(path, i)
    svg_path = os.path.splitext(file_path)[0] + '_scaled.svg'
    subprocess.call([
                    'rsvg-convert',
                    '-a',
                    file_path,
                    '-w', '30',
                    '-f', 'svg',
                    '-o', svg_path])

scaled_files = [f for f in os.listdir(path) if f.endswith('_scaled.svg')]
exp = r'rgb\((?:(?P<red>\d{1,3}.?(?:\d{1,50}\%)?)(?:\,?)(?P<green>\d{1,3}.?(?:\d{1,50}\%)?)(?:\,?)(?P<blue>\d{1,3}.?(?:\d{1,50}\%)?)(?:))\)'

for j in scaled_files:
    w = open(os.path.splitext(os.path.join(path, j))[0] + '_hexed.svg', 'w')
    r = open(os.path.join(path, j))
    for l in r:
        w.write(re.sub(exp, cs, l))
    w.close()
    r.close()