1 说明

本文主要针对图片和PDF的水印操作设计了四种场景,下图为几个示例

2 实现

针对上述四个场景分别实现如下,首先,引入依赖,因为对图片的水印操作只需要使用JDK自带的功能即可,主要引入的依赖是iText的依赖包。其次,设计一个参数类方便调用本服务时参数传递与接收。之后设计了一个文件属性类方便提取MultipartFile对象传递过来的文件名和文件类型。

     <dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13</version></dependency>

水印参数类

import com.itextpdf.text.BaseColor;
import lombok.Data;import java.awt.*;/*** 文字水印参数** @author 一朝风月* @date 2021/8/3 14:23*/
@Data
public class WaterMarkerParams {/*** 水印内容*/private String mark;/*** 水印颜色*/private Color color;/*** 字体*/private String font;/*** 水印字体大小*/private int fontSize;/*** 水印位置 0:右下角,1:居中,9:自定义坐标*/private int position;/*** 文字样式, 1:居中,2:铺满*/private int align;/*** 文字倾斜角度*/private int angle;/*** x坐标*/private int x;/*** y坐标*/private int y;/*** 旋转角度*/private Integer degree;/*** 透明度*/private float transparency;/*** 不透明度*/private float opacity;/*** PDF水印颜色*/private BaseColor baseColor;/*** 视图宽*/private float fitWidth;/*** 视图高*/private float fitHeight;/*** pdf图片放置X轴*/private float pdfX;/*** pdf图片放置Y轴*/private float pdfY;public WaterMarkerParams() {this.mark = "";this.color = Color.white;this.fontSize = 9;this.font = "宋体";this.position = 0;this.transparency = 0.3f;this.opacity = 0.2f;this.baseColor = BaseColor.BLACK;this.fitWidth = 200;this.fitHeight = 200;this.pdfX = 200;this.pdfY = 206;this.align = 1;this.angle = 30;}
}

文件属性类

import lombok.Data;/*** 文件属性** @author 一朝风月* @date 2021/8/4 16:34*/
@Data
public class FileProps {private String fileName;private String fileType;public FileProps(String fileSrcName) {if (fileSrcName.contains(".") && fileSrcName != null) {int location = fileSrcName.lastIndexOf(".");this.fileName = fileSrcName.substring(0, location);this.fileType = fileSrcName.substring(location + 1);} else {this.fileName = "";this.fileType = "";}}
}

2.1 为图片添加文字水印

 /*** 文字水印** @param file                图片* @param params              水印参数* @param httpServletResponse 响应* @return 加文字后的图片* @throws IOException IO异常*/@PostMapping("text")public Result mText(MultipartFile file, WaterMarkerParams params, HttpServletResponse httpServletResponse) throws IOException {FileProps fileProps = new FileProps(file.getOriginalFilename());if (!"pic".equalsIgnoreCase(ExtService.getCategory(fileProps.getFileType()))) {return Result.error("请传入图片格式的文件!");}Image srcImg = ImageIO.read(file.getInputStream());int srcImgWidth = srcImg.getWidth(null);int srcImgHeight = srcImg.getHeight(null);BufferedImage bufferedImage = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);Graphics2D g = bufferedImage.createGraphics();g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);Font font = new Font(params.getFont(), Font.PLAIN, params.getFontSize());g.setColor(params.getColor());g.setFont(font);if (params.getX() > srcImgWidth || params.getY() > srcImgHeight) {return Result.error("传入x,y坐标超出图片尺寸!");}if (params.getPosition() == 0) {params.setX(srcImgWidth - getWatermarkLength(params.getMark(), g) - 3);params.setY(srcImgHeight - 3);}if (params.getPosition() == 1) {params.setX((srcImgWidth - getWatermarkLength(params.getMark(), g)) / 2);params.setY(srcImgHeight / 2);}g.drawString(params.getMark(), params.getX(), params.getY());g.dispose();// 输出图片httpServletResponse.setContentType("application/*");httpServletResponse.setHeader("Content-Disposition", "attachment;filename=\"" + fileProps.getFileName() + "\"");ImageIO.write(bufferedImage, fileProps.getFileType(), httpServletResponse.getOutputStream());//测试图片代码
//        FileOutputStream outImgStream = new FileOutputStream("D:\\test\\" + UuidUtil.getUuid() + "." + fileType);
//        ImageIO.write(bufferedImage, fileType, outImgStream);
//        outImgStream.flush();
//        outImgStream.close();return null;}

2.2 为图片添加图片水印

 /*** 图片水印** @param srcImage            图片* @param iconImage           水印图片* @param params              水印参数* @param httpServletResponse 响应* @return 加水印的图片* @throws IOException IO异常*/@PostMapping("picture")public Result mPicture(MultipartFile srcImage, MultipartFile iconImage, WaterMarkerParams params,HttpServletResponse httpServletResponse) throws IOException {FileProps fileProps = new FileProps(srcImage.getOriginalFilename());Image srcImg = ImageIO.read(srcImage.getInputStream());Image iconImg = ImageIO.read(iconImage.getInputStream());BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null), srcImg.getHeight(null),BufferedImage.TYPE_INT_RGB);Graphics2D g = buffImg.createGraphics();g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);int srcImgWidth = srcImg.getWidth(null);int srcImgHeight = srcImg.getHeight(null);int iconImgWidth = iconImg.getWidth(null);int iconImgHeight = iconImg.getHeight(null);if (params.getX() > srcImgWidth || params.getY() > srcImgHeight) {return Result.error("传入x,y坐标超出图片尺寸!");}if (params.getPosition() == 0) {params.setX(srcImgWidth - iconImgWidth);params.setY(srcImgHeight - iconImgHeight);}if (params.getPosition() == 1) {params.setX(srcImgWidth / 2 - iconImgWidth / 2);params.setY(srcImgHeight / 2 - iconImgHeight / 2);}if (params.getPosition() == 2) {params.setX(0);params.setY(0);}g.drawImage(srcImg.getScaledInstance(srcImgWidth, srcImgHeight, Image.SCALE_SMOOTH), 0,0, null);if (null != params.getDegree()) {g.rotate(Math.toRadians(params.getDegree()), (double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2);}ImageIcon imgIcon = new ImageIcon(iconImage.getBytes());Image img = imgIcon.getImage();// 透明度g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, params.getTransparency()));g.drawImage(img, params.getX(), params.getY(), null);g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));g.dispose();httpServletResponse.setContentType("application/*");httpServletResponse.setHeader("Content-Disposition", "attachment;filename=\"" + fileProps.getFileName() + "\"");ImageIO.write(buffImg, fileProps.getFileType(), httpServletResponse.getOutputStream());// 生成图片
//        FileOutputStream outImgStream = new FileOutputStream("D:\\test\\" + UuidUtil.getUuid() + "." + fileType);
//        ImageIO.write(buffImg, fileType, outImgStream);
//        outImgStream.flush();
//        outImgStream.close();return null;}

2.3 PDF添加文字水印

     /*** PDF增加水印** @return 加文字后的PDF*/@PostMapping("pdfText")public Result mPdfText(MultipartFile file, WaterMarkerParams params,HttpServletResponse httpServletResponse) throws IOException, DocumentException {FileProps fileProps = new FileProps(file.getOriginalFilename());PdfReader reader = new PdfReader(file.getInputStream());
//        FileOutputStream outImgStream = new FileOutputStream("D:\\test\\" + UuidUtil.getUuid() + "."
//                + fileProps.getFileType());httpServletResponse.setContentType("application/*");httpServletResponse.setHeader("Content-Disposition", "attachment;filename=\"" + fileProps.getFileName() + "\"");PdfStamper stamper = new PdfStamper(reader, httpServletResponse.getOutputStream());int total = reader.getNumberOfPages() + 1;PdfContentByte content;BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);PdfGState gs = new PdfGState();for (int i = 1; i < total; i++) {content = stamper.getOverContent(i);gs.setFillOpacity(params.getOpacity());content.beginText();content.setColorFill(BaseColor.LIGHT_GRAY);content.setFontAndSize(base, params.getFontSize());if (params.getAlign() == 1) {content.setTextMatrix(70, 200);content.showTextAligned(Element.ALIGN_CENTER, params.getMark(), 300, 350, params.getAngle());}if (params.getAlign() == 2) {// 间隔int interval = -5;// 获取水印文字的高度和宽度int textH, textW;JLabel label = new JLabel();label.setText(params.getMark());FontMetrics metrics = label.getFontMetrics(label.getFont());textH = metrics.getHeight();textW = metrics.stringWidth(label.getText());// 获取每一页的高度、宽度com.itextpdf.text.Rectangle pageSizeWithRotation = reader.getPageSizeWithRotation(i);float pageHeight = pageSizeWithRotation.getHeight();float pageWidth = pageSizeWithRotation.getWidth();// 根据纸张大小多次添加, 水印文字成30度角倾斜for (int height = interval + textH; height < pageHeight; height = height + textH * 3) {for (int width = interval + textW; width < pageWidth + textW; width = width + textW * 2) {content.showTextAligned(Element.ALIGN_LEFT, params.getMark(), width - textW, height - textH, 30);}}}content.endText();}stamper.close();return null;}

2.4 PDF添加图片水印

     /*** PDF增加图片水印** @return 加图片水印后的PDF*/@PostMapping("pdfPicture")public Result mPdfPicture(MultipartFile file, MultipartFile iconImage, WaterMarkerParams params,HttpServletResponse httpServletResponse) throws IOException, DocumentException {FileProps fileProps = new FileProps(file.getOriginalFilename());PdfReader reader = new PdfReader(file.getInputStream());httpServletResponse.setContentType("application/*");httpServletResponse.setHeader("Content-Disposition", "attachment;filename=\"" + fileProps.getFileName() + "\"");PdfStamper stamper = new PdfStamper(reader, httpServletResponse.getOutputStream());int total = reader.getNumberOfPages() + 1;PdfContentByte content;PdfGState gs = new PdfGState();for (int i = 1; i < total; i++) {content = stamper.getOverContent(i);gs.setFillOpacity(params.getOpacity());content.beginText();com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(iconImage.getBytes());image.setAbsolutePosition(params.getPdfX(), params.getPdfY());image.scaleToFit(params.getFitWidth(), params.getFitHeight());content.addImage(image);content.endText();}stamper.close();return null;}

2.5 如何有既加文字又加图片的情况,那就调用两次接口吧

3 测试

测试后的图和说明中的那幅图一样。

Java 水印操作的设计与实现相关推荐

  1. Java 签章操作的设计与实现

    1 说明 本文主要讲解使用Java和SpringBoot框架设计实现对PDF的签章操作.实现对PDF的签章操作不是简单的找个图片贴到PDF上即可,而是需要申请数字证书才能对PDF签章,否则无法验证签章 ...

  2. Java图形化界面设计——容器(JFrame)

    Java图形化界面设计--容器(JFrame) 程序是为了方便用户使用的,因此实现图形化界面的程序编写是所有编程语言发展的必然趋势,在命令提示符下运行的程序可以让我们了解java程序的基本知识体系结构 ...

  3. java字符串操作_Java的字符串操作

    Java的字符串操作 小型送分题:Java有字符串(String),StringBuffer(字符串缓存),StringBuilder(字符串建造者?)各种实现,究其原因还是历史上的各种坑. 一.不同 ...

  4. Java反射:框架设计的灵魂

    Java反射:框架设计的灵魂 框架:办成品软件,可以在框架的基础上进行开发 反射:将类的各个部分封装成对象,这就是反射机制 反射的好处 在程序运行的过程中,操作这些对象 可以降低程序的耦合性,提高程序 ...

  5. java技术论坛的毕业设计_基于java的bbs论坛设计,软件毕业设计

    基于java的bbs论坛设计,软件毕业设计 XXX毕 业 设 计 任 务 书专业 软件技术 年级 xx 级 班级 二班姓名 xx 学号 20 xx0205xx3威 海 职 业 学 院 教 务 处 编 ...

  6. Java Spring MVC分层设计

    Java Spring MVC分层设计 第一次尝试着用Java做Web开发,使用了Java Spring框架,顺便说一句,如果使用Spring开发,建议使用STS(Spring Tool Suite) ...

  7. java 解析/操作 xml 几种常用方式 xml的增加/删除/修改

    java 解析/操作 xml 几种常用方式 xml的增加/删除/修改 首先,我们先介绍几种常用的xml解析器. 1. 介绍 1)DOM(JAXP Crimson解析器) DOM是用与平台和语言无关的方 ...

  8. JAVA高级应用课程设计(网上书城系统——会员登陆模块的设计与实现)

    课程设计报告 课   程  名   称: JAVA高级应用课程设计 设   计  题   目:网上书城系统--会员登陆模块的设计与实现 目 录 一.开发背景. 1 (一)背景概述. 1 (二)发展前景 ...

  9. 一种基于加密域的数字图像水印算法的设计与实现(附Matlab源码)

    一种基于加密域的数字图像水印算法的设计与实现 项目介绍 毕设项目 题目:一种基于加密域的数字图像水印算法的设计与实现 随着数字媒体技术的发展,数字媒体版权的保护得到了越来越多人的重视,数字水印技术作为 ...

  10. Java拼图游戏总结,Java拼图游戏课程设计报告

    Java拼图游戏课程设计报告 JavaJava 程序设计与应用开发 课程设计报告程序设计与应用开发 课程设计报告 设计题目 拼图大作战 学生姓名 学生班级 学生学号 指导教师 完成时间2016 年 0 ...

最新文章

  1. iPhone开发:类似iChat的聊天泡泡示例
  2. 数据加密类型及创建和申请CA证书
  3. css text-align-last设置末尾文本对齐方式
  4. 【秒懂】号称最为简明实用的Django上手教程
  5. 如何平衡存储系统的一致性和可用性?
  6. Android版添加phonegap-银联支付插件教程
  7. java guava 使用_使用Guava操作基本类型
  8. 【报告分享】2021新茶饮研究报告.pdf(附下载链接)
  9. 【Tensorflow】图像的读取、解码、显示、处理、编码、保存
  10. tcp程序——回声客户端
  11. 无偏移谷歌瓦片地址_下载谷歌高清无偏移卫星地图
  12. 保存网页图片的八种方法
  13. Windows的计划任务
  14. 高效C++ Effective C++
  15. 51单片机DS18B20测温LCD12864显示
  16. 传说中WM手机工程测试命令
  17. 【蓝桥杯备赛笔记 02】费解的开关
  18. 2021-04-06-MSF之永恒之蓝
  19. 计算机策略编辑器,组策略及组策略编辑器基础知识
  20. 世界首个拥有肌肉骨骼机器人问世(组图)

热门文章

  1. 没有服务器认证消息,关于《跑跑卡丁车》没有服务器认证消息的问题,怎么解决?...
  2. 服务器文件安全扫描,服务器安全扫描工具
  3. 不知如何选股?不知哪种指标策略可靠?量化分析比较DMA、DMI、MACD、KDJ、BOLL指标策略收益情况
  4. 【2017.11.16】外包单报价
  5. 聚合搜索V3.0泛解析泛目录站群源码 MIP自动推送 SEO功能SEO源码
  6. java file exists用法_Java File exists()方法
  7. linux批量化删除以某某结尾命令
  8. matlab锂电池充电电路,锂离子电池充放电电路模型及其仿真.doc
  9. 学习计划 -- 实时更新
  10. 常用LINUX配置及SHELL命令集锦-SHELL命令