WaterMarkUtils.java 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. package com.caimei.modules.archive.utils;
  2. import com.itextpdf.text.*;
  3. import com.itextpdf.text.Rectangle;
  4. import com.itextpdf.text.pdf.*;
  5. import com.thinkgem.jeesite.common.config.Global;
  6. import groovy.util.logging.Slf4j;
  7. import org.apache.poi.POIXMLDocument;
  8. import org.apache.poi.hwpf.HWPFDocument;
  9. import org.apache.poi.openxml4j.opc.OPCPackage;
  10. import org.apache.poi.sl.usermodel.PictureData;
  11. import org.apache.poi.sl.usermodel.PictureData.PictureType;
  12. import org.apache.poi.ss.usermodel.*;
  13. import org.apache.poi.xslf.usermodel.*;
  14. import org.apache.poi.xssf.usermodel.XSSFRelation;
  15. import org.apache.poi.xssf.usermodel.XSSFSheet;
  16. import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  17. import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
  18. import org.apache.poi.xwpf.usermodel.XWPFDocument;
  19. import org.apache.poi.xwpf.usermodel.XWPFHeader;
  20. import org.apache.poi.xwpf.usermodel.XWPFParagraph;
  21. import org.slf4j.Logger;
  22. import org.slf4j.LoggerFactory;
  23. import schemasMicrosoftComVml.CTShape;
  24. import javax.imageio.ImageIO;
  25. import javax.swing.*;
  26. import java.awt.Color;
  27. import java.awt.Font;
  28. import java.awt.*;
  29. import java.awt.Image;
  30. import java.awt.font.FontRenderContext;
  31. import java.awt.geom.Rectangle2D;
  32. import java.awt.image.BufferedImage;
  33. import java.io.*;
  34. import java.lang.reflect.Field;
  35. /**
  36. * Description
  37. *
  38. * @author : Charles
  39. * @date : 2021/9/18
  40. */
  41. public class WaterMarkUtils {
  42. private final static String outPath = Global.getConfig("archive.tempPath");
  43. /**
  44. * 日志对象
  45. */
  46. private static Logger log = LoggerFactory.getLogger(WaterMarkUtils.class);
  47. // 水印透明度
  48. private static float alpha = 0.5f;
  49. // 水印之间的间隔
  50. private static final int XMOVE = 200;
  51. // 水印之间的间隔
  52. private static final int YMOVE = 200;
  53. public static void main(String[] args) {
  54. /*addPictureWaterMark("D:\\WorkSpace\\file\\img.jpg", "D:\\WorkSpace\\file\\temp\\img1.jpg", "我是水印");
  55. setPictureWatermark("D:\\WorkSpace\\file\\img.jpg", "D:\\WorkSpace\\file\\temp\\img2.jpg", Color.GRAY, "我是水印");
  56. // setWordWaterMark("D:\\WorkSpace\\file\\test.doc", "D:\\WorkSpace\\file\\temp\\test.doc", "我是水印", "doc");
  57. setWordWaterMark("D:\\WorkSpace\\file\\test.docx", "D:\\WorkSpace\\file\\temp\\test.docx", "我是水印", "docx");
  58. setPdfWatermark("D:\\WorkSpace\\file\\test.pdf", "D:\\WorkSpace\\file\\temp\\test.pdf", "我是水印");
  59. // setExcelWaterMark("D:\\WorkSpace\\file\\test.xls", "D:\\WorkSpace\\file\\temp\\test.xls", "我是水印");
  60. // setPPTWaterMark("D:\\WorkSpace\\file\\test.ppt", "D:\\WorkSpace\\file\\temp\\test.ppt", "我是水印");
  61. setPPTWaterMark("D:\\WorkSpace\\file\\test.pptx", "D:\\WorkSpace\\file\\temp\\test.pptx", "我是水印");
  62. */}
  63. /**
  64. * @param srcImgPath 源图片路径
  65. * @param tarImgPath 保存的图片路径
  66. * @param waterMarkContent 水印内容
  67. */
  68. public static void addPictureWaterMark(String srcImgPath, String tarImgPath,
  69. String waterMarkContent) {
  70. FileOutputStream outImgStream = null;
  71. try {
  72. // 读取原图片信息
  73. File srcImgFile = new File(srcImgPath);// 得到文件
  74. Image srcImg = ImageIO.read(srcImgFile);// 文件转化为图片
  75. int srcImgWidth = srcImg.getWidth(null);// 获取图片的宽
  76. int srcImgHeight = srcImg.getHeight(null);// 获取图片的高
  77. // 加水印
  78. BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight,
  79. BufferedImage.TYPE_INT_RGB);
  80. Graphics2D g = bufImg.createGraphics();
  81. // 设置对线段的锯齿状边缘处理
  82. g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
  83. RenderingHints.VALUE_INTERPOLATION_BILINEAR);
  84. g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
  85. // 设置水印旋转
  86. g.rotate(Math.toRadians(-40),
  87. (double) bufImg.getWidth() / 2,
  88. (double) bufImg.getHeight() / 2);
  89. g.setColor(new Color(107, 109, 106)); // 根据图片的背景设置水印颜色
  90. Font font = new Font("宋体", Font.PLAIN, 20);
  91. g.setFont(font); // 设置字体
  92. // 设置水印文字透明度
  93. // g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,alpha));
  94. //根据不同的像素判断多个水印还是单个水印300*300
  95. if (srcImgWidth > 300 && srcImgHeight > 300) {
  96. //多个水印
  97. // 设置水印的坐标
  98. int x = -srcImgWidth / 2;
  99. int y = -srcImgHeight / 2;
  100. int markWidth = font.getSize() * getTextLength(waterMarkContent);// 字体长度
  101. int markHeight = font.getSize();// 字体高度
  102. // 循环添加水印
  103. while (x < srcImgWidth * 1.5) {
  104. y = -srcImgHeight / 2;
  105. while (y < srcImgHeight * 1.5) {
  106. g.drawString(waterMarkContent, x, y);
  107. y += markHeight + YMOVE;
  108. }
  109. x += markWidth + XMOVE;
  110. }
  111. } else {
  112. //单个水印
  113. int x = (srcImgWidth - getWatermarkLength(waterMarkContent, g)) / 2;
  114. int y = srcImgHeight / 2;
  115. g.drawString(waterMarkContent, x, y);
  116. }
  117. g.dispose();
  118. // 输出图片
  119. outImgStream = new FileOutputStream(tarImgPath);
  120. String formatName = srcImgPath.substring(srcImgPath.lastIndexOf(".") + 1, srcImgPath.length());
  121. ImageIO.write(bufImg, formatName, outImgStream);
  122. outImgStream.flush();
  123. } catch (Exception e) {
  124. log.error("addPictureWatermark fail", e);
  125. // throw new MyException(ResultCode.FAILURE, "addPictureWatermark fail");
  126. } finally {
  127. if (outImgStream != null) {
  128. try {
  129. outImgStream.close();
  130. } catch (IOException e) {
  131. e.printStackTrace();
  132. }
  133. }
  134. }
  135. }
  136. /**
  137. * 图片添加水印
  138. *
  139. * @param srcImgPath 需要添加水印的图片的路径
  140. * @param outImgPath 添加水印后图片输出路径
  141. * @param markContentColor 水印文字的颜色
  142. * @param waterMarkContent 水印的文字
  143. */
  144. public static void setPictureWatermark(String srcImgPath, String outImgPath, Color markContentColor, String waterMarkContent) {
  145. FileOutputStream outImgStream = null;
  146. try {
  147. // 读取原图片信息
  148. File srcImgFile = new File(srcImgPath);
  149. Image srcImg = ImageIO.read(srcImgFile);
  150. int srcImgWidth = srcImg.getWidth(null);
  151. int srcImgHeight = srcImg.getHeight(null);
  152. // 加水印
  153. BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
  154. Graphics2D g = bufImg.createGraphics();
  155. g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
  156. Font font = new Font("宋体", Font.BOLD, srcImgHeight / 6);
  157. //根据图片的背景设置水印颜色
  158. g.setColor(markContentColor);
  159. //设置旋转角度
  160. g.rotate(Math.toRadians(-45), (double) bufImg.getWidth() / 2, (double) bufImg.getHeight() / 2);
  161. //设置水印透明度
  162. g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.2F));
  163. g.setFont(font);
  164. int x = (srcImgWidth - getWatermarkLength(waterMarkContent, g)) / 2;
  165. int y = srcImgHeight / 2;
  166. g.drawString(waterMarkContent, x, y);
  167. g.dispose();
  168. // 输出图片
  169. outImgStream = new FileOutputStream(outImgPath);
  170. ImageIO.write(bufImg, "jpg", outImgStream);
  171. outImgStream.flush();
  172. outImgStream.close();
  173. } catch (Exception e) {
  174. log.error("setPictureWatermark fail", e);
  175. // throw new MyException(ResultCode.FAILURE, "setPictureWatermark fail");
  176. } finally {
  177. if (outImgStream != null) {
  178. try {
  179. outImgStream.close();
  180. } catch (IOException e) {
  181. e.printStackTrace();
  182. }
  183. }
  184. }
  185. }
  186. /**
  187. * word文字水印
  188. *
  189. * @param markStr
  190. */
  191. public static void setWordWaterMark(File inputFile, String markStr,String filePath, String fileType) {
  192. if ("docx".equals(fileType)) {
  193. //2003doc 用HWPFDocument ; 2007doc 用 XWPFDocument
  194. XWPFDocument doc = null;
  195. try {
  196. // OPCPackage pack = POIXMLDocument.openPackage(inputPath);
  197. // doc = new XWPFDocument(pack);
  198. doc = new XWPFDocument(new FileInputStream(inputFile));
  199. // doc = new XWPFDocument(new FileInputStream(inputFile));
  200. } catch (FileNotFoundException e) {
  201. log.error("setWordWaterMark fail: 源文件不存在", e);
  202. // throw new MyException(ResultCode.FAILURE, "setWordWaterMark fail: 源文件不存在");
  203. } catch (IOException e) {
  204. log.error("setWordWaterMark fail: 读取源文件IO异常", e);
  205. // throw new MyException(ResultCode.FAILURE, "setWordWaterMark fail: 读取源文件IO异常");
  206. } catch (Exception e) {
  207. log.error("setWordWaterMark fail: 不支持的文档格式", e);
  208. // throw new MyException(ResultCode.FAILURE, "setWordWaterMark fail: 不支持的文档格式");
  209. }
  210. XWPFParagraph paragraph = doc.createParagraph();
  211. XWPFHeaderFooterPolicy headerFooterPolicy = doc.getHeaderFooterPolicy();
  212. if (headerFooterPolicy == null) {
  213. headerFooterPolicy = doc.createHeaderFooterPolicy();
  214. }
  215. // create default Watermark - fill color black and not rotated
  216. headerFooterPolicy.createWatermark(markStr);
  217. // get the default header
  218. // Note: createWatermark also sets FIRST and EVEN headers
  219. // but this code does not updating those other headers
  220. XWPFHeader header = headerFooterPolicy.getHeader(XWPFHeaderFooterPolicy.DEFAULT);
  221. paragraph = header.getParagraphArray(0);
  222. // // get com.microsoft.schemas.vml.CTShape where fill color and rotation is set
  223. // paragraph.getCTP().newCursor();
  224. // System.out.println(paragraph.getCTP().getRArray(0));
  225. // System.out.println(paragraph.getCTP().getRArray(0).getPictArray(0));
  226. org.apache.xmlbeans.XmlObject[] xmlobjects = paragraph.getCTP().getRArray(0).getPictArray(0).selectChildren(
  227. new javax.xml.namespace.QName("urn:schemas-microsoft-com:vml", "shape"));
  228. if (xmlobjects.length > 0) {
  229. com.microsoft.schemas.vml.CTShape ctshape = (com.microsoft.schemas.vml.CTShape) xmlobjects[0];
  230. ctshape.setFillcolor("#D3D3D3");
  231. ctshape.setStyle(ctshape.getStyle() + ";rotation:315" + ";height:60pt;width:360pt");
  232. }
  233. File file = new File(outPath + filePath);
  234. if (!file.exists()) {
  235. try {
  236. file.createNewFile();
  237. } catch (IOException e) {
  238. log.error("setWordWaterMark fail: 创建输出文件IO异常", e);
  239. // throw new MyException(ResultCode.FAILURE, "setWordWaterMark fail: 创建输出文件失败");
  240. }
  241. }
  242. try {
  243. doc.write(new FileOutputStream(outPath + filePath));
  244. } catch (FileNotFoundException e) {
  245. log.error("setWordWaterMark fail: 输出文件不存在", e);
  246. // throw new MyException(ResultCode.FAILURE, "setWordWaterMark fail: 创建输出文件失败");
  247. } catch (IOException e) {
  248. log.error("setWordWaterMark fail: ", e);
  249. // throw new MyException(ResultCode.FAILURE, "setWordWaterMark fail");
  250. } finally {
  251. if (doc != null) {
  252. try {
  253. doc.close();
  254. } catch (IOException e) {
  255. e.printStackTrace();
  256. }
  257. }
  258. }
  259. }
  260. }
  261. /**
  262. * pdf设置文字水印
  263. *
  264. * @param inputPath
  265. * @param outPath
  266. * @param markStr
  267. */
  268. public static void setPdfWatermark(String inputPath, String outPath, String markStr) {
  269. File file = new File(outPath);
  270. if (!file.exists()) {
  271. try {
  272. file.createNewFile();
  273. } catch (IOException e) {
  274. log.error("setPdfWatermark fail: 创建输出文件IO异常", e);
  275. // throw new MyException(ResultCode.FAILURE, "setPdfWatermark fail: 创建输出文件IO异常");
  276. }
  277. }
  278. BufferedOutputStream bufferOut = null;
  279. try {
  280. bufferOut = new BufferedOutputStream(new FileOutputStream(file));
  281. } catch (FileNotFoundException e) {
  282. log.error("setPdfWatermark fail: 源文件不存在", e);
  283. // throw new MyException(ResultCode.FAILURE, "setPdfWatermark fail: 源文件不存在");
  284. }
  285. PdfStamper stamper = null;
  286. int total = 0;
  287. PdfContentByte content;
  288. Rectangle pageSizeWithRotation = null;
  289. BaseFont base = null;
  290. PdfReader reader = null;
  291. try {
  292. reader = new PdfReader(inputPath);
  293. //解决PdfReader not opened with owner password
  294. Field f = PdfReader.class.getDeclaredField("ownerPasswordUsed");
  295. f.setAccessible(true);
  296. f.set(reader, Boolean.TRUE);
  297. stamper = new PdfStamper(reader, bufferOut);
  298. total = reader.getNumberOfPages() + 1;
  299. base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
  300. } catch (IOException e) {
  301. log.error("setPdfWatermark fail:", e);
  302. // throw new MyException(ResultCode.FAILURE, "setPdfWatermark fail");
  303. } catch (DocumentException e) {
  304. log.error("setPdfWatermark fail:", e);
  305. // throw new MyException(ResultCode.FAILURE, "setPdfWatermark fail");
  306. } catch (IllegalAccessException e) {
  307. e.printStackTrace();
  308. } catch (NoSuchFieldException e) {
  309. e.printStackTrace();
  310. }
  311. // 获取水印文字的高度和宽度
  312. int textH = 0, textW = 0;
  313. JLabel label = new JLabel();
  314. label.setText(markStr);
  315. FontMetrics metrics = label.getFontMetrics(label.getFont());
  316. textH = metrics.getHeight();
  317. textW = metrics.stringWidth(label.getText());
  318. PdfGState gs = new PdfGState();
  319. for (int i = 1; i < total; i++) {
  320. //在内容上方加水印
  321. content = stamper.getOverContent(i);
  322. gs.setFillOpacity(0.5f);
  323. content.saveState();
  324. content.setGState(gs);
  325. content.beginText();
  326. // content.setRGBColorFill(0, 0, 0);
  327. content.setFontAndSize(base, 20);
  328. // 获取每一页的高度、宽度
  329. pageSizeWithRotation = reader.getPageSizeWithRotation(i);
  330. float pageHeight = pageSizeWithRotation.getHeight();
  331. float pageWidth = pageSizeWithRotation.getWidth();
  332. // 根据纸张大小多次添加, 水印文字成30度角倾斜
  333. for (int height = -5 + textH; height < pageHeight; height = height + YMOVE) {
  334. for (int width = -5 + textW; width < pageWidth + textW; width = width + XMOVE) {
  335. content.showTextAligned(Element.ALIGN_LEFT, markStr, width - textW, height - textH, 30);
  336. }
  337. }
  338. content.endText();
  339. }
  340. try {
  341. stamper.close();
  342. bufferOut.flush();
  343. bufferOut.close();
  344. reader.close();
  345. } catch (IOException e) {
  346. log.error("setPdfWatermark fail:", e);
  347. // throw new MyException(ResultCode.FAILURE, "setPdfWatermark fail");
  348. } catch (DocumentException e) {
  349. log.error("setPdfWatermark fail:", e);
  350. // throw new MyException(ResultCode.FAILURE, "setPdfWatermark fail");
  351. }
  352. }
  353. /**
  354. * excel设置水印
  355. *
  356. * @param inputPath
  357. * @param outPath
  358. * @param markStr
  359. */
  360. public static void setExcelWaterMark(String inputPath, String outPath, String markStr) {
  361. //读取excel文件
  362. XSSFWorkbook workbook = null;
  363. try {
  364. workbook = new XSSFWorkbook(new FileInputStream(inputPath));
  365. } catch (FileNotFoundException e) {
  366. log.error("setExcelWaterMark fail: 源文件不存在", e);
  367. // throw new MyException(ResultCode.FAILURE, "setExcelWaterMark fail: 源文件不存在");
  368. } catch (IOException e) {
  369. log.error("setExcelWaterMark fail: 读取源文件IO异常", e);
  370. //throw new MyException(ResultCode.FAILURE, "setExcelWaterMark fail: 读取源文件IO异常");
  371. }
  372. OutputStream fos = null;
  373. ByteArrayOutputStream os = null;
  374. try {
  375. //获取水印
  376. os = getImage(markStr);
  377. int pictureIdx = workbook.addPicture(os.toByteArray(), Workbook.PICTURE_TYPE_PNG);
  378. for (int i = 0; i < workbook.getNumberOfSheets(); i++) {//获取每个Sheet表
  379. XSSFSheet sheet1 = workbook.getSheetAt(i);
  380. String rID = sheet1.addRelation(null, XSSFRelation.IMAGES, workbook.getAllPictures().get(pictureIdx)).getRelationship().getId();
  381. //set background picture to sheet
  382. sheet1.getCTWorksheet().addNewPicture().setId(rID);
  383. }
  384. // Excel文件生成后存储的位置。
  385. File file = new File(outPath);
  386. fos = new FileOutputStream(file);
  387. workbook.write(fos);
  388. } catch (Exception e) {
  389. log.error("setExcelWaterMark fail: 创建输出文件IO异常", e);
  390. // throw new MyException(ResultCode.FAILURE, "setExcelWaterMark fail: 创建输出文件IO异常");
  391. } finally {
  392. if (os != null) {
  393. try {
  394. os.close();
  395. } catch (IOException e) {
  396. e.printStackTrace();
  397. }
  398. }
  399. if (fos != null) {
  400. try {
  401. fos.close();
  402. } catch (IOException e) {
  403. e.printStackTrace();
  404. }
  405. }
  406. if (workbook != null) {
  407. try {
  408. workbook.close();
  409. } catch (IOException e) {
  410. e.printStackTrace();
  411. }
  412. }
  413. }
  414. }
  415. /**
  416. * PPT设置水印
  417. *
  418. * @param path
  419. * @param targetpath
  420. * @param markStr
  421. * @throws IOException
  422. */
  423. public static void setPPTWaterMark(String path, String targetpath, String markStr) {
  424. XMLSlideShow slideShow = null;
  425. try {
  426. slideShow = new XMLSlideShow(new FileInputStream(path));
  427. } catch (IOException e) {
  428. log.error("setPPTWaterMark fail:", e);
  429. // throw new MyException(ResultCode.FAILURE, "setPPTWaterMark fail:获取PPT文件失败");
  430. }
  431. ByteArrayOutputStream os = null;
  432. FileOutputStream out = null;
  433. try {
  434. //获取水印
  435. os = getImage(markStr);
  436. PictureData pictureData1 = slideShow.addPicture(os.toByteArray(), PictureType.PNG);
  437. for (XSLFSlide slide : slideShow.getSlides()) {
  438. XSLFPictureShape pictureShape = slide.createPicture(pictureData1);
  439. // pictureShape.setAnchor(new java.awt.Rectangle(250, 0, 500, 500));
  440. pictureShape.setAnchor(pictureShape.getAnchor());
  441. }
  442. out = new FileOutputStream(targetpath);
  443. slideShow.write(out);
  444. } catch (IOException e) {
  445. log.error("setPPTWaterMark fail:" + e);
  446. // throw new MyException(ResultCode.FAILURE, "setPPTWaterMark fail:生成ppt文件失败");
  447. } finally {
  448. if (slideShow != null) {
  449. try {
  450. slideShow.close();
  451. } catch (IOException e) {
  452. e.printStackTrace();
  453. }
  454. }
  455. if (out != null) {
  456. try {
  457. out.close();
  458. } catch (IOException e) {
  459. e.printStackTrace();
  460. }
  461. }
  462. if (os != null) {
  463. try {
  464. os.close();
  465. } catch (IOException e) {
  466. e.printStackTrace();
  467. }
  468. }
  469. }
  470. }
  471. /**
  472. * 获取水印文字总长度
  473. *
  474. * @param waterMarkContent 水印的文字
  475. * @param g
  476. * @return 水印文字总长度
  477. */
  478. public static int getWatermarkLength(String waterMarkContent, Graphics2D g) {
  479. return g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0, waterMarkContent.length());
  480. }
  481. /**
  482. * 获取文本长度。汉字为1:1,英文和数字为2:1
  483. */
  484. private static int getTextLength(String text) {
  485. int length = text.length();
  486. for (int i = 0; i < text.length(); i++) {
  487. String s = String.valueOf(text.charAt(i));
  488. if (s.getBytes().length > 1) {
  489. length++;
  490. }
  491. }
  492. length = length % 2 == 0 ? length / 2 : length / 2 + 1;
  493. return length;
  494. }
  495. /**
  496. * 获取水印文字图片流
  497. *
  498. * @param text
  499. * @return
  500. */
  501. private static ByteArrayOutputStream getImage(String text) {
  502. ByteArrayOutputStream os = new ByteArrayOutputStream();
  503. try {
  504. // 导出到字节流B
  505. BufferedImage image = createWaterMarkImageBig(text);
  506. ImageIO.write(image, "png", os);
  507. } catch (IOException e) {
  508. log.error("getImage fail: 创建水印图片IO异常", e);
  509. // throw new MyException(ResultCode.FAILURE, "getImage fail: 创建水印图片IO异常");
  510. }
  511. return os;
  512. }
  513. /**
  514. * 根据文字生成水印图片(大号 平铺)
  515. *
  516. * @param text
  517. * @return
  518. */
  519. public static BufferedImage createWaterMarkImageBig(String text) {
  520. Integer width = 1000;
  521. Integer height = 800;
  522. BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 获取bufferedImage对象
  523. Font font = new Font("宋体", Font.PLAIN, 70);
  524. Graphics2D g2d = image.createGraphics();
  525. image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
  526. g2d.dispose();
  527. g2d = image.createGraphics();
  528. //设置字体颜色和透明度
  529. g2d.setColor(new Color(0, 0, 0, 60));
  530. //设置字体
  531. g2d.setStroke(new BasicStroke(1));
  532. //设置字体类型 加粗 大小
  533. g2d.setFont(font);
  534. //设置倾斜度
  535. g2d.rotate(Math.toRadians(-30), (double) image.getWidth() / 2, (double) image.getHeight() / 2);
  536. FontRenderContext context = g2d.getFontRenderContext();
  537. Rectangle2D bounds = font.getStringBounds(text, context);
  538. double x = (width - bounds.getWidth()) / 2;
  539. double y = (height - bounds.getHeight()) / 2;
  540. double ascent = -bounds.getY();
  541. double baseY = y + ascent;
  542. //写入水印文字原定高度过小,所以累计写水印,增加高度
  543. g2d.drawString(text, (int) x, (int) baseY);
  544. //设置透明度
  545. g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
  546. //释放对象
  547. g2d.dispose();
  548. return image;
  549. }
  550. public static void addWaterMark(File inputFile, String markStr, String filePath, String fileType) {
  551. if (fileType.contains("doc")) {
  552. setWordWaterMark(inputFile, markStr, filePath, fileType);
  553. }
  554. }
  555. }