Python PDF 加水印 和 Java PDF 加水印

最近項目有給PDF加水印的需求,目前使用的方法是:首先生成一個水印 PDF,再通過 PyPDF4 來把原件的每一頁和 水印 PDF 合併,但耗時和頁數成正比,耗時太長。

後來通過 JAVA 實現的方案是:讀取原 PDF 後,在每一頁的最外層直接添加文字,並且可以調整角度和透明度。

JAVA 方案耗時大概4000頁在500毫秒,而相同文件在使用 Python 方案時耗時大概在 500 秒,JAVA 方案比 Python 方案快了 1000 倍。

然後就想到可能是 Merge 方案操作太耗時,就找了找 Python 裏有沒有 Java 方案的實現,目前還沒找到一樣的方案,但通過 PymuPDF 實現了個類似的方案:在每一頁創建一個透明矩形,矩形可調整角度,然後在矩形裏填充文字。

因爲目前項目已經選用 JAVA 方案了,所以 PymuPDF 方案就沒再找調整文字透明度的方法,諸君可以找找試試。

對了,PymuPDF 方案果然在耗時上提升了一大截,但還沒 JAVA 方案那麼變態的快,4000頁大概耗時在3秒,耗時和創建幾個矩形成正比。

好了,話不多說,給諸君上菜。

Python

import fitz
from PyPDF2 import PdfFileReader, PdfFileWriter


def add_watermark_by_merge_pdf(input_pdf, output, watermark):
    """PyPDF2 Merge 方案"""
    watermark_obj = PdfFileReader(watermark)
    watermark_page = watermark_obj.getPage(0)
    pdf_reader = PdfFileReader(input_pdf)
    pdf_writer = PdfFileWriter()

    for page in range(pdf_reader.getNumPages()):
        p = pdf_reader.getPage(page)
        p.mergePage(watermark_page)
        pdf_writer.addPage(page)

    with open(output, 'wb') as f:
        pdf_writer.write(f)


def add_watermark_by_text(input_path, output_path):
    """PymuPDF 矩形方案"""
    doc = fitz.open(input_path)
    text1 = "rotate=-90"
    red = (1, 0, 0)
    gray = (0, 0, 1)
    for page in doc:
        p1 = fitz.Point(page.rect.width - 25, page.rect.height - 25)
        shape = page.newShape()
        shape.drawCircle(p1, 1)
        shape.finish(width=0.3, color=red, fill=red)
        shape.insertText(p1, text1, rotate=-90, color=gray)
        shape.commit()
    doc.save(output_path)


if __name__ == "__main__":
    add_watermark_by_merge_pdf(
        './douluo.pdf', './watermark.pdf', './output.pdf')
    add_watermark_by_text('./douluo.pdf', './output.pdf')

JAVA

package test;

import java.io.FileOutputStream;

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Element;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfGState;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;

public class Test {
    /**
     * @param inputFile     你的PDF文件地址
     * @param outputFile    添加水印後生成PDF存放的地址
     * @param waterMarkName 你的水印
     * @return
     */
    public static boolean waterMark(String inputFile, String outputFile, String waterMarkName) {
        try {
            PdfReader reader = new PdfReader(inputFile);
            PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputFile));
            // 這裏的字體設置比較關鍵,這個設置是支持中文的寫法
            BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);// 使用系統字體
            int total = reader.getNumberOfPages() + 1;

            PdfContentByte under;
            // Rectangle pageRect = null;
            long s1 = System.currentTimeMillis();
            for (int i = 1; i < total; i++) {
                // 獲得PDF最頂層
                under = stamper.getOverContent(i);
                // set Transparency
                PdfGState gs = new PdfGState();
                // 設置透明度爲0.2
                gs.setFillOpacity(0.5f);
                under.setGState(gs);
                under.saveState();
                under.restoreState();
                under.beginText();
                under.setFontAndSize(base, 35);
                under.setTextMatrix(30, 30);
                under.setColorFill(BaseColor.GRAY);
                for (int y = 0; y < 3; y++) {
                    for (int x = 0; x < 2; x++) {
                        // 水印文字成45度角傾斜
                        under.showTextAligned(Element.ALIGN_LEFT, waterMarkName, 100 + 300 * x, 300 * y, 45);
                    }
                }
                // 添加水印文字
                under.endText();
                under.setLineWidth(1f);
                under.stroke();
            }
            stamper.close();
            System.out.println(System.currentTimeMillis() - s1);
            return true;

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }

    public static void main(String[] args) {
        System.out.println(waterMark("./douluo.pdf", "./output.pdf", "中文水印 2020-05-05"));
    }

}

JAVA POM

<dependencies>
    <dependency>
      <groupId>com.itextpdf</groupId>
      <artifactId>itextpdf</artifactId>
      <version>5.5.10</version>
  	</dependency>
  	<dependency>
      <groupId>com.itextpdf</groupId>
      <artifactId>itext-asian</artifactId>
      <version>5.2.0</version>
    </dependency>
  </dependencies>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章