PDF轉(zhuǎn)PPTX

從PPTX轉(zhuǎn)PDF的方式很多,通過(guò)ppt自帶的工具即可實(shí)現(xiàn)快速而精確的轉(zhuǎn)換。但從PDF轉(zhuǎn)PPTX的轉(zhuǎn)換卻缺乏簡(jiǎn)單便捷的方式。

該問(wèn)題的需求在于:

  • ppt編輯公式比較繁瑣,且需要花費(fèi)大量的時(shí)間用來(lái)調(diào)節(jié)字體等格式,且不美觀

  • latex編輯公式較為方便,但生成的PDF與課堂白板sewoo并不兼容,無(wú)法很好地利用畫筆在課件上進(jìn)行標(biāo)記,給授課帶來(lái)不遍。

一個(gè)簡(jiǎn)單的想法是看看有無(wú)現(xiàn)有的工具將PDF直接導(dǎo)出為PPTX,但發(fā)現(xiàn)無(wú)論是adobe acrobat還是foxit pdf reader,亦或者PDF24 tools均喜歡做額外的工作,進(jìn)行OCR識(shí)別,效果還不甚理想。直接轉(zhuǎn)化為圖片再拼接成PPTX不香么!多此一舉!

好在PDF24 tools可以將PDF拆分成圖片,而PPT又可以很方便地導(dǎo)入圖片。

image
image

這種方式可以有效地解決我的需求。但我想更簡(jiǎn)單點(diǎn),有沒(méi)有一鍵完成的可能?

最初的想法是使用VBA,隨后導(dǎo)出為exe可執(zhí)行程序。但缺乏現(xiàn)有的教程指導(dǎo)。隨后查詢Github,找到了幾個(gè)pdf轉(zhuǎn)png的項(xiàng)目,結(jié)合網(wǎng)上的部分資源,耗時(shí)一個(gè)晚上,實(shí)現(xiàn)了一鍵tex->pdf->pngs->pptx的工作流。


# python

# windows

# pyinstaller -i pdf2pptx.ico --add-data=".\default.pptx;." -F -w pdf2pptx.py

# macOS

# pyinstaller -i pdf2pptx.ico --add-data=".\default.pptx:." -F  pdf2pptx.py

# pipenv 下打包縮小體積

# pip install pyinstaller pymupdf python-pptx PyPDF2

import fitz # pip install  pymupdf

import os

import sys

import shutil

import pptx #pip install python-pptx

import PyPDF2

#生成資源文件目錄訪問(wèn)路徑

def resource_path(relative_path):

    if getattr(sys, 'frozen', False): #是否Bundle Resource

        base_path = sys._MEIPASS

    else:

        base_path = os.path.abspath(".")

    return os.path.join(base_path, relative_path)

def pdf2pptx(pdf_name,zoom):

    # pdf2pngs

    pdf_name=os.path.abspath(pdf_name)

    if pdf_name[-4:].lower() == '.pdf':

        dir_name = os.path.dirname(pdf_name) # 獲得地址的父鏈接

        base_name = os.path.basename(pdf_name)[0:-4] # 獲得地址的文件名

        path = dir_name + os.sep + base_name

        if not os.path.exists(path):

            os.makedirs(path)

        with open(pdf_name,'rb') as f:

            pdfwidth=PyPDF2.PdfFileReader(f).getPage(0).mediaBox[2]

            pdfheight=PyPDF2.PdfFileReader(f).getPage(0).mediaBox[3]

        pdfscale=pdfheight/pdfwidth

        pdfmode = 0

        if pdfscale > 0.74 and pdfscale < 0.76:

            pdfmode = 0

        elif pdfscale > 0.5 and pdfscale < 0.6:

            pdfmode = 1

        else:

            pdfmode = -1

        pdf = fitz.open(pdf_name)

        # pdfwidth=pdf[0].get_images()[0][2]

        # pdfheight=pdf[0].get_images()[0][3]

        # pdfscale=pdfheight/pdfwidth

        # pdfmode = 0

        # if pdfscale > 0.74 and pdfscale < 0.76:

        #    pdfmode = 0

        # elif pdfscale > 0.5 and pdfscale < 0.6:

        #    pdfmode = 1

        # else:

        #    pdfmode = -1

        for pg in range(0, pdf.pageCount):

            page = pdf[pg]  # 獲得每一頁(yè)的對(duì)象

            trans = fitz.Matrix(zoom, zoom).preRotate(0)

            pm = page.getPixmap(matrix=trans, alpha=False)  # 獲得每一頁(yè)的流對(duì)象

            pm.writePNG(path + os.sep + base_name + '_' + '{:0>3d}.{}'.format(pg+1, 'png'))  # 保存圖片

        pdf.close()

        print('PDF轉(zhuǎn)PNG成功!')

    # pngs2pptx

        pngs=os.listdir(path+os.sep)

        template=resource_path(os.path.join("default.pptx"))

        prs=pptx.Presentation(template)

        if pdfmode == 0:

            prs.slide_width = pptx.util.Inches(4)

            prs.slide_height = pptx.util.Inches(3)

        elif pdfmode == 1:

            prs.slide_width = pptx.util.Inches(16)

            prs.slide_height = pptx.util.Inches(9)

        else:

            print('請(qǐng)采用標(biāo)準(zhǔn)格式!')

            prs.slide_width = pptx.util.Inches(4)

            prs.slide_height = pptx.util.Inches(3)

        layout=prs.slide_layouts[6]

        for png in pngs:

            slide=prs.slides.add_slide(layout)

            slide.shapes.add_picture(path + os.sep + png,0,0,height=prs.slide_height)

        prs.save(path + '.pptx')

        print('PNG轉(zhuǎn)PPTX成功!')

        shutil.rmtree(path)

    else:

        print('警告! 文件類型錯(cuò)誤,請(qǐng)打開pdf文件類型!')

if __name__=="__main__":

    if len(sys.argv) == 2:

        pdf2pptx(sys.argv[1],5)

    elif len(sys.argv) > 2:

        pdf2pptx(sys.argv[1],int(sys.argv[2]))

    else:

        print('請(qǐng)輸入要轉(zhuǎn)化的文件名')

在此過(guò)程中,又研究了如何將python源文件編譯為獨(dú)立的exe文件。

中途遇到了幾個(gè)問(wèn)題,列如下:

  • 相對(duì)路徑和絕對(duì)路徑的問(wèn)題。為了避免前后不一致,在程序運(yùn)行前段將文件地址設(shè)定為絕對(duì)路徑。

  • 獲取PDF文件的長(zhǎng)寬比。PPT文件有16:9和4:3兩種比例,通過(guò)或許原PDF的長(zhǎng)寬比,可以設(shè)定PPTX的長(zhǎng)寬。最初的方案直接利用fitz庫(kù)即可提取,但部分PDF會(huì)發(fā)生錯(cuò)誤。因而改用現(xiàn)有PyPDF2庫(kù)來(lái)提取該特征。此外,最初的想法是將長(zhǎng)寬比作為參數(shù)輸入,但后來(lái)覺(jué)得太蠢,還是通過(guò)上述方法來(lái)實(shí)現(xiàn),更能體現(xiàn)自動(dòng)化。

  • 將python源文件編譯為exe后,找不到模板文件"default.pptx"。這一點(diǎn)經(jīng)常出現(xiàn)在pyinstaller編譯中,由于脫離了原python運(yùn)行環(huán)境,部分資源無(wú)法找到,會(huì)出現(xiàn)這種錯(cuò)誤。因而需要將"default.pptx"文件拷貝到工作目錄,并通過(guò)''pptx.Presentation("default.pptx")''的方式來(lái)調(diào)用。但這種方式會(huì)導(dǎo)致需要將該模板與exe文件綁定,既不方便,也不優(yōu)雅。隨后查閱pyinstaller手冊(cè),可以通過(guò)''--add-data''參數(shù),將該文件內(nèi)嵌到exe文件內(nèi)部。

  • 程序運(yùn)行期間,會(huì)出現(xiàn)cmd窗口。 編譯命令中添加''-w''參數(shù)解決。

  • 編譯生成的exe文件較大??梢钥紤]使用pipenv環(huán)境進(jìn)行編譯,可以降低空間占用。

  • 環(huán)境配置。安裝fitz庫(kù),直接安裝pymupdf包即可。安裝pptx庫(kù),直接安裝python-pptx包。

完成以上步驟之后,將pdf文件用該可執(zhí)行文件打開,便可以轉(zhuǎn)化為pptx文件。

為了進(jìn)一步自動(dòng)化,每次在tex編譯生成pdf之后,自動(dòng)將pdf轉(zhuǎn)為pptx,查閱了vscode插件Latex Workshop的手冊(cè)。

image

注意到適當(dāng)調(diào)整占位符,即可完成自動(dòng)將pdf轉(zhuǎn)為pptx的過(guò)程。

隨后修改配置文件:


"latex-workshop.latex.tools": [

      {

              "name": "pdf2pptx",

              "command": "pdf2pptx",

              "args": [

              "%DOCFILE%.pdf"

              ]

      }

],

"latex-workshop.latex.recipes": [

      {

              "name": "xelatex",

              "tools": [

              "xelatex",

              "pdf2pptx"

          ]

      }

] 

其中latex-workshop.latex.tools對(duì)應(yīng)latex-workshop.latex.recipes中的tools鍵.

至此,編輯tex文件之后,只需保存一下,即可自動(dòng)生成pdf和pptx文件。

程序:pdf2pptx.exe

Github項(xiàng)目地址:mission-young/PDF2PPTX (github.com)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容