前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python完成SVG转PNG格式——方法二

Python完成SVG转PNG格式——方法二

原创
作者头像
Elsa_111
修改2021-07-16 14:47:28
5.1K0
修改2021-07-16 14:47:28
举报
文章被收录于专栏:Elsa的学习笔记

一、前情提要

Python完成SVG转PNG格式中,虽然图片格式成功转换了,但是会出现几个问题,如下所示

1、原本透明背景的SVG格式图片,转换成PNG格式之后,图片变成了白色的背景

白色背景变透明的方法可看我上一篇文章python把png的白色背景变透明

直接转换之后的结果
直接转换之后的结果
在上面转换结果的基础上,在进行透明背景的处理
在上面转换结果的基础上,在进行透明背景的处理

2、有的图片在成功转换之后出现了奇怪的线

原图没有这个线
原图没有这个线

3、控制台出现报错

应该是2D库中的线段共线问题,这是因为用renderPM模块转换SVG到PNG格式导致的
应该是2D库中的线段共线问题,这是因为用renderPM模块转换SVG到PNG格式导致的

总结:

1、会出现白色背景,是因为 renderPM 模块转换出来的PNG格式的图片是24位深的,即只能控制RGB通道,所以,会从透明背景变成白色的背景,无法避免,只能转换完成之后再处理;

2、出现奇怪的线,是因为 renderPM 模块内部转换过程中出现的问题,无法避免,只能转换完成之后再处理;

3、控制台报错 x_order_2: colinear! ,是因为 renderPM 模块,是读取了SVG格式的图片内容之后,再在一块画布上画出PNG格式的图像,但是此时的PNG图像只有24位深了,所以控制透明背景的 Alpha 通道只能与另外三个共线了。

二、解决问题

通过总结,我们可以发现,所有问题的根源都是因为我们使用了 renderPM 模块来完成SVG格式到PNG格式的转换,所以,想要解决问题,最好的办法就是采用一个全新的方案去转换格式,这里我找到的了一个cairosvg.svg2png( )方法来转换,上述问题都消失了,并且转换效果很不错,下面介绍一下,具体应该怎么做。

三、实现步骤

1、CarioSVG模块仅支持python3,注意一下python解释器的版本控制。在命令行输入以下指令:

代码语言:javascript
复制
pip install cairosvg

等待安装完成,完成之后,先别急着用,用不了的,因为会出现如下提示,这是因为缺少语言环境

错误提示,不要慌
错误提示,不要慌

2、下载GTK+ libraries,二选一即可,下载的内容都是一样的

有一点需要注意,安装的过程中,不要修改 它安装的路径,就让它 安装在默认的路径下,不然之后运行的时候,会发现CairoSVG找不着你安装的GTK,然后就会一直报上面说的这个错误,安装了也是白装

正确路径应该是类似于这样的,三选一
正确路径应该是类似于这样的,三选一

1、有很多博客是让大家去github的GTK+ for Windows Runtime Environment Installer: 64-bit去下载,但是有时会加载不了网页

2、我把自己用的这个GTK3放在百度网盘了,也可以去我这里下载。

链接: gtk3-runtime-3.24.29-2021-04-29-ts-win64.exe

提取码: qhw1

3、测试环境是否配置正确

在命令行使用CairoSVG,输入以下代码,看一下能不能将 当前目录 下的xx.svg文件转换为xx.png文件:

注意:

①先通过命令行进入到你保存有SVG格式图片的那个文件夹下,再运行该语句

②xx.svg 这个必须是你当前文件夹下有的svg格式的图片

②xx.png 这个名字自己定义的

代码语言:javascript
复制
cairosvg xx.svg -o xx.png

正常情况下,这么一套流程走下来,就没有问题了,转换好的PNG文件会保存在当前目录下,即与SVG格式的图片,放在同一个路径下,可以自己去查看,转换的效果什么的

四、完整代码展示

SvgToPng.ui 这个是用Qt设计师画的界面,和我方法一中的那个界面一模一样,没变化,想参考的话,可以过去跟着我画一下,Python完成SVG转PNG格式

代码语言:javascript
复制
# -*- coding: utf-8 -*-
# @Time    : 2021/7/15 14:23
# @Author  : Elsa
# @File    : SvgToPng.py

import os
import cairosvg
from PySide2.QtCore import QStringListModel
from PySide2.QtGui import QPixmap
from PySide2.QtUiTools import QUiLoader
from PySide2.QtWidgets import QApplication, QFileDialog, QMessageBox


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.file_num = int(len(self.file_paths) / 2)
        for i in range(0, self.file_num):
            for j in range(0, self.file_num):
                png_name_one = self.file_paths[i].replace('\\', '/').split('/')[-1].split('.')[0]
                png_name_two = self.file_paths[j].replace('\\', '/').split('/')[-1].split('.')[0]
                if png_name_one == png_name_two:
                    del self.file_paths[i]
        # 先预览最后一张
        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':
            # 设置保存的文件名为“./名字_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'
            cairosvg.svg2png(file_obj=open(self.image_name, "rb"), write_to=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_()

五、结果展示

没有x_order_2: colinear!的报错了
没有x_order_2: colinear!的报错了
图片的问题也解决了
图片的问题也解决了

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、前情提要
    • 1、原本透明背景的SVG格式图片,转换成PNG格式之后,图片变成了白色的背景
      • 2、有的图片在成功转换之后出现了奇怪的线
        • 3、控制台出现报错
        • 二、解决问题
        • 三、实现步骤
          • 1、CarioSVG模块仅支持python3,注意一下python解释器的版本控制。在命令行输入以下指令:
            • 2、下载GTK+ libraries,二选一即可,下载的内容都是一样的
              • 3、测试环境是否配置正确
              • 四、完整代码展示
              • 五、结果展示
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档