基于Python實(shí)現(xiàn)向指定PDF指定頁(yè)面指定位置插入圖片的方法
1. 需求
- 想要能否實(shí)現(xiàn)批量自動(dòng)為多個(gè)pdf加蓋不同六格虛擬章(不改變pdf原有分辨率和文字可識(shí)別性);
- 改在pdf首頁(yè)上方空白位置,一般居中即可;
- 如可由使用者自主選擇靠頁(yè)邊距更好,以便部分首頁(yè)上方有字的文件時(shí)人工可微調(diào)位置。
2. 需求分析
- 直接將 pdf 文件轉(zhuǎn)換為圖片,在將圖片繪制到對(duì)應(yīng)頁(yè)的對(duì)應(yīng)位置,最后將全部圖片在轉(zhuǎn)換為 pdf 文件;
- 使用 reportlab 創(chuàng)建一個(gè) pdf 頁(yè),然后將圖片插入到對(duì)應(yīng)位置;
- 使用 PyPDF2 將 reportlab 創(chuàng)建的含有圖片 pdf 和目標(biāo)頁(yè)面進(jìn)行合并。
3. 實(shí)現(xiàn)效果

4. 方案選擇
- 由于要求不改變pdf原有分辨率和文字可識(shí)別性,因此就不能將 pdf 轉(zhuǎn)圖片,因?yàn)檫M(jìn)行此步操作后,重新生成的 pdf 不能進(jìn)行文字可識(shí)別性;
- 所以采用方案二 reportlab 配合 PyPDF2 完成需求的實(shí)現(xiàn)。
5. 設(shè)置插入圖片寬高
- init 默認(rèn)插入圖片的寬高;
- reset_image_width_and_height 方法提供修改插入圖片寬高的方法。
def __init__(self):
self.image_width = int(237 * 0.6)
self.image_height = int(60 * 0.8)
# 設(shè)置圖片的寬高
def reset_image_width_and_height(self, w, h):
self.image_width = w
self.image_height = h
6. 創(chuàng)建 pdf 插入圖片
- 創(chuàng)建一個(gè) BytesIO 對(duì)象;
- Canvas 類(lèi)是 ReportLab PDF 創(chuàng)建工具包的核心,它提供了一個(gè)畫(huà)布,你可以在上面繪制文本、圖形、圖像等,以生成 PDF 文檔;
- 創(chuàng)建一個(gè) Canvas 對(duì)象,指定 packet 和頁(yè)面大小;
- drawImage 方法插入圖像;
- 調(diào)用 save() 方法將繪制的內(nèi)容保存到 packet 對(duì)象中;
- packet.seek(0) 將文件指針移動(dòng)到 BytesIO 對(duì)象的開(kāi)頭;
- 使用 PdfReader 讀取 pdf 文件,并將第一頁(yè)返回。
# 創(chuàng)建一個(gè)PDF頁(yè)面,并在其中放置圖片
def create_overlay(self, image_path, x_pos, y_pos, page_width, page_height):
packet = io.BytesIO()
can = canvas.Canvas(packet, pagesize=(page_width, page_height))
can.drawImage(image_path, x_pos, y_pos, width=self.image_width, height=self.image_height) # 圖片位置和大小
can.save()
packet.seek(0)
overlay = PdfReader(packet)
return overlay.pages[0]
7. 合并插入圖片的 pdf 頁(yè)到目標(biāo) pdf
- 讀取原始PDF文件【需要插入圖片的 pdf】;
- 創(chuàng)建一個(gè)PDF writer對(duì)象;
- 遍歷PDF的每一頁(yè),找到目標(biāo)頁(yè)面;
- 獲取當(dāng)前頁(yè)面對(duì)象;
- 判斷當(dāng)前頁(yè)是否是目標(biāo)頁(yè)面;
- 計(jì)算圖片的插入位置;
- 調(diào)用 create_overlay 創(chuàng)建一個(gè)插入圖片的 pdf 頁(yè)面對(duì)象;
- 將 create_overlay 返回的頁(yè)面通過(guò) merge_page 合并到當(dāng)前 page;
- 將每一個(gè)循環(huán)的 page 通過(guò) add_page 添加到第二步中創(chuàng)建的 writer 對(duì)象中;
- 判斷輸出路徑是否存在,然后寫(xiě)入 pdf。
# 將創(chuàng)建的覆蓋層合并到目標(biāo)PDF的指定頁(yè)面
def merge_image_to_pdf(self, input_pdf_path, output_pdf_path, image_path, page_number, x_pos, y_pos):
# 讀取原始PDF文件
original_pdf = PdfReader(open(input_pdf_path, "rb"))
# 創(chuàng)建一個(gè)PDF writer對(duì)象
pdf_writer = PdfWriter()
# 遍歷PDF的每一頁(yè)
for page_num in range(len(original_pdf.pages)):
page = original_pdf.pages[page_num]
if page_number == page_num:
# 計(jì)算距離
left_distance = int((page.mediabox.width - self.image_width) / 2 + x_pos)
top_distance = int((page.mediabox.height - self.image_height) - y_pos)
overlay = self.create_overlay(image_path, left_distance, top_distance, page.mediabox.width, page.mediabox.height)
page.merge_page(overlay)
pdf_writer.add_page(page)
# 寫(xiě)入修改后的PDF
with open(output_pdf_path, "wb") as out_file:
pdf_writer.write(out_file)
8. 調(diào)用
- 初始化 InsertImageToPDF;
- 調(diào)用插入圖片的方法 merge_image_to_pdf;
- 將圖片 【"./out_images/pdf.png"】插入pdf 【"./pdf/pdf-1/pdf-1.pdf"】,輸出路徑【"./out_images/pdf.png"】;
- 【0, 0, 10】插入第幾頁(yè),圖片距離左側(cè)邊距,圖片距離頂部邊距。
if __name__ == "__main__":
pdf = InsertImageToPDF()
# 使用函數(shù)
pdf.merge_image_to_pdf(
"./pdf/pdf-1/pdf-1.pdf",
"./out_pdf/pdf-1.pdf",
"./out_images/pdf.png",
0, 0, 10)
9. 運(yùn)行結(jié)果

10. 完整代碼
- 引入所需使用的庫(kù) reportlab, PyPDF2, io;
- 初始化插入圖片的寬高,設(shè)置圖片的寬高的函數(shù);
- 創(chuàng)建一個(gè)PDF頁(yè)面,并在其中放置圖片;
- 將創(chuàng)建的覆蓋層合并到目標(biāo)PDF的指定頁(yè)面。
from reportlab.pdfgen import canvas
from PyPDF2 import PdfWriter, PdfReader
import io
class InsertImageToPDF:
def __init__(self):
self.image_width = int(237 * 0.6)
self.image_height = int(60 * 0.8)
# 設(shè)置圖片的寬高
def reset_image_width_and_height(self, w, h):
self.image_width = w
self.image_height = h
# 創(chuàng)建一個(gè)PDF頁(yè)面,并在其中放置圖片
def create_overlay(self, image_path, x_pos, y_pos, page_width, page_height):
packet = io.BytesIO()
can = canvas.Canvas(packet, pagesize=(page_width, page_height))
can.drawImage(image_path, x_pos, y_pos, width=self.image_width, height=self.image_height) # 圖片位置和大小
can.save()
packet.seek(0)
overlay = PdfReader(packet)
return overlay.pages[0]
# 將創(chuàng)建的覆蓋層合并到目標(biāo)PDF的指定頁(yè)面
def merge_image_to_pdf(self, input_pdf_path, output_pdf_path, image_path, page_number, x_pos, y_pos):
# 讀取原始PDF文件
original_pdf = PdfReader(open(input_pdf_path, "rb"))
# 創(chuàng)建一個(gè)PDF writer對(duì)象
pdf_writer = PdfWriter()
# 遍歷PDF的每一頁(yè)
for page_num in range(len(original_pdf.pages)):
page = original_pdf.pages[page_num]
if page_number == page_num:
# 計(jì)算距離
left_distance = int((page.mediabox.width - self.image_width) / 2 + x_pos)
top_distance = int((page.mediabox.height - self.image_height) - y_pos)
overlay = self.create_overlay(image_path, left_distance, top_distance, page.mediabox.width, page.mediabox.height)
page.merge_page(overlay)
pdf_writer.add_page(page)
# 寫(xiě)入修改后的PDF
with open(output_pdf_path, "wb") as out_file:
pdf_writer.write(out_file)
if __name__ == "__main__":
pdf = InsertImageToPDF()
# 使用函數(shù)
pdf.merge_image_to_pdf(
"./pdf/pdf-1/pdf-1.pdf",
"./out_pdf/pdf-1.pdf",
"./out_images/pdf.png",
0, 0, 10)
11. 總結(jié)
- 實(shí)現(xiàn)同一個(gè)需求的方法和技術(shù)很多,我們需要選擇最接近需求的方案;
- 技術(shù)盡量選擇自己熟悉的,或者曾經(jīng)實(shí)現(xiàn)或者學(xué)習(xí)過(guò)的技術(shù),能夠更快開(kāi)發(fā);
- 盡量多的接觸更多的技術(shù),直到每種技術(shù)之間的優(yōu)劣勢(shì)。
以上就是基于Python實(shí)現(xiàn)向指定PDF指定頁(yè)面指定位置插入圖片的方法的詳細(xì)內(nèi)容,更多關(guān)于Python向指定PDF指定位置插入圖片的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Pycharm?cannot?set?up?a?python?SDK問(wèn)題的原因及解決方法
這篇文章主要給大家介紹了關(guān)于Pycharm?cannot?set?up?a?python?SDK問(wèn)題的原因及解決方法,這個(gè)問(wèn)題已經(jīng)不是第一次出現(xiàn)了,所以干脆總結(jié)下,需要的朋友可以參考下2022-06-06
Python中正則表達(dá)式妙用之以搜索電子郵件地址為例
這篇文章主要給大家介紹了關(guān)于Python中正則表達(dá)式妙用之以搜索電子郵件地址為例的相關(guān)資料,正則表達(dá)式經(jīng)常被用到,而自己總是記不全,匯總一份完整的以備不時(shí)之需,需要的朋友可以參考下2024-05-05
PyTorch核心方法之state_dict()、parameters()參數(shù)打印與應(yīng)用案例
PyTorch是一個(gè)流行的開(kāi)源深度學(xué)習(xí)框架,提供了靈活且高效的方式來(lái)訓(xùn)練和部署神經(jīng)網(wǎng)絡(luò),這篇文章主要介紹了PyTorch核心方法之state_dict()、parameters()參數(shù)打印與應(yīng)用案例的相關(guān)資料,需要的朋友可以參考下2025-12-12
利用Python繪制有趣的萬(wàn)圣節(jié)南瓜怪效果
這篇文章主要介紹了用Python繪制有趣的萬(wàn)圣節(jié)南瓜怪效果,本文實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-10-10
使用TFRecord存取多個(gè)數(shù)據(jù)案例
今天小編就為大家分享一篇使用TFRecord存取多個(gè)數(shù)據(jù)案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-02-02
python tkinter實(shí)現(xiàn)簡(jiǎn)單計(jì)算器功能
這篇文章主要為大家詳細(xì)介紹了python tkinter實(shí)現(xiàn)簡(jiǎn)單計(jì)算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
使用Python實(shí)現(xiàn)給企業(yè)微信發(fā)送消息功能
本文將介紹如何使用python3給企業(yè)微信發(fā)送消息,文中有詳細(xì)的圖文解說(shuō)及代碼示例,對(duì)正在學(xué)習(xí)python的小伙伴很有幫助,需要的朋友可以參考下2021-12-12
python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5信號(hào)與槽基礎(chǔ)使用方法與實(shí)例
這篇文章主要介紹了python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5信號(hào)與槽基礎(chǔ)使用方法與實(shí)例,需要的朋友可以參考下2020-03-03

