企业级-PDF图片水印

作者:fyupeng
技术专栏:☞ https://github.com/fyupeng
项目地址:☞ https://github.com/fyupeng/distributed-blog-system-api


留给读者

遇到签名,往往很无奈签名的位置、大小。

一、介绍

直接提供PDF路径和图片路径,以及输出路径,就可以完成需要的需求,关键字也可以作为参数传入,根据自行需求修改。

二、代码

public class PdfBuilderUtil {public static void imageWatermark(String inputPath, String outputPath,String imagePath) throws IOException, com.itextpdf.text.DocumentException {PdfReader reader = new PdfReader(inputPath);PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(outputPath));PdfGState gs1 = new PdfGState();gs1.setFillOpacity(0.1f);InputStream imageIS = new FileInputStream(imagePath);Image image = Image.getInstance(IOUtils.toByteArray(imageIS));int n = reader.getNumberOfPages();InputStream inputStream = new FileInputStream(inputPath);PDDocument document = PDDocument.load(inputStream);for(int i=1;i<=n;i++){PdfContentByte pdfContentByte = stamp.getOverContent(i);// 默认图片水印大小,详见盖章右下角大小样例image.scalePercent(75f);// 默认图片水印横坐标,详见盖章右下角横坐标float absoluteX = 370;// 默认图片水印纵坐标,高度中间位置float absoluteY = (PageSize.POSTCARD.getHeight() - image.getScaledHeight())/2;float[] xyz = getKeyWords(reader, "盖章位置");if (xyz != null && xyz.length >= 3) {//新版文书absoluteY = xyz[1];} else {//旧版文书float[] oldXyz = getKeyWords(reader, "其他位置");if (oldXyz != null && oldXyz.length >= 3) {absoluteY = oldXyz[2]+300;}}// 读取图像文件PDFTextStripper stripper = new PDFTextStripper();stripper.setStartPage(i); // Page indexes are 1-based in PDFTextStripperstripper.setEndPage(i);String text = stripper.getText(document);if (!text.trim().isEmpty()) {image.setAbsolutePosition(absoluteX, absoluteY);pdfContentByte.addImage(image);}}inputStream.close();imageIS.close();stamp.close();reader.close();}/*** 根据关键字定位* @param pdfReader* @param keyWords* @return*/public  static float[] getKeyWords(PdfReader pdfReader, String keyWords) {float[] coordinate = null;int page = 0;try{int pageNum = pdfReader.getNumberOfPages();PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(pdfReader);CustomRenderListener renderListener = new CustomRenderListener();renderListener.setKeyWord(keyWords);for (page = 1; page <= pageNum; page++) {renderListener.setPage(page);pdfReaderContentParser.processContent(page, renderListener);coordinate = renderListener.getPcoordinate();if (coordinate != null) break;}} catch (IOException e) {e.printStackTrace();}return coordinate;}}

pdf签名帮助类

public class CustomRenderListener implements RenderListener{private float[] pcoordinate = null;private String keyWord;private int page;public int getPage() {return page;}public void setPage(int page) {this.page = page;}public float[] getPcoordinate(){return pcoordinate;}public String getKeyWord() {return keyWord;}public void setKeyWord(String keyWord) {this.keyWord = keyWord;}@Overridepublic void beginTextBlock() {}@Overridepublic void endTextBlock() {}@Overridepublic void renderImage(ImageRenderInfo arg0) {}@Overridepublic void renderText(TextRenderInfo textRenderInfo) {String text = textRenderInfo.getText();if (null != text && text.contains(keyWord)) {Float boundingRectange = textRenderInfo.getBaseline().getBoundingRectange();pcoordinate = new float[3];pcoordinate[0] = boundingRectange.x;pcoordinate[1] = boundingRectange.y;pcoordinate[2] = page;}}
}

三、总结

简洁、高效、精炼!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/48616.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RK RGA _MMU unsupported memory larger then 4G!问题解决

使用RGA程序,长时间运行的过程中出现了rga_mm: RGA_MMU unsupported memory larger than 4G! rga_mm: RGA_MMU unsupported memory larger than 4G! rga_mm: scheduler core[4] unsupported mm_flag[0x8]! rga_mm: rga_mm_map_buffer map virtual address error! rga_mm: job…

华为云.云日志服务LTS及其基本使用

云计算 云日志服务LTS及其基本使用 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550…

2024最新版虚拟便携空调小程序源码 支持流量主切换空调型号

产品截图 部分源代码展示 urls.js Object.defineProperty(exports, "__esModule", {value: !0 }), exports.default ["9c5f1fa582bee88300ffb7e28dce8b68_3188_128_128.png", "E-116154b04e91de689fb1c4ae99266dff_960.svg", "573eee719…

酱酒七个轮次口感与特点,哪个轮次最好喝?

都知道酱香型白酒是按照“12987”工艺酿造而成,这12987便是以一整年为一个生产周期,中间经历润沙下沙,并在多次的蒸煮发酵后,完成七次取酒。 所以酱香型白酒是由7个轮次的基酒勾调而成的,这七轮次酒口感特点各不相同,品质也是有着极大的差异。而这各个轮次基酒的勾调配比又直接…

【踩坑日记26】Connection timed out fatal: expected flush after ref listing ```

问题描述 (base) XXXomega:/home/XXX/code$ git clone https://github.com/comeeasy/DALS.git Cloning into DALS... error: RPC failed; curl 28 Failed to connect to github.com port 443: Connection timed out fatal: expected flush after ref listing解决方法 直接换一…

mysql的索引、事务和存储引擎

目录 索引 索引的概念 索引的作用 作用 索引的副作用 创建索引 创建索引的原则和依据 索引的类型 创建索引 查看索引 删除索引 drop 主键索引 普通索引 添加普通索引 唯一索引 添加唯一索引 组合索引 添加组合索引 查询组合索引 全文索引 添加全文索引 …

构建高效Node.js中间层:探索请求合并转发的艺术

&#x1f389; 博客主页&#xff1a;【剑九 六千里-CSDN博客】 &#x1f3a8; 上一篇文章&#xff1a;【CSS盒模型&#xff1a;掌握网页布局的核心】 &#x1f3a0; 系列专栏&#xff1a;【面试题-八股系列】 &#x1f496; 感谢大家点赞&#x1f44d;收藏⭐评论✍ 引言&#x…

深度学习简介(框架)

目录 1. 深度学习简介1.1 历史背景1.2 核心原理1.3 应用领域1.4 技术挑战1.5 未来趋势 2. 深度学习与传统机器学习2.1 深度学习的原理2.2 深度学习的优势2.3 深度学习的应用2.4 深度学习的挑战2.5 深度学习的未来 3. 深度学习的关键技术3.1 神经网络基础3.2 卷积神经网络&#…

java中的常量池

类文件常量池 类文件结构概览 一个Java类文件的大致结构如下&#xff1a; 魔数&#xff08;Magic Number&#xff09;&#xff1a;标识文件类型&#xff0c;值为0xCAFEBABE。 版本号&#xff08;Version&#xff09;&#xff1a;次版本号和主版本号。 常量池&#xff08;Cons…

接口测试JMeter-1.接口测试初识

第一章 接口测试初识 1. 接口测试理论基础 “接口测试”一个让人觉得非常高大上的名词&#xff0c;特别是对于刚入门的测试同学而言。随着测试技术不断的深化&#xff0c;“接口测试”出现在我们视野中的频次越来越高。那么接口测试到底是如何做的&#xff1f;接口测试的优势又…

Flowable-SpringBoot项目集成

在前面的介绍中&#xff0c;虽然实现了绘制流程图&#xff0c;然后将流程图存储到数据库中&#xff0c;然后从数据库中获取流程信息&#xff0c;并部署和启动流程&#xff0c;但是部署的流程绘制器是在tomcat中部署的&#xff0c;可能在部分的项目中&#xff0c;需要我们将流程…

Windows图形界面(GUI)-DLG-C/C++ - 月历控件(MonthCalendar)

公开视频 -> 链接点击跳转公开课程博客首页 -> e​​​​​​链接点击跳转博客主页 目录 月历控件(MonthCalendar) 使用场景 控件操作 月历控件(MonthCalendar) 使用场景 日程安排&#xff1a;用户可以通过月历控件选择特定的日期来安排会议或活动。事件管理&#x…

<数据集>pcb板缺陷检测数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;693张 标注数量(xml文件个数)&#xff1a;693 标注数量(txt文件个数)&#xff1a;693 标注类别数&#xff1a;6 标注类别名称&#xff1a;[missing_hole, mouse_bite, open_circuit, short, spurious_copper, spur…

git 提交的进阶操作

cherry-pick cherry-pick 是 Git 中的一种操作,允许你从一个分支中选择特定的 commit,并将其应用到另一个分支。它的主要用途是将特定的更改引入到其他分支,而无需合并整个分支历史。这在修复 bug 或者移植某些功能时特别有用。 cherry-pick 的使用场景 Bug 修复: 例如,你…

Python面试宝典第16题:跳跃游戏

题目 给你一个非负整数数组 nums &#xff0c;你最初位于数组的第一个下标 &#xff0c;数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true。否则&#xff0c;返回 false。 示例 1&#xff1a; 输…

detection_segmentation

目标检测和实例分割(OBJECT_DETECTION AND INSTANCE SEGMENTATION) 文章目录 目标检测和实例分割(OBJECT_DETECTION AND INSTANCE SEGMENTATION)一. 计算机视觉(AI VISION)1. 图像分类2. 目标检测与定位3. 语义分割和实例分割目标检测算法可以分为两大类&#xff1a; R-CNN生成…

Linux系统:揭开它神秘面纱的科普之旅

在这个数字化时代&#xff0c;电脑和手机成了我们生活中不可或缺的一部分。而提到这些设备的操作系统&#xff0c;大家可能首先想到的是Windows、macOS或是Android。 但你知道吗&#xff0c;在技术的海洋里&#xff0c;还有一个强大而灵活的操作系统家族&#xff0c;它就是Lin…

python-多任务编程

2. 多任务编程 2.1 多任务概述 多任务 即操作系统中可以同时运行多个任务。比如我们可以同时挂着qq&#xff0c;听音乐&#xff0c;同时上网浏览网页。这是我们看得到的任务&#xff0c;在系统中还有很多系统任务在执行,现在的操作系统基本都是多任务操作系统&#xff0c;具备…

XML Schema 复合类型 - 仅含元素

XML Schema 复合类型 - 仅含元素 引言 XML Schema 是一种用于定义 XML 文档结构和内容的语言。它提供了一种强大的方式来描述 XML 文档中允许的元素和属性,以及它们之间的关系。在 XML Schema 中,复合类型是一种重要的概念,它允许开发者定义包含其他元素或属性的复杂结构。…

JVM--HostSpot算法细节实现

1.根节点枚举 定义&#xff1a; 我们以可达性分析算法中从GC Roots 集合找引用链这个操作作为介绍虚拟机高效实现的第一个例 子。固定可作为GC Roots 的节点主要在全局性的引用&#xff08;例如常量或类静态属性&#xff09;与执行上下文&#xff08;例如 栈帧中的本地变量表&a…