java pdfbox3.0.1截取pdf,添加图片,文字水印,水印旋转。自定义字体,pdf转jpg模糊问题记录

1,读取pdf文件,读取自己需要的页数

try (PDDocument document = Loader.loadPDF(new RandomAccessReadBuffer(inputStream))) {
             //pageList为需要的pdf页码
            if (!CollectionUtils.isEmpty(pageList)) {
                PDDocument destinationDocument = new PDDocument();
                // 抽取传入的页
                for (Integer i : pageList) {
                    //大于pdf页数的无效配置
                    if (i > document.getNumberOfPages()) {
                        continue;
                    }
                    PDPage page = document.getPage(i - 1);
                    destinationDocument.addPage(page);
                }
                //**添加水印,必须先添加到新的文档对象中再进行水印添加,不能直接添加page对象,字体不会复制
                //添加水印方法
                extracted(destinationDocument, vo);
                // 保存修改后的 PDF 文件
                destinationDocument.save(new File(outFilePath));
                destinationDocument.close();
            } 
        } catch (IOException e) {
            logger.error("水印添加失败:{}", e.getMessage());
          
        }

1.1 上面的代码会有pdf最后一页没有水印的问题(不知道原因)

        解决方案是在原pdf上操作删除不需要的页码

//提取需要的页数
            if (!CollectionUtils.isEmpty(pageList)) {
                for (int i = document.getNumberOfPages()-1; i >=0; i--) {
                    if (!pageList.contains(i+1)) {
                        //删除不需要的页
                        document.removePage(i);
                    }
                }
            }

2,读取本地字体

 //读取本地字体
InputStream inputStream = new Object() {
      public InputStream getPath() {
         return Objects.requireNonNull(this.getClass().
          getResourceAsStream("/font/字体.ttf"));
            }
        }.getPath();
 PDType0Font font = PDType0Font.load(document, inputStream);

 读取resource文件夹下的字体。此工具类是静态方法需要这样读取,如果是注入方式可以换其他方式

3,pdf添加水印

 此处代码实现水印3*3三等份居中显示,根据自己需求改动x,y坐标。

 // 遍历 PDF 中的所有页面
        for (int i = 0; i < document.getNumberOfPages(); i++) {
            PDPage page = document.getPage(i);
            // 获取页面的宽和高
            float width = page.getMediaBox().getWidth();
            float height = page.getMediaBox().getHeight();
            PDPageContentStream contentStream = new PDPageContentStream(document, page,
                    PDPageContentStream.AppendMode.APPEND, true, true);
            // 设置字体和字号
            contentStream.setFont(font, vo.getFontSize());
            // 设置颜色
            contentStream.setNonStrokingColor(new Color(vo.getRed(), vo.getGreed(), vo.getBlue()));
            //透明度
            PDExtendedGraphicsState extendedGraphicsState = new PDExtendedGraphicsState();
            extendedGraphicsState.setNonStrokingAlphaConstant(vo.getTransparency());
            extendedGraphicsState.setAlphaSourceFlag(true);
            extendedGraphicsState.setBlendMode(BlendMode.NORMAL);
            contentStream.setGraphicsStateParameters(extendedGraphicsState);
            //长宽分成三等分,取中心点
            float startY = height / 3 / 2;
            float startX = width / 3 / 2;
            // 获取水印文字的宽度和高度取中心点
            float textWidth = font.getStringWidth(vo.getTxtData()) / 1000 * vo.getFontSize() / 2;
            float textHeight = font.getFontDescriptor().getCapHeight() / 1000 * vo.getFontSize() / 2;
            //读取水印图片
            PDImageXObject pdImageObject = null;
            float picWidth = 0;
            float picHeight = 0;
            if (!ObjectUtils.isEmpty(vo.getImgData())) {
                //读取图片
                Path tempPath = Files.write(Paths.get(rootSrc), Base64.decode(vo.getImgData()));
                pdImageObject = PDImageXObject.createFromFileByExtension(tempPath.toFile(), document);
                //图片的宽高
                picWidth = pdImageObject.getWidth();
                picHeight = pdImageObject.getHeight();
            }
            //平铺 3*3,不平铺居中显示
            float y = startY;
            for (int j = 1; j <= 3; j++) {
                float x = startX;
                if (!vo.getLayFlag() && j != 2) {
                    y = y + startY * 2;
                    continue;
                }
                for (int k = 1; k <= 3; k++) {
                    if (!vo.getLayFlag() && k != 2) {
                        x = x + startX * 2;
                        continue;
                    }
                /*
                  旋转需要先偏移中心点,后旋转,再偏移回来
                 */
                    Matrix rotateInstance = Matrix.getTranslateInstance(x - textWidth, y - textHeight);
                    //文字设置
                    rotateInstance.translate(textWidth, textHeight);
                    rotateInstance.rotate(Math.toRadians(vo.getRotation()));
                    rotateInstance.translate(-textWidth, -textHeight);
                    //图片设置
                    if (!ObjectUtils.isEmpty(vo.getImgData())) {
                        Matrix picRotateInstance = Matrix.getTranslateInstance(x  - picWidth/2, y - picHeight / 2);
                        picRotateInstance.translate(picWidth / 2, picHeight / 2);
                        picRotateInstance.rotate(Math.toRadians(vo.getRotation()));
                        picRotateInstance.translate(-picWidth / 2, -picHeight / 2);
                        picRotateInstance.scale(picWidth, picHeight);
                        contentStream.drawImage(pdImageObject, picRotateInstance);
                    }
                    // 添加文本水印
                    contentStream.beginText();
                    contentStream.setTextMatrix(rotateInstance);
                    //水印内容
                    contentStream.showText(vo.getTxtData());
                    contentStream.endText();
                    x = x + startX * 2;
                }
                y = y + startY * 2;
            }
            contentStream.close();
        }

vo参数定义:

如果前端传入的是16进制编码可以用Color.decode(“#0000FF”)转换成rgb格式。

    @Schema(title = "RGB编码:红色")
    private int red;
    @Schema(title = "RGB编码:绿色")
    private int greed;
    @Schema(title = "RGB编码:蓝色")
    private int blue;

    @Schema(title = "文本内容")
    private String txtData;

    @Schema(title = "字体大小")
    private Integer fontSize;

    @Schema(title = "内容透明度")
    private Float transparency;

    @Schema(title = "内容旋转角度")
    private Integer rotation;

    @Schema(title = "是否平铺")
    private Boolean layFlag;

    @Schema(title = "图片base64编码")
    private String imgData;

4,pdf转jpg模糊

读取pdf时定义dpi为300解决

BufferedImage bufferedImage = pdfRenderer.renderImageWithDPI(i,300, ImageType.RGB);

  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值