python自制PDF转换.PNG格式图片(按每页生成图片完整源码)小工具!

news2024/9/23 15:35:45

使用PyQt5应用程序制作PDF转换成图片的小工具,可以导入PDF文档后一键生成对应的PNG图片。

PDF图片转换小工具使用的中间件:

python版本:3.6.8
UI应用版本:PyQt5
PDF文件操作非标准库:PyPDF2
PNG图片生成库:PyMuPDF

pip install PyQt5

pip install PyPDF2

pip install PyMuPDF==1.18.17

将需要使用到的python标准库或非标准库全部导入到我们的代码块中进入开发环节。

# Importing all the classes from the PyQt5.QtGui module.
from PyQt5.QtGui import *

# Importing all the classes from the PyQt5.QtCore module.
from PyQt5.QtCore import *

# Importing all the classes from the PyQt5.QtWidgets module.
from PyQt5.QtWidgets import *

# Importing the `fitz` module.
import fitz

# Importing the PyPDF2 module.
import PyPDF2

# Importing the `sys` module.
import sys

# Importing the os module.
import os

# Importing the traceback module.
import traceback

接下来直接进入正题,首先创建名称为PdfToPngUI的python类,将UI组件及布局和相关的槽函数都写入到这个类中。

# This class is a widget that contains a button and a text box. When the button is clicked, the text box is populated with
# the path to the converted file
class PdfToPngUI(QWidget):
    def __init__(self):
        """
        A constructor. It is called when an object is created from a class and it allows the class to initialize the
        attributes of a class.
        """
        super(PdfToPngUI, self).__init__()
        self.init_ui()

    def init_ui(self):
        """
        This function initializes the UI.
        """
        self.setWindowTitle('PDF图片转换工具 公众号:Python 集中营')
        self.setWindowIcon(QIcon('analysis.ico'))
        self.resize(600, 400)

        self.source_pdf_path = QLineEdit()
        self.source_pdf_path.setPlaceholderText('PDF文件路径')
        self.source_pdf_path.setReadOnly(True)

        self.source_pdf_btn = QPushButton()
        self.source_pdf_btn.setText('导入')
        self.source_pdf_btn.clicked.connect(self.source_pdf_btn_click)

        self.target_png_path = QLineEdit()
        self.target_png_path.setPlaceholderText('目标图片存储路径')
        self.target_png_path.setReadOnly(True)

        self.target_png_btn = QPushButton()
        self.target_png_btn.setText('路径')
        self.target_png_btn.clicked.connect(self.target_png_btn_click)

        self.start_btn = QPushButton()
        self.start_btn.setText('PDF一键生成PNG图片')
        self.start_btn.clicked.connect(self.start_btn_click)

        self.brower = QTextBrowser()
        self.brower.setReadOnly(True)
        self.brower.setFont(QFont('宋体', 8))
        self.brower.setPlaceholderText('日志处理过程区域...')
        self.brower.ensureCursorVisible()

        grid = QGridLayout()
        grid.addWidget(self.source_pdf_path, 0, 0, 1, 2)
        grid.addWidget(self.source_pdf_btn, 0, 2, 1, 1)
        grid.addWidget(self.target_png_path, 1, 0, 1, 2)
        grid.addWidget(self.target_png_btn, 1, 2, 1, 1)
        grid.addWidget(self.start_btn, 2, 0, 1, 3)
        grid.addWidget(self.brower, 3, 0, 1, 3)

        self.pdf_thread = WorkThread(self)
        self.pdf_thread.message.connect(self.show_message)
        self.pdf_thread.finished.connect(self.finished)

        self.setLayout(grid)

    def show_message(self, text):
        """
        It shows a message

        :param text: The text to be displayed
        """
        cursor = self.brower.textCursor()
        cursor.movePosition(QTextCursor.End)
        self.brower.append(text)
        self.brower.setTextCursor(cursor)
        self.brower.ensureCursorVisible()

    def source_pdf_btn_click(self):
        """
        It opens a file dialog box to select the source PDF file.
        """
        source_pdf_path = QFileDialog.getOpenFileName(self, "选取文件", os.getcwd(), "PDF File (*.pdf)")
        self.source_pdf_path.setText(source_pdf_path[0])

    def target_png_btn_click(self):
        """
        A function that is called when the target_png_btn is clicked.
        """
        target_png_path = QFileDialog.getExistingDirectory(self, '选择文件夹', os.getcwd())
        self.target_png_path.setText(target_png_path)

    def start_btn_click(self):
        """
        A function that is called when the start button is clicked.
        """
        self.pdf_thread.start()
        self.start_btn.setEnabled(False)

    def finished(self, finished):
        """
        A function that is called when the target_png_btn is clicked
        """
        if finished is True:
            self.start_btn.setEnabled(True)

通过上面的PdfToPngUI类处理,这个时候UI组件及布局和槽函数已经开发完成了,应用的页面效果如下。

PDF图片转换器UI页面.png

然后,我们开始业务逻辑的开发。这里将业务逻辑使用单独的子线程开发避免和页面的主线程发生阻塞。

创建一个子线程的python类WorkThread并继承自QThread子线程,将PDF图片转换的过程写到里面。

# It's a QThread that runs a function in a separate thread
class WorkThread(QThread):
    message = pyqtSignal(str)
    finished = pyqtSignal(bool)

    def __init__(self, parent=None):
        """
        A constructor that initializes the class.

        :param parent: The parent widget
        """
        super(WorkThread, self).__init__(parent)
        self.working = True
        self.parent = parent

    def __del__(self):
        """
        A destructor. It is called when the object is destroyed.
        """
        self.working = False

    def run(self):
        """
        PDF转换图片的业务函数。
        """
        try:
            source_pdf_path = self.parent.source_pdf_path.text().strip()
            target_png_path = self.parent.target_png_path.text().strip()
            if source_pdf_path == '' or target_png_path == '':
                self.message.emit('来源文件路径或目标存储路径不能为空!')
                self.finished.emit(True)
                return

            self.message.emit('源文件路径:{}'.format(source_pdf_path))
            self.message.emit('目标文件路径:{}'.format(target_png_path))

            pdf_ = fitz.open(source_pdf_path)
            self.message.emit('成功打开PDF文件对象!')
            reader = PyPDF2.PdfFileReader(source_pdf_path)
            self.message.emit('PDF文件流处理完成!')
            page_num = reader.getNumPages()
            self.message.emit('PDF文件页数读取完成!')

            for n in range(0, page_num):
                page = pdf_.load_page(n)
                pix_ = page.get_pixmap()
                pix_.save(os.path.join(target_png_path, str(n) + '.png'))
                self.message.emit('图片保存成功:{}'.format(os.path.join(target_png_path, str(n) + '.png')))
            self.message.emit('PNG图片全部转换完成!')
            self.finished.emit(True)
        except:
            traceback.print_exc()
            self.message.emit('程序运行出现错误,请检查参数是否设置正确!')
            self.finished.emit(True)

经过上述的UI界面组件以及业务线程的开发,功能已经实现了,下面使用main函数调起整个应用就OK了。

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = PdfToPngUI()
    main.show()
    sys.exit(app.exec_())

PDF图片转换.gif

往期精彩

假如有一个专属于python的终端工具,那绝对非他莫属!

如何解决python读取大数据量文件时造成的内存溢出?

python如何完成对 Excel文件的解密后读取?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/355338.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VINS-Mono/Fusion与OpenCV去畸变对比

VINS中没有直接使用opencv的去畸变函数,而是自己编写了迭代函数完成去畸变操作,主要是为了加快去畸变计算速度 本文对二者的结果精度和耗时进行了对比 VINS-Mono/Fusion与OpenCV去畸变对比1 去畸变原理2 代码实现2.1 OpenCV去畸变2.2 VINS去畸变3 二者对…

压缩20M文件从30秒到1秒的优化过程

压缩20M文件从30秒到1秒的优化过程 有一个需求需要将前端传过来的10张照片,然后后端进行处理以后压缩成一个压缩包通过网络流传输出去。之前没有接触过用Java压缩文件的,所以就直接上网找了一个例子改了一下用了,改完以后也能使用&#xff0…

(考研湖科大教书匠计算机网络)第四章网络层-第九节:虚拟专用网与网络地址转换

获取pdf:密码7281专栏目录首页:【专栏必读】考研湖科大教书匠计算机网络笔记导航 文章目录一:虚拟专用网(1)虚拟专用网是什么(2)虚拟专用网如何分配IP地址(3)例子&#x…

【JAVA八股文】框架相关

框架相关1. Spring refresh 流程2. Spring bean 生命周期3. Spring bean 循环依赖解决 set 循环依赖的原理4. Spring 事务失效5. Spring MVC 执行流程6. Spring 注解7. SpringBoot 自动配置原理8. Spring 中的设计模式1. Spring refresh 流程 Spring refresh 概述 refresh 是…

深度学习(1)神经网络基础

要学习深度学习,那么首先要熟悉神经网络(Neural Networks,简称NN)的一些基本概念。当然,这里所说的神经网络不是生物学的神经网络,我们将其称之为人工神经网络(Artificial Neural Networks&…

海豚调度2.0.5 星环驱动包踩坑(二)worker服务正常、zk注册正常,心跳时间不更新,也不执行任务,任务一直处于执行中状态

目录背景问题记录20230206 发现服务启动失败20230215 有一台worker不执行作业,其它均正常问题解决问题思考背景 之前分享过海豚调度2.0.5连接星环库使用记录,后来说存储过程又出现了超时的情况,原因是因为调度星环驱动包和生产星环库驱动包不…

ES 异常写入解决流程

问题说明 一天下午,在北京客户现场的同学反馈我们elasticsearch出现的大量的异常,他反馈说他使用多线程写入大量数据到elasticsearch集群时,隔一段时间之后就会出现CircuitBreakingException,多尝试几次后,他就把问题反…

基于微信小程序的微信社团小程序

文末联系获取源码 开发语言:Java 框架:ssm JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7/8.0 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包:Maven3.3.9 浏览器…

JavaEE|网络原理·上

文章目录一、网络发展史1.独立模式2.网络互联3.局域网(LAN)4.广域网(WAN)局域网组网的方式①基于网线直连②基于集线器(hub)组建③基于交换机(switch)组建④基于交换机和路由器组建二、网络通信基础1.ip地址…

Winform控件开发(14)——NotifyIcon(史上最全)

前言: 先看个气泡提示框的效果: 代码如下: 在一个button中注册click事件,当我们点击button1时,就能显示气泡 private void button1_Click(object sender, EventArgs e){notifyIcon1.Visible = true;notifyIcon1

【论文速递】ICLR2018 - 用于小样本语义分割的条件网络

【论文速递】ICLR2018 - 用于小样本语义分割的条件网络 【论文原文】:CONDITIONAL NETWORKS FOR FEW-SHOT SEMANTIC SEGMENTATION(Workshop track - ICLR 2018) 【作者信息】:Kate Rakelly Evan Shelhamer Trevor Darrell Alexe…

PyTorch - Conv2d 和 MaxPool2d

文章目录Conv2d计算Conv2d 函数解析代码示例MaxPool2d计算函数说明卷积过程动画Transposed convolution animationsTransposed convolution animations参考视频:土堆说 卷积计算 https://www.bilibili.com/video/BV1hE411t7RN 关于 torch.nn 和 torch.nn.function t…

Reverse入门[不断记录]

文章目录前言一、[SWPUCTF 2021 新生赛]re1二、[SWPUCTF 2021 新生赛]re2三、[GFCTF 2021]wordy[花指令]四、[NSSRound#3 Team]jump_by_jump[花指令]五、[NSSRound#3 Team]jump_by_jump_revenge[花指令]前言 心血来潮,想接触点Reverse,感受下Reverse&am…

网络编程(一)

网络编程 文章目录网络编程前置概念1- 字节序高低地址与高低字节高低地址:高低字节字节序大端小端例子代码判断当前机器是大端还是小端为何要有字节序字节序转换函数需要字节序转换的时机例子一例子二2- IP地址转换函数早期(不用管)举例现在与字节序转换函数相比:**…

模块化热更思路

title: 模块化热更思路 categories: Others tags: [热更, 模块化, 分包] date: 2023-02-18 01:04:57 comments: false mathjax: true toc: true 模块化热更 浅浅的记录一下访问破 200w (But, I don’t care about this.) 前篇 只谈思路, 不贴实现代码. 需求 游戏类型属于合集…

Linux(十三)设计模式——单例模式

设计模式——针对典型场景所设计出来的特别的处理方案 单例模式:一个类只能实例化一个对象(所以叫单例) 场景: 1、资源角度:资源在内存中只占有一份 2、数据角度:如果只有一个对象,那么该对象在…

2019蓝桥杯真题质数(填空题) C语言/C++

题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。 我们知道第一个质数是 2、第二个质数是 3、第三个质数是 5…… 请你计算第 2019 个质数是多少? 运行限制 最大运行时间:1s 最大运行内存: 128M…

Mac下安装Tomcat以及IDEA中的配置

安装brew 打开终端输入以下命令: /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 搜索tomcat版本,输入以下命令: brew search tomcat 安装自己想要的版本,例…

JDK版本区别

1. 泛型 ArrayList listnew ArrayList()------>ArrayList<Integer>listnew ArrayList<Integer>(); 2 自动装箱/拆箱 nt ilist.get(0).parseInt();-------->int ilist.get(0);原始类型与对应的包装类不用显式转换 3 for-each i0;i<a.length;i------------&…

解析从Linux零拷贝深入了解Linux-I/O(上)

本文将从文件传输场景以及零拷贝技术深究 Linux I/O 的发展过程、优化手段以及实际应用。前言 存储器是计算机的核心部件之一&#xff0c;在完全理想的状态下&#xff0c;存储器应该要同时具备以下三种特性&#xff1a; 速度足够快&#xff1a;存储器的存取速度应当快于 CPU …