引言
在日常办公中,PPT文件往往因为图片过大而导致文件体积过大,不便于传输和存储。为了应对这一问题,我们可以使用Python的wxPython
图形界面库结合python-pptx
和Pillow
,开发一个简单的PPTX压缩工具。本文将详细介绍如何实现这一功能。
全部代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | import wx import os from pptx import Presentation from PIL import Image import io class CompressorFrame(wx.Frame): def __init__( self ): super ().__init__(parent = None , title = 'PPTX压缩工具' ) self .panel = wx.Panel( self ) self .create_ui() def create_ui( self ): vbox = wx.BoxSizer(wx.VERTICAL) # 文件选择部分 hbox1 = wx.BoxSizer(wx.HORIZONTAL) self .file_path = wx.TextCtrl( self .panel, size = ( 300 , - 1 )) browse_btn = wx.Button( self .panel, label = '选择文件' ) browse_btn.Bind(wx.EVT_BUTTON, self .on_browse) hbox1.Add( self .file_path, proportion = 1 , flag = wx.EXPAND|wx. ALL , border = 5 ) hbox1.Add(browse_btn, flag = wx. ALL , border = 5 ) # 压缩按钮 compress_btn = wx.Button( self .panel, label = '开始压缩' ) compress_btn.Bind(wx.EVT_BUTTON, self .on_compress) # 进度条 self .progress = wx.Gauge( self .panel, range = 100 , size = ( 400 , 25 )) # 状态文本 self .status_text = wx.StaticText( self .panel, label = "") vbox.Add(hbox1, flag = wx.EXPAND|wx. ALL , border = 5 ) vbox.Add(compress_btn, flag = wx.ALIGN_CENTER|wx. ALL , border = 5 ) vbox.Add( self .progress, flag = wx.EXPAND|wx. ALL , border = 5 ) vbox.Add( self .status_text, flag = wx.EXPAND|wx. ALL , border = 5 ) self .panel.SetSizer(vbox) self .Fit() def on_browse( self , event): with wx.FileDialog( self , "选择PPTX文件" , wildcard = "PowerPoint files (*.pptx)|*.pptx" , style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog: if fileDialog.ShowModal() = = wx.ID_CANCEL: return path = fileDialog.GetPath() path = os.path.normpath(path.strip( '"')) self.file_path.SetValue(path) def update_status(self, text): wx.CallAfter(self.status_text.SetLabel, text) def on_compress(self, event): if not self.file_path.GetValue(): wx.MessageBox('请先选择文件', '提示', wx.OK | wx.ICON_INFORMATION) return input_path = self.file_path.GetValue().strip('"' ) input_path = os.path.normpath(input_path) if not os.path.exists(input_path): wx.MessageBox( '文件不存在,请检查路径' , '错误' , wx.OK | wx.ICON_ERROR) return output_path = self ._get_output_path(input_path) try : self ._compress_pptx(input_path, output_path) wx.MessageBox( '压缩完成!n保存路径:' + output_path, '成功' , wx.OK | wx.ICON_INFORMATION) except Exception as e: wx.MessageBox(f '压缩过程中出错:{str(e)}' , '错误' , wx.OK | wx.ICON_ERROR) finally : self .progress.SetValue( 0 ) self .update_status("") def _get_output_path( self , input_path): directory = os.path.dirname(input_path) filename = os.path.basename(input_path) name, ext = os.path.splitext(filename) return os.path.join(directory, f "{name}_compressed{ext}" ) def _compress_pptx( self , input_path, output_path): try : prs = Presentation(input_path) except Exception as e: raise Exception(f "无法打开PPTX文件: {str(e)}" ) total_slides = len (prs.slides) processed_images = 0 skipped_images = 0 for i, slide in enumerate (prs.slides): self .update_status(f "正在处理第 {i+1}/{total_slides} 张幻灯片" ) shapes_with_images = [] for shape in slide.shapes: if hasattr (shape, "image" ): shapes_with_images.append(shape) for shape in shapes_with_images: try : # 获取图片数据 image_bytes = shape.image.blob # 使用PIL压缩图片 with Image. open (io.BytesIO(image_bytes)) as img: # 转换RGBA为RGB if img.mode = = 'RGBA' : img = img.convert( 'RGB' ) # 压缩图片 # 如果图片较大,调整尺寸 max_size = 800 # 最大尺寸为1024像素 if img.width > max_size or img.height > max_size: ratio = min (max_size / img.width, max_size / img.height) new_size = ( int (img.width * ratio), int (img.height * ratio)) img = img.resize(new_size, Image.LANCZOS) output_buffer = io.BytesIO() img.save(output_buffer, format = 'JPEG' , quality = 10 , optimize = True ) # 替换原图片 shape._element.blip.embed.rId = shape._element.blip.embed.rId new_image = output_buffer.getvalue() # 更新图片数据 image_part = shape.image image_part._blob = new_image processed_images + = 1 except Exception as e: print (f "处理图片时出错: {str(e)}" ) skipped_images + = 1 continue # 更新进度条 progress = int ((i + 1 ) / total_slides * 100 ) wx.CallAfter( self .progress.SetValue, progress) self .update_status(f "完成!成功处理 {processed_images} 张图片,跳过 {skipped_images} 张图片" ) try : prs.save(output_path) except Exception as e: raise Exception(f "保存文件时出错: {str(e)}" ) def main(): app = wx.App() frame = CompressorFrame() frame.Show() app.MainLoop() if __name__ = = '__main__' : main() |
环境准备
在开始之前,我们需要安装以下Python库:
- wxPython:用于创建图形用户界面
- python-pptx:用于处理PPTX文件
- Pillow:用于图片压缩
安装命令:
1 | pip install wxPython python-pptx Pillow |
代码结构
代码主要包括以下几个部分:
- 图形界面设计
- 文件选择与压缩功能
- 图片压缩逻辑
代码实现
导入必要模块
1 2 3 4 5 | import wx import os from pptx import Presentation from PIL import Image import io |
创建主窗口
主窗口CompressorFrame继承自wx.Frame,用于展示UI组件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | class CompressorFrame(wx.Frame): def __init__( self ): super ().__init__(parent = None , title = 'PPTX压缩工具' ) self .panel = wx.Panel( self ) self .create_ui() def create_ui( self ): vbox = wx.BoxSizer(wx.VERTICAL) # 文件选择部分 hbox1 = wx.BoxSizer(wx.HORIZONTAL) self .file_path = wx.TextCtrl( self .panel, size = ( 300 , - 1 )) browse_btn = wx.Button( self .panel, label = '选择文件' ) browse_btn.Bind(wx.EVT_BUTTON, self .on_browse) hbox1.Add( self .file_path, proportion = 1 , flag = wx.EXPAND|wx. ALL , border = 5 ) hbox1.Add(browse_btn, flag = wx. ALL , border = 5 ) # 压缩按钮 compress_btn = wx.Button( self .panel, label = '开始压缩' ) compress_btn.Bind(wx.EVT_BUTTON, self .on_compress) # 进度条 self .progress = wx.Gauge( self .panel, range = 100 , size = ( 400 , 25 )) # 状态文本 self .status_text = wx.StaticText( self .panel, label = "") vbox.Add(hbox1, flag = wx.EXPAND|wx. ALL , border = 5 ) vbox.Add(compress_btn, flag = wx.ALIGN_CENTER|wx. ALL , border = 5 ) vbox.Add( self .progress, flag = wx.EXPAND|wx. ALL , border = 5 ) vbox.Add( self .status_text, flag = wx.EXPAND|wx. ALL , border = 5 ) self .panel.SetSizer(vbox) self .Fit() |
文件选择功能
通过文件对话框让用户选择PPTX文件。
1 2 3 4 5 6 7 | def on_browse( self , event): with wx.FileDialog( self , "选择PPTX文件" , wildcard = "PowerPoint files (*.pptx)|*.pptx" , style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog: if fileDialog.ShowModal() = = wx.ID_CANCEL: return path = fileDialog.GetPath() self .file_path.SetValue(os.path.normpath(path.strip( '"' ))) |
压缩功能实现
压缩图片逻辑:
- 使用Pillow库压缩PPT中的图片,将其转换为JPEG格式,并降低质量以减少文件大小。
- 限制图片的最大尺寸,保持图片的可视质量。
更新进度条与状态:
使用wx.Gauge展示处理进度。
实时更新处理状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | def _compress_pptx( self , input_path, output_path): prs = Presentation(input_path) total_slides = len (prs.slides) processed_images = 0 skipped_images = 0 for i, slide in enumerate (prs.slides): self .update_status(f "正在处理第 {i+1}/{total_slides} 张幻灯片" ) shapes_with_images = [shape for shape in slide.shapes if hasattr (shape, "image" )] for shape in shapes_with_images: try : image_bytes = shape.image.blob with Image. open (io.BytesIO(image_bytes)) as img: if img.mode = = 'RGBA' : img = img.convert( 'RGB' ) max_size = 800 if img.width > max_size or img.height > max_size: ratio = min (max_size / img.width, max_size / img.height) new_size = ( int (img.width * ratio), int (img.height * ratio)) img = img.resize(new_size, Image.LANCZOS) output_buffer = io.BytesIO() img.save(output_buffer, format = 'JPEG' , quality = 10 , optimize = True ) new_image = output_buffer.getvalue() shape.image._blob = new_image processed_images + = 1 except Exception as e: print (f "处理图片时出错: {str(e)}" ) skipped_images + = 1 wx.CallAfter( self .progress.SetValue, int ((i + 1 ) / total_slides * 100 )) self .update_status(f "完成!成功处理 {processed_images} 张图片,跳过 {skipped_images} 张图片" ) prs.save(output_path) |
主函数
启动wxPython应用程序。
1 2 3 4 5 6 7 8 | def main(): app = wx.App() frame = CompressorFrame() frame.Show() app.MainLoop() if __name__ = = '__main__' : main() |
运行结果
到此这篇关于基于Python开发PPTX压缩工具的文章就介绍到这了,更多相关Python PPTX压缩内容请搜索IT俱乐部以前的文章或继续浏览下面的相关文章希望大家以后多多支持IT俱乐部!