用wxPython和PyMuPDF将PNG图像合并为PDF文件

在日常工作中,我们经常需要将多个图像文件合并到一个PDF文档中,以便于查看、共享或存档。虽然现有的一些工具可以实现这一功能,但开发一个自定义的GUI工具可以更好地满足特定需求,并提供更好的用户体验。

在本文中,我将介绍如何使用Python、wxPython和PyMuPDF库创建一个简单的图形界面程序,用于将指定文件夹中的PNG图像合并为一个PDF文件。

程序概述

我们的程序包含以下主要部分:

1. **wxPython GUI** - 提供用户界面,包括文件选择器、图像预览和文件列表控件。
2. **PyMuPDF库** - 用于创建和操作PDF文件,将PNG图像插入到PDF页面中。
3. **Python文件操作** - 用于遍历文件夹和获取文件信息。

下面是程序的用户界面截图:

使用步骤:

1. 运行程序后,选择包含PNG图像的文件夹
2. 在左侧的列表框中,所有PNG文件名将被列出。单击任一文件名,右侧区域会显示该图像的预览。
3. 选中要合并到PDF中的PNG文件,点击">>"按钮将其移动到右侧列表框中。
4. 点击"生成PDF"按钮,选择PDF文件的保存路径。
5. 程序将按照右侧列表框中的顺序,将PNG图像合并到一个新的PDF文件中。
6. 合并完成后,会弹出一个对话框,显示PDF文件的保存路径。

C:\pythoncode\new\pngToPdf.py

代码解析

import os
import wx
import fitz  # PyMuPDF库

class PDFMergeApp(wx.App):
    def __init__(self):
        super().__init__()
        self.frame = PDFMergeFrame(None)
        self.frame.Show()

class PDFMergeFrame(wx.Frame):
    def __init__(self, parent):
        super().__init__(parent, title="PDF合并工具")
        panel = wx.Panel(self)
        
        # 创建控件
        self.dir_picker = wx.DirPickerCtrl(panel, message="选择PNG文件夹")
        self.list_box1 = wx.ListBox(panel, style=wx.LB_SINGLE)
        self.picture = wx.StaticBitmap(panel)
        self.list_box2 = wx.ListBox(panel, style=wx.LB_EXTENDED)
        move_btn = wx.Button(panel, label=">>")
        generate_btn = wx.Button(panel, label="生成PDF")
        
        # 绑定事件处理函数
        self.dir_picker.Bind(wx.EVT_DIRPICKER_CHANGED, self.update_list_box1)
        self.list_box1.Bind(wx.EVT_LISTBOX, self.display_image)
        move_btn.Bind(wx.EVT_BUTTON, self.move_to_list_box2)
        generate_btn.Bind(wx.EVT_BUTTON, self.generate_pdf)
        
        # 布局
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        left_sizer = wx.BoxSizer(wx.VERTICAL)
        right_sizer = wx.BoxSizer(wx.VERTICAL)
        left_sizer.Add(self.dir_picker, 0, wx.EXPAND | wx.ALL, 5)
        left_sizer.Add(self.list_box1, 1, wx.EXPAND | wx.ALL, 5)
        right_sizer.Add(self.picture, 1, wx.EXPAND | wx.ALL, 5)
        right_sizer.Add(self.list_box2, 1, wx.EXPAND | wx.ALL, 5)
        right_sizer.Add(generate_btn, 0, wx.ALIGN_CENTER | wx.ALL, 5)
        sizer.Add(left_sizer, 1, wx.EXPAND | wx.ALL, 5)
        sizer.Add(move_btn, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
        sizer.Add(right_sizer, 1, wx.EXPAND | wx.ALL, 5)
        panel.SetSizer(sizer)
        
    def update_list_box1(self, event):
        self.list_box1.Clear()
        dir_path = self.dir_picker.GetPath()
        for filename in os.listdir(dir_path):
            if filename.endswith(".png"):
                self.list_box1.Append(filename)
        
    def display_image(self, event):
        selection = event.GetSelection()
        filename = self.list_box1.GetString(selection)
        dir_path = self.dir_picker.GetPath()
        image = wx.Image(os.path.join(dir_path, filename), wx.BITMAP_TYPE_PNG)
        self.picture.SetBitmap(wx.Bitmap(image))
        
    def move_to_list_box2(self, event):
        selections = self.list_box1.GetSelections()
        items = [self.list_box1.GetString(sel) for sel in selections]
        for item in items:
            self.list_box2.Append(item)
            self.list_box1.Delete(self.list_box1.FindString(item))
        
    def generate_pdf(self, event):
        dir_path = self.dir_picker.GetPath()
        pdf_path = wx.FileSelector("保存PDF文件", wildcard="PDF 文件 (*.pdf)|*.pdf",
                                flags=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
        if pdf_path:
            pdf = fitz.open()
            for index in range(self.list_box2.GetCount()):
                filename = self.list_box2.GetString(index)
                image_path = os.path.join(dir_path, filename)
                img = fitz.Pixmap(image_path)
                page = pdf.new_page(width=img.width, height=img.height)
                page.insert_image(rect=page.rect, pixmap=img)
            pdf.save(pdf_path)
            pdf.close()
            wx.MessageBox(f"已成功生成PDF文件: {pdf_path}", "完成", wx.OK | wx.ICON_INFORMATION)
if __name__ == "__main__":
    app = PDFMergeApp()
    app.MainLoop()

这段代码的核心在于wxPython GUI的构建和PyMuPDF库的使用。

在创建GUI时,我们定义了各种控件,如文件夹选择器、列表框和图像预览区域,并将它们合理布局。通过事件绑定,实现了不同控件的交互功能,例如选择文件夹后更新文件列表、预览图像、在列表框之间移动文件等。

合并PNG到PDF的关键是使用PyMuPDF库。我们遍历右侧列表框中的PNG文件路径,使用`fitz.Pixmap`打开每个PNG图像。然后,为每个图像创建一个新的PDF页面,并使用`page.insert_image`方法将图像插入到该页面中。最后,将所有页面保存到一个新的PDF文件中。

总结

通过结合wxPython和PyMuPDF,我们创建了一个方便实用的工具,可以快速将PNG图像合并为PDF文档。该程序不仅操作简单,还具有预览功能,可以确认要合并的图像顺序。你可以根据自己的需求对代码进行进一步扩展和定制,例如支持其他图像格式、调整图像大小或添加水印等。无论是用于工作还是个人使用,这个小工具都将为你节省宝贵的时间和精力。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【java】异常与错误

Throwable包括Error和Expected。 Error Error错误是程序无法处理的,由JVM产生并抛出的。 举例:StackOverflowError \ ThreadDeath Expected Expected异常包括两类,即受检异常(非运行时异常)和非受检异常(运行时异常),异常往往…

两大DRAM巨头20%产能转给HBM

随着人工智能(AI)需求的激增,全球领先的内存芯片制造商三星(Samsung)和SK海力士(SK Hynix)预计,由于高性能芯片需求不断增长,今年DRAM和高带宽内存(HBM)的价格将保持强劲。据《韩国经济日报》报道,三星和SK海力士已将其超过20%的D…

BUUCTF靶场[MISC]荷兰宽带数据泄露、九连环

[MISC]荷兰宽带数据泄露 考点:查看路由器恢复丢失密码的文件 工具:RouterPassView——路由器密码查看工具 工具链接:https://routerpassview.en.lo4d.com/windows RouterPassView是一款老牌的路由器密码查看器,可以一键获取路…

网络安全从业者“行话”

目录 ​编辑 一、攻击篇 1.攻击工具 2.攻击方法 3.攻击者 二、防守篇 1.软硬件 2.技术与服务 网络安全学习资源分享: 特别声明 一、攻击篇 1.攻击工具 肉鸡 所谓“肉鸡”是一种很形象的比喻&…

JavaScript循环结构

JS循环结构 1 while结构2 for循环3 foreach循环 1 while结构 几乎和JAVA一致 代码 /* 打印99 乘法表 */var i 1;while(i < 9){var j 1;while(j < i){document.write(j"*"i""i*j" ");j;}document.write("<hr/>");i…

win11此电脑右键“属性“选项,无法打开怎么解决?

方法如下&#xff1a; 1. 按【 Win X 】组合键&#xff0c;或【 右键】点击任务栏上的【 Windows开始菜单】&#xff0c;在打开的隐藏菜单项中&#xff0c;选择【 终端管理员】&#xff1b; 2. 用户账户控制窗口&#xff0c;你要允许此应用对你的设备进行更改吗&#xff1f;点…

IT Tools

ChatGpt chatGpt chatgpt vs & vscode工具 Vs Extensions & Remote Development Vs Extensions Remote-SSH VSCode远程连接到Linux并实现免密码登录 Git Graph C cppreference.com cplusplus 镜像站点 用于下载 QT, Ubuntu, 清华镜像站点 CMake Downlo…

【面试必看】MyBatis部分

MyBatis 必读 Mybatis系列全解 MyBatis最全使用指南 MyBatis最全使用指南 1. JDBC java 操作数据库的原始方式就是 JDBC。 但是存在以下问题&#xff1a; 每次操作我们都要创建 connection、Statement 等一些对象&#xff0c;操作完还要关闭、销毁这些对象。 ResultSet …

TSINGSEE青犀智慧校园视频综合管理系统建设方案及平台功能

一、方案背景 智慧校园视频综合管理系统以物联网、云计算、大数据分析等新技术为核心&#xff0c;将基于计算机网络的信息服务融入学校的各个应用与服务领域&#xff0c;实现互联和协作。通过“云边缘计算”构架&#xff0c;在各应用子系统的基础数据层面上&#xff0c;打通上…

活字格日期组件默认值以及自动编号设置

1、日期组件默认值为今天。 日期组件&#xff0c;缺省值&#xff0c;today&#xff08;&#xff09; 2、自动编号设置&#xff1a; 数据表。字段。唯一id。设置规则。启用。确定。 效果&#xff1a;

初识C++ · string的使用(2)

目录 1 Modifiers部分 1.1 assign的使用 1.2 insert的使用 1.3 erase的使用 1.4 replace的使用 2 capacity部分 2.1 max_size的使用 2.2 capacity的使用 2.3 reserve的使用 2.4 shrink_to_fit简介 2.5 resize的使用 2.6 clear的使用 3 String operations部分 3.1 …

奖金+1 万,OpenTenBase 开源核心贡献挑战赛,KB 专家助力其跑在 K8s 上

OpenTenBase 是由开放原子开源基金会孵化及运营的开源项目&#xff0c;是一款开放中立的企业级分布式 HTAP 开源数据库。OpenTenBase 具备高扩展性、商业数据库语法兼容、分布式 HTAP 引擎、多级容灾和多维度资源隔离等能力&#xff0c;已成功应用于金融、医疗、航天等行业的核…

Qt qt5.3集成mqtt模块

参考 【Qt官方MQTT库的使用&#xff0c;附一个MqttClient例子】 - 叶小鹏 - 博客园 (cnblogs.com)MQTT&#xff1a;windows最简单搭建mqtt服务端及本地客户端测试_emqx-windows-4.3.6-CSDN博客MQTTX 下载 编译 我从Github下载的是Release v5.12.5 qt/qtmqtt (github.com)版…

Rust Web开发框架actix-web入门案例

概述 在看书的时候&#xff0c;用到了actix-web这个框架的案例。 书里面的版本是1.0&#xff0c;但是我看官网最新都4.4了。 为了抹平这种信息差&#xff0c;所以我决定把官方提供的示例代码过一遍。 核心代码 Cargo.toml [package] name "hello" version &q…

Openeuler系统安装oracle 19c

前言 经验证oracle 19c用静默安装&#xff0c;会一直报错&#xff0c;没有找到解决办法 报错信息如下&#xff1a; 换用RPM安装测试成功 安装过程 1.下载安装包 1.1 下载链接&#xff1a;https://www.oracle.com/database/technologies/oracle19c-linux-downloads.html 下…

翻译《The Old New Thing》- What does the CS_CLASSDC class style do?

What does the CS_CLASSDC class style do? - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20060602-00/?p30993 Raymond Chen 2006年06月02日 CS_CLASSDC 类样式有什么作用&#xff1f; 简要 本文讨论了CS_CLASSDC类样式的问题&#xff…

搭建域环境

文章目录 配置域控网络安装DNS服务安装域控新建用户新建域内机器 windows server 2008是基于windows vista开发的&#xff0c;windows server 2008 r2是基于Win 7开发的。域控为windows server 2008. 配置域控网络 在网络共享中心配置域控IP&#xff0c;这里设置域控IP为&…

在centos8上生成nfs-ganesha的相关rpm

在centos8上生成nfs-ganesha的相关rpm 1.背景2.依赖环境准备2.1配置yum源2.2安装依赖包2.3拉取源代码 3编译打包3.1生成makefile3.1生成rpm 1.背景 在某些情况下&#xff0c;可能需要在CentOS 8上从源代码生成NFS Ganesha的RPM包&#xff0c;特别是当内置的软件仓库提供的NFS …

vue读取excel表格内容

vue读取excel文件内容 1. 安装第三方工具 xlsx npm install xlsx2. 在vue组件中引入xlsx import * as xlsx from xlsx3. 使用xlsx读取excel文件 html部分 <el-upload action"#" :auto-upload"false" :on-change"handleFileSelect" accept…

哪款台灯护眼效果最好,护眼效果十足的五款台灯分享

在孩子学习过程中&#xff0c;有一样物品的重要性不容忽视&#xff0c;那就是一盏提供舒适光源的台灯。面对不断增加的学业负担&#xff0c;孩子们经常需要在夜晚借助台灯的光亮进行学习&#xff0c;这已经成为了家庭生活中普遍的情景。然而&#xff0c;我们必须给予足够的关注…