我下载了个作为示例的PDF文件:
代码
利用PDFBox
<dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.23</version> </dependency>
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.PdfReader; import com.itextpdf.text.pdf.PdfStamper; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.font.PDType0Font; import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState; import org.apache.pdfbox.util.Matrix; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; public class PDFWaterMark { public static void main(String[] args) throws Exception { usePDFBox(); } private static void usePDFBox() throws Exception { File sourcePDF = new File("20210331165837838.pdf"); File targetPDF = new File("20210331165837838-watermark.pdf"); PDDocument doc = PDDocument.load(sourcePDF); doc.setAllSecurityToBeRemoved(true); // 水印文字 String ts = "给PDF加水印"; for(PDPage page : doc.getPages()){ // 透明度 PDExtendedGraphicsState graphicsState = new PDExtendedGraphicsState(); graphicsState.setNonStrokingAlphaConstant(0.2f); graphicsState.setAlphaSourceFlag(true); PDPageContentStream cs = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true, true); cs.setGraphicsStateParameters(graphicsState); cs.setNonStrokingColor(100,0,40, 0); // CMYK颜色 cs.beginText(); // 引入外部字体 cs.setFont(PDType0Font.load(doc, new File("C:\Windows\Fonts\simhei.ttf")), 30); // cs.setFont(PDType1Font.TIMES_ROMAN, 30); // 旋转的角度,用弧度表示;水平移动300;纵向移动200 cs.setTextMatrix(Matrix.getRotateInstance(0.6,300f,200f)); cs.showText(ts); cs.endText(); cs.close(); } doc.save(targetPDF); } }
结果:
文件体积:
利用IText
<dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.13.1</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> </dependency>
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.PdfReader; import com.itextpdf.text.pdf.PdfStamper; import java.io.FileInputStream; import java.io.FileOutputStream; public class PDFWaterMark { public static void main(String[] args) throws Exception { useIText(); } private static void useIText() throws Exception { // 水印文字 String ts = "给PDF加水印"; FileInputStream sourcePDF = new FileInputStream("20210331165837838.pdf"); FileOutputStream targetPDF = new FileOutputStream("20210331165837838-watermark-itext.pdf"); PdfReader reader = new PdfReader(sourcePDF); PdfStamper stamp = new PdfStamper(reader, targetPDF); // 用自定义字体 BaseFont font = BaseFont.createFont("华康少女文字简W5.ttc,1", BaseFont.IDENTITY_H, true); // 源PDF文件的总页数 int pageSize = reader.getNumberOfPages(); for (int i = 1; i <= pageSize; i++) { // 水印在之前文本下 PdfContentByte under = stamp.getUnderContent(i); under.beginText(); // 颜色 RGBA under.setColorFill(new BaseColor(197f,0f,35f,50)); // 字体 under.setFontAndSize(font, 38); // under.setTextMatrix(300, 200); // 文字居中;水印文字;X坐标;Y坐标;旋转角度 under.showTextAligned(Element.ALIGN_CENTER, ts, 300, 200, 45); under.endText(); } stamp.close(); } }
结果
文件体积:
IText比PDFBox要好,即使引入外部字体文件,最终生成的PDF体积没有明显变化
扩展,关于颜色
参考:https://www.colormatters.com/color-and-design/color-systems-rgb-and-cmyk
印刷颜色选择:https://htmlcolors.com/