Python完成SVG转PNG格式

2021-07-15 18:03:47 浏览数 (1)

一、完成目标: 将SVG格式的图标转换为PNG格式的图标,并预览

二、任务分析:

  • svg是什么格式 :

svg格式的图像可任意放大图形显示,而且边缘异常清晰,生成的文件很小,方便传输,文字在svg图像中保留可编辑和可搜寻的状态,没有字体的限制

  • png是什么格式 :

PNG. ( 1996-10-01 ). 便携式网络图形 (英语: Portable Network Graphics , PNG )

是一种支持 无损压缩 的 位图 图形格式,支持索引、 灰度 、 RGB 三种颜色方案以及 Alpha通道 (透明度)等特性

三、运行环境说明

python解释器版本:python3.6

gui版本:PySide2 (其实用PyQt5也是一样的,只是部分调用方法改一下就行)

软件:PyCharm

四、用QtDesigner(Qt设计师)画出需要的界面(图标自己随便下喜欢的)

这是我设计的,具体界面什么样,可以随自己心意,这几个部件是必要有的这是我设计的,具体界面什么样,可以随自己心意,这几个部件是必要有的
这是 我给各个部件的命名这是 我给各个部件的命名

五、完整的SvgToPng.py代码展示

代码语言:javascript复制
import os
import PIL.Image as Image
from PySide2.QtCore import QStringListModel
from PySide2.QtGui import QPixmap
from PySide2.QtUiTools import QUiLoader
from PySide2.QtWidgets import QApplication, QFileDialog, QMessageBox
from reportlab.graphics import renderPM
from svglib.svglib import svg2rlg
from cairosvg import svg2png

class Stats:
    # 初始化
    def __init__(self):
        # 动态加载ui文件
        self.ui = QUiLoader().load('SvgToPng.ui')

        # 信号与槽链接
        self.ui.btn_file.clicked.connect(self.ChangeOne)
        self.ui.btn_files.clicked.connect(self.ChangeMore)
        self.ui.listView.clicked.connect(self.ShowMore)

        # 变量定义
        self.file_name = ''  # 选择的文件/文件夹
        self.save_file_name = ''  # 最终保存的文件夹位置
        self.image_name = ''

        self.file_paths = []  # 文件列表
        self.file_index = 0  # 文件索引
        self.file_num = ''  # 文件个数

    # 选择单个文件转换
    def ChangeOne(self):
        # 选择svg格式的文件
        self.file_name = QFileDialog.getOpenFileName(None, "选择文件", "/", "*.svg")
        self.file_name = str(self.file_name).split(',')[0].strip('(').replace("'", "")
        if self.file_name == '':
            QMessageBox.warning(
                self.ui,
                '提示',
                '未打开文件!')
        # 将打开文件路径显示在文本框中
        self.ui.edit_svg.setText(self.file_name)
        # 得到源文件位置
        self.image_name = self.file_name
        # 转换格式
        self.SvgToPng()
        # 显示转换后的png文件路径
        slm = QStringListModel()
        show = [self.save_file_name, '']
        slm.setStringList(show)
        self.ui.listView.setModel(slm)
        # 预览
        self.ShowOne()

    # 选择文件夹转换
    def ChangeMore(self):
        # 选择文件夹
        self.file_name = QFileDialog.getExistingDirectory(None, '选择文件夹', '/')  # 返回选中的文件夹路径
        # 将打开的文件夹路径显示在文本框中
        self.ui.edit_svg.setText(self.file_name)
        # 读取文件夹的文件
        self.file_paths.clear()
        for root, dirs, files in os.walk(self.file_name, topdown=False):
            for file in files:
                self.file_paths.append(os.path.join(root, file))
        line_name = str(self.file_paths[0]).replace('\', '/').split('/')[-1]
        # 读取出来的列表,第一个数据是一个系统文件,可能有可能无,所以判断一下
        if line_name == 'desktop.ini':
            self.file_paths = self.file_paths[1:]
        # 列表长度,统计有多少个文件
        self.file_num = len(self.file_paths)
        if self.file_num <= 0:
            QMessageBox.warning(
                self.ui,
                '提示',
                '文件夹为空!')
            return
        # 批量转换
        for self.file_index in range(0, self.file_num):
            self.image_name = self.file_paths[self.file_index].replace('\', '/')
            # 处理文件
            self.SvgToPng()
            self.file_paths[self.file_index] = self.save_file_name
        # 控制右侧的列表仅展示png文件
        self.file_index = 0
        for self.file_index in range(0, int(self.file_num / 2)):
            image_name_now = self.file_paths[self.file_index].replace('\', '/').split('/')[-1].split('.')[-1]
            if image_name_now == 'svg':
                del self.file_paths[self.file_index]
        # 先预览最后一张
        self.ShowOne()
        # 显示图片列表
        slm = QStringListModel()
        slm.setStringList(self.file_paths)
        self.ui.listView.setModel(slm)

    # 格式转换
    def SvgToPng(self):
        # 获取当前文件的后缀名
        image_name_now = self.image_name.split('/')[-1].split('.')[-1]
        if image_name_now == 'svg':
            # 读取svg
            png_picture = svg2rlg(self.image_name)
            if png_picture is None:
                QMessageBox.warning(
                    self.ui,
                    '提示',
                    '文件格式不正确!')
            # 设置保存的文件名为“./名字_1.png”
            image_png_name = self.image_name.split('/')[-1]
            self.save_file_name = self.image_name.strip(image_png_name)   image_png_name.strip('.svg')   '_1.png'
            # 转换成png
            renderPM.drawToFile(png_picture, self.save_file_name, fmt="PNG")
            # 设置透明背景
            self.TransPng()

    # 处理背景
    def TransPng(self):
        # 从原来的RGB,24位,转成RGBA,32位
        img = Image.open(self.save_file_name).convert('RGBA')
        W, L = img.size
        white_pixel = (255, 255, 255, 255)
        for h in range(W):
            for i in range(L):
                if img.getpixel((h, i)) == white_pixel:
                    img.putpixel((h, i), (0, 0, 0, 0))
        img.save(self.save_file_name)

    # 展示图片
    def ShowOne(self):
        # 预览png图标
        pix = QPixmap(self.save_file_name)
        self.ui.label_print.setPixmap(pix)
        # 图片自适应
        self.ui.label_print.setScaledContents(True)

    # 列表展示图片
    def ShowMore(self, qModelIndex):
        self.save_file_name = self.file_paths[qModelIndex.row()]
        self.ShowOne()


if __name__ == '__main__':
    app = QApplication([])
    app.setStyle('Fusion')  # 设置窗口显示的风格
    stats = Stats()
    stats.ui.show()
    app.exec_()

六、结果展示

点击右边的列表,左边会相应变化点击右边的列表,左边会相应变化

七、补充说明

1、程序目前并未进行多线程处理,转换量大的话,需要等待一会,才会有显示

2、x_order_2: colinear!的报错问题还未解决,正在尝试改变转换方式,暂时不影响程序运行

3、界面图标保存在与项目文件同一路径下的“image”文件夹中,可能需要更新文件路径

0 人点赞