Java使用pdfbox实现给pdf文件加图片水印

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

Java使用pdfbox实现给pdf文件加图片水印

初窥门径   2022-11-16 我要评论

引入依赖

<dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.27</version>
        </dependency>

代码

调节参数:图片宽高,旋转角度,几行几列 等等

package sjp.demo.workutils.utils;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.blend.BlendMode;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
import org.apache.pdfbox.util.Matrix;

import java.io.File;
import java.io.IOException;

public class PdfUtils {

    public static void main(String[] args) throws IOException {
        String file = "D:\\workspaces\\demo\\sjp-work-utils\\src\\main\\resources\\pdf\\阿拉丁统计平台SDK接入指南.pdf";
        String imgPath = "D:\\workspaces\\demo\\sjp-work-utils\\src\\main\\resources\\imgs\\logo.png";
        addImgWatermark(file, imgPath);

    }

    public static void addImgWatermark(String filePath, String imgPath) throws IOException {
        String name = filePath.substring(filePath.lastIndexOf(File.separator), filePath.lastIndexOf(".pdf"));
        String folder = filePath.substring(0, filePath.lastIndexOf(File.separator));
        File file = new File(filePath);
        try (PDDocument doc = PDDocument.load(file)) {
            PDImageXObject pdImage = PDImageXObject.createFromFile(imgPath, doc);

            WatermarkOptions options = new WatermarkOptions()
                    .size(120, 60)
                    .padding(20)
                    .layout(4, 3)
                    // 建议0-90度
                    .rotate(30);

            for (PDPage page : doc.getPages()) {
                addImgWatermark(doc, page, pdImage, options);
            }
            doc.save(folder + File.separator + name + "_WaterMark.pdf");
        }

    }

    private static void addImgWatermark(PDDocument doc, PDPage page, PDImageXObject pdImage, WatermarkOptions options) throws IOException {
        try (
                PDPageContentStream cs = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true, true)
        ) {
            float width = page.getMediaBox().getWidth();
            float height = page.getMediaBox().getHeight();
//            System.out.println("width=" + width + ",height=" + height);

            //有一些pdf页面是有角度翻转的,修正一下
            int rotation = page.getRotation();
//            System.out.println("page.getRotation()=" + rotation);
            switch (rotation) {
                case 90:
                    width = page.getMediaBox().getHeight();
                    height = page.getMediaBox().getWidth();
                    cs.transform(Matrix.getRotateInstance(Math.toRadians(90), height, 0));
                    break;
                case 180:
                    cs.transform(Matrix.getRotateInstance(Math.toRadians(180), width, height));
                    break;
                case 270:
                    width = page.getMediaBox().getHeight();
                    height = page.getMediaBox().getWidth();
                    cs.transform(Matrix.getRotateInstance(Math.toRadians(270), 0, width));
                    break;
                default:
                    break;
            }

            PDExtendedGraphicsState gs = new PDExtendedGraphicsState();
            gs.setNonStrokingAlphaConstant(0.2f);// 设置透明度
            gs.setAlphaSourceFlag(true);
            gs.setBlendMode(BlendMode.NORMAL);
            cs.setGraphicsStateParameters(gs);

            int row = options.row;
            int column = options.column;
            float imgWidth = options.width;
            float imgHeight = options.height;
            float padding = options.padding;
            int degree = options.degree;

            // 计算获得每个单元格的宽高
            float cellWidth = (width - padding * 2) / column;
            float cellHeight = (height - padding * 2) / row;
//            System.out.println("cellWidth=" + cellWidth + ",cellHeight=" + cellHeight);

            // 偏移量,如果单元格宽高大于图片宽高,这可以使图片居中
            float xOffset = padding + (cellWidth - imgWidth) / 2;
            float yOffset = padding + (cellHeight - imgHeight) / 2;

            float x;
            float y;
            for (int i = 0; i < row; i++) {
                y = i * cellHeight + yOffset; 

                for (int j = 0; j < column; j++) {
                    x = j * cellWidth + xOffset;

                    // 旋转导致的x位置修正
                    x += Math.sin(Math.toRadians(degree)) * imgHeight;

//                    System.out.println((int) x + "," + (int) y);

                    Matrix matrix = new Matrix();
                    // 先移位
                    matrix.translate(x, y);
                    // 旋转
                    matrix.rotate(Math.toRadians(degree));
                    // 修改尺寸(必须在旋转后面,否则会变形)
                    matrix.scale(imgWidth, imgHeight);

                    // 画图
                    cs.drawImage(pdImage, matrix);
                }
            }

        }

    }

    static class WatermarkOptions {
        /**
         * 边距
         */
        float padding = 20;
        /**
         * 图片宽度
         */
        float width;
        /**
         * 图片高度
         */
        float height;
        /**
         * 旋转角度
         */
        int degree = 0;
        /**
         * 行数
         */
        int row = 1;
        /**
         * 列数
         */
        int column = 1;

        public WatermarkOptions() {

        }

        public WatermarkOptions padding(int p) {
            if (p < 10) {
                throw new IllegalArgumentException("边距不能小于0");
            }
            this.padding = p;
            return this;
        }

        public WatermarkOptions layout(int row, int column) {
            if (row <= 0 || column <= 0) {
                throw new IllegalArgumentException("行数或列数必须大于0");
            }
            this.row = row;
            this.column = column;

            return this;
        }

        public WatermarkOptions size(float width, float height) {
            this.width = width;
            this.height = height;
            return this;
        }

        public WatermarkOptions rotate(int degree) {
            this.degree = degree;
            return this;
        }

    }

}

效果

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们