基于Python開發(fā)PPTX壓縮工具
引言
在日常辦公中,PPT文件往往因為圖片過大而導致文件體積過大,不便于傳輸和存儲。為了應(yīng)對這一問題,我們可以使用Python的wxPython圖形界面庫結(jié)合python-pptx和Pillow,開發(fā)一個簡單的PPTX壓縮工具。本文將詳細介紹如何實現(xiàn)這一功能。
全部代碼
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))
# 狀態(tài)文本
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:
# 獲取圖片數(shù)據(jù)
image_bytes = shape.image.blob
# 使用PIL壓縮圖片
with Image.open(io.BytesIO(image_bytes)) as img:
# 轉(zhuǎn)換RGBA為RGB
if img.mode == 'RGBA':
img = img.convert('RGB')
# 壓縮圖片
# 如果圖片較大,調(diào)整尺寸
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()
# 更新圖片數(shù)據(jù)
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()
環(huán)境準備
在開始之前,我們需要安裝以下Python庫:
- wxPython:用于創(chuàng)建圖形用戶界面
- python-pptx:用于處理PPTX文件
- Pillow:用于圖片壓縮
安裝命令:
pip install wxPython python-pptx Pillow
代碼結(jié)構(gòu)
代碼主要包括以下幾個部分:
- 圖形界面設(shè)計
- 文件選擇與壓縮功能
- 圖片壓縮邏輯
代碼實現(xiàn)
導入必要模塊
import wx import os from pptx import Presentation from PIL import Image import io
創(chuàng)建主窗口
主窗口CompressorFrame繼承自wx.Frame,用于展示UI組件。
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))
# 狀態(tài)文本
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文件。
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('"')))
壓縮功能實現(xiàn)
壓縮圖片邏輯:
- 使用Pillow庫壓縮PPT中的圖片,將其轉(zhuǎn)換為JPEG格式,并降低質(zhì)量以減少文件大小。
- 限制圖片的最大尺寸,保持圖片的可視質(zhì)量。
更新進度條與狀態(tài):
使用wx.Gauge展示處理進度。
實時更新處理狀態(tài)。
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)主函數(shù)
啟動wxPython應(yīng)用程序。
def main():
app = wx.App()
frame = CompressorFrame()
frame.Show()
app.MainLoop()
???????if __name__ == '__main__':
main()
運行結(jié)果

到此這篇關(guān)于基于Python開發(fā)PPTX壓縮工具的文章就介紹到這了,更多相關(guān)Python PPTX壓縮內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用python生成一個導出數(shù)據(jù)庫的bat腳本文件的方法
下面小編就為大家?guī)硪黄胮ython生成一個導出數(shù)據(jù)庫的bat腳本文件的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12
基于Python的網(wǎng)頁自動化工具DrissionPage的使用詳解
DrissionPage 是一個基于 python 的網(wǎng)頁自動化工具,它既能控制瀏覽器,也能收發(fā)數(shù)據(jù)包,還能把兩者合而為一,下面就跟隨小編一起來學習一下它的具體使用吧2024-01-01
簡單談?wù)凱ython中的幾種常見的數(shù)據(jù)類型
Python 中的變量不需要聲明。每個變量在使用前都必須賦值,變量賦值以后該變量才會被創(chuàng)建。在 Python 中,變量就是變量,它沒有類型,我們所說的"類型"是變量所指的內(nèi)存中對象的類型。2017-02-02
Python如何生成exe文件?用Pycharm一步步帶你學(超詳細、超貼心)
這篇文章主要給大家介紹了關(guān)于Python如何生成exe文件的相關(guān)資料,本文利用Pycharm一步步帶你學,文中通過圖文以及實例代碼介紹的超詳細、超貼心,需要的朋友可以參考下2022-02-02

