AddWatermarkUtil.java 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. package com.ruoyi.common.utils;
  2. import org.apache.commons.compress.utils.IOUtils;
  3. import org.apache.commons.fileupload.FileItem;
  4. import org.apache.commons.fileupload.disk.DiskFileItemFactory;
  5. import org.springframework.http.MediaType;
  6. import org.springframework.web.multipart.MultipartFile;
  7. import org.springframework.web.multipart.commons.CommonsMultipartFile;
  8. import javax.imageio.ImageIO;
  9. import java.awt.*;
  10. import java.awt.font.FontRenderContext;
  11. import java.awt.font.TextLayout;
  12. import java.awt.geom.AffineTransform;
  13. import java.awt.image.BufferedImage;
  14. import java.io.*;
  15. /**
  16. * @ProjectName: test
  17. * @Package: com.test.utils
  18. * @ClassName: MyTest
  19. * @Author: ***
  20. * @Description:
  21. * @Date: 2020/10/29 11:48
  22. * @Version: 1.0
  23. */
  24. public class AddWatermarkUtil {
  25. public static void waterPress(File srcImgFile, File outputFile,
  26. Color markContentColor, int fontSize, String waterMarkContent) {
  27. try {
  28. String[] waterMarkContents = waterMarkContent.split("\\|\\|");
  29. // 读取原图片信息
  30. Image srcImg = ImageIO.read(srcImgFile);
  31. int srcImgWidth = srcImg.getWidth(null);
  32. int srcImgHeight = srcImg.getHeight(null);
  33. // 加水印
  34. BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
  35. // 得到画笔对象
  36. Graphics2D g = bufImg.createGraphics();
  37. // 设置起点
  38. g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
  39. Font font = new Font("Default", Font.PLAIN, fontSize);
  40. // 水印透明度
  41. g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5F));
  42. // 根据图片的背景设置水印颜色
  43. g.setColor(markContentColor);
  44. // 设置水印文字字体
  45. g.setFont(font);
  46. // 数组长度
  47. int contentLength = waterMarkContents.length;
  48. // 获取水印文字中最长的
  49. int maxLength = 0;
  50. for (int i = 0; i < contentLength; i++) {
  51. int fontlen = getWatermarkLength(waterMarkContents[i], g);
  52. if (maxLength < fontlen) {
  53. maxLength = fontlen;
  54. }
  55. }
  56. for (int j = 0; j < contentLength; j++) {
  57. waterMarkContent = waterMarkContents[j];
  58. int tempX = 10;
  59. int tempY = fontSize;
  60. // 单字符长度
  61. int tempCharLen = 0;
  62. // 单行字符总长度临时计算
  63. int tempLineLen = 0;
  64. StringBuffer sb = new StringBuffer();
  65. for (int i = 0; i < waterMarkContent.length(); i++) {
  66. char tempChar = waterMarkContent.charAt(i);
  67. tempCharLen = getCharLen(tempChar, g);
  68. tempLineLen += tempCharLen;
  69. if (tempLineLen >= srcImgWidth) {
  70. // 长度已经满一行,进行文字叠加
  71. g.drawString(sb.toString(), tempX, tempY);
  72. // 清空内容,重新追加
  73. sb.delete(0, sb.length());
  74. tempLineLen = 0;
  75. }
  76. // 追加字符
  77. sb.append(tempChar);
  78. }
  79. // 通过设置后两个输入参数给水印定位
  80. //右下角
  81. g.drawString(sb.toString(), srcImgWidth - maxLength, srcImgHeight - (contentLength - j - 1) * tempY - 50);
  82. // g.drawString(sb.toString(), 20, srcImgHeight - (contentLength - j - 1) * tempY - 50);
  83. }
  84. g.dispose();
  85. // 输出图片
  86. // 释放资源
  87. g.dispose();
  88. ImageIO.write(bufImg, "PNG", outputFile);
  89. } catch (Exception e) {
  90. e.printStackTrace();
  91. }
  92. }
  93. public static int getCharLen(char c, Graphics2D g) {
  94. return g.getFontMetrics(g.getFont()).charWidth(c);
  95. }
  96. /**
  97. * 获取水印文字总长度
  98. *
  99. * @paramwaterMarkContent水印的文字
  100. * @paramg
  101. * @return水印文字总长度
  102. */
  103. public static int getWatermarkLength(String waterMarkContent, Graphics2D g) {
  104. return g.getFontMetrics(g.getFont()).charsWidth(
  105. waterMarkContent.toCharArray(), 0, waterMarkContent.length());
  106. }
  107. /**
  108. * 添加倾斜水印
  109. *
  110. * @param inputFile 图片
  111. * @param outputFile
  112. * @param text
  113. * @throws IOException
  114. */
  115. public static void addWaterMark(File inputFile, File outputFile, Color markContentColor, int fontSize, String text) throws IOException {
  116. Image image = ImageIO.read(inputFile);
  117. int imgWidth = image.getWidth(null);// 获取图片的宽
  118. int imgHeight = image.getHeight(null);// 获取图片的高
  119. int angel = 315;// 旋转角度
  120. int xpadding = 280;// 每个水印水平间隔
  121. int ypadding = 280;// 每个水印垂直间隔
  122. // int fontSize = 10;
  123. BufferedImage bi = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_ARGB);
  124. Graphics2D g = bi.createGraphics();
  125. g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  126. // 绘制原图片
  127. float alpha = 1F;
  128. AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha);
  129. g.setComposite(ac);
  130. g.drawImage(image, 0, 0, imgWidth, imgHeight, null);
  131. g.setBackground(Color.BLACK);
  132. // 开始绘制水印
  133. // 水印字体
  134. Font font = new Font("Default", Font.BOLD, fontSize);
  135. g.setFont(font);
  136. FontRenderContext frc = g.getFontRenderContext();
  137. TextLayout tl = new TextLayout(text, font, frc);
  138. // 水印串宽度
  139. int stringWidth = g.getFontMetrics(g.getFont()).charsWidth(text.toCharArray(), 0, text.length());
  140. // 旋转水印
  141. g.rotate(Math.toRadians(angel), (double) imgWidth / 2, (double) imgHeight / 2);
  142. // 水印透明度
  143. g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5F));
  144. // 字体色
  145. g.setColor(markContentColor);
  146. int x = -imgHeight / 2;
  147. int y = -imgWidth / 2;
  148. // 循环绘制
  149. while (x < imgWidth + imgHeight / 2) {
  150. y = -imgWidth / 2;
  151. while (y < imgHeight + imgWidth / 2) {
  152. Shape sha = tl.getOutline(AffineTransform.getTranslateInstance(x, y));
  153. g.fill(sha);
  154. y += ypadding;
  155. }
  156. x += stringWidth + xpadding;
  157. }
  158. // 释放资源
  159. g.dispose();
  160. ImageIO.write(bi, "PNG", outputFile);
  161. }
  162. /**
  163. * MultipartFile 转 File
  164. * @param multipartFile
  165. * @return
  166. */
  167. public static File transferToFile(MultipartFile multipartFile) {
  168. //选择用缓冲区来实现这个转换即使用java 创建的临时文件 使用 MultipartFile.transferto()方法 。
  169. File file = null;
  170. try {
  171. String originalFilename = multipartFile.getOriginalFilename();
  172. String[] filename = originalFilename.split("\\.");
  173. file = File.createTempFile(filename[0], filename[1]);
  174. multipartFile.transferTo(file);
  175. file.deleteOnExit();
  176. } catch (IOException e) {
  177. e.printStackTrace();
  178. }
  179. return file;
  180. }
  181. /**
  182. * File 转 MultipartFile
  183. * @param file
  184. * @return
  185. */
  186. public static MultipartFile fileToTransfer(File file) {
  187. FileItem item = new DiskFileItemFactory().createItem("file"
  188. , MediaType.MULTIPART_FORM_DATA_VALUE
  189. , true
  190. , file.getName());
  191. try (InputStream input = new FileInputStream(file);
  192. OutputStream os = item.getOutputStream()) {
  193. // 流转移
  194. IOUtils.copy(input, os);
  195. } catch (Exception e) {
  196. throw new IllegalArgumentException("Invalid file: " + e, e);
  197. }
  198. return new CommonsMultipartFile(item);
  199. }
  200. }