ImageUtils.java 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. package com.ruoyi.common.utils.file;
  2. import com.ruoyi.common.config.RuoYiConfig;
  3. import com.ruoyi.common.constant.Constants;
  4. import com.ruoyi.common.utils.StringUtils;
  5. import net.coobird.thumbnailator.Thumbnails;
  6. import org.apache.poi.util.IOUtils;
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9. import javax.imageio.ImageIO;
  10. import java.awt.*;
  11. import java.awt.image.BufferedImage;
  12. import java.io.*;
  13. import java.net.URL;
  14. import java.net.URLConnection;
  15. import java.util.Arrays;
  16. /**
  17. * 图片处理工具类
  18. *
  19. * @author ruoyi
  20. */
  21. public class ImageUtils {
  22. private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);
  23. public static byte[] getImage(String imagePath) {
  24. InputStream is = getFile(imagePath);
  25. try {
  26. return IOUtils.toByteArray(is);
  27. } catch (Exception e) {
  28. log.error("图片加载异常 {}", e);
  29. return null;
  30. } finally {
  31. IOUtils.closeQuietly(is);
  32. }
  33. }
  34. public static InputStream getFile(String imagePath) {
  35. try {
  36. byte[] result = readFile(imagePath);
  37. result = Arrays.copyOf(result, result.length);
  38. return new ByteArrayInputStream(result);
  39. } catch (Exception e) {
  40. log.error("获取图片异常 {}", e);
  41. }
  42. return null;
  43. }
  44. /**
  45. * 读取文件为字节数据
  46. *
  47. * @param url 地址
  48. * @return 字节数据
  49. */
  50. public static byte[] readFile(String url) {
  51. InputStream in = null;
  52. try {
  53. if (url.startsWith("http")) {
  54. // 网络地址
  55. URL urlObj = new URL(url);
  56. URLConnection urlConnection = urlObj.openConnection();
  57. urlConnection.setConnectTimeout(30 * 1000);
  58. urlConnection.setReadTimeout(60 * 1000);
  59. urlConnection.setDoInput(true);
  60. in = urlConnection.getInputStream();
  61. } else {
  62. // 本机地址
  63. String localPath = RuoYiConfig.getProfile();
  64. String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX);
  65. in = new FileInputStream(downloadPath);
  66. }
  67. return IOUtils.toByteArray(in);
  68. } catch (Exception e) {
  69. log.error("获取文件路径异常 {}", e);
  70. return null;
  71. } finally {
  72. IOUtils.closeQuietly(in);
  73. }
  74. }
  75. /**
  76. * 添加图片水印
  77. *
  78. * @param sourceFile 文件源路径
  79. * @param destFile 文件路径
  80. * @param watermarkText1 水印信息上
  81. * @param watermarkText2 水印信息下
  82. * @throws Exception 异常
  83. */
  84. public static void addWatermark(File sourceFile, File destFile, String watermarkText1, String watermarkText2) throws Exception {
  85. // 读取图片
  86. BufferedImage image = ImageIO.read(sourceFile);
  87. // 获取图片宽高
  88. int width = image.getWidth();
  89. int height = image.getHeight();
  90. // 创建 Graphics2D 对象
  91. Graphics2D g2d = (Graphics2D) image.getGraphics();
  92. g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  93. // 根据图片大小调整字体大小
  94. int fontSize = Math.max(width, height) / 40; // 字体大小为图片较大边长的 1/20
  95. g2d.setFont(new Font("SimHei", Font.BOLD, fontSize));
  96. // g2d.setColor(new Color(255, 255, 255, 128)); // 白色半透明
  97. // 计算水印文本宽高
  98. FontMetrics fontMetrics = g2d.getFontMetrics();
  99. // 第一行水印的宽高
  100. int textWidth1 = fontMetrics.stringWidth(watermarkText1);
  101. int textHeight = fontMetrics.getHeight(); // 每行的高度
  102. // 第二行水印的宽度
  103. int textWidth2 = fontMetrics.stringWidth(watermarkText2);
  104. // 计算水印的位置(右下角,分两行)
  105. int padding = width / 50; // 边距
  106. int x1 = width - textWidth1 - padding; // 第一行水平位置
  107. int x2 = width - textWidth2 - padding; // 第二行水平位置
  108. int y1 = height - textHeight - padding; // 第一行垂直位置
  109. int y2 = height - padding; // 第二行垂直位置
  110. // 分析水印区域的背景颜色(取样水印区域的平均颜色)
  111. Color averageColor = getAverageColor(image, x1, y1 - textHeight, textWidth1, textHeight + (y2 - y1));
  112. // 判断背景颜色是否浅色或深色
  113. Color watermarkColor = isLightColor(averageColor) ? new Color(0, 0, 0, 180) : new Color(255, 255, 255, 128);
  114. // 设置水印颜色
  115. g2d.setColor(watermarkColor);
  116. // 绘制两行水印
  117. g2d.drawString(watermarkText1, x1, y1);
  118. g2d.drawString(watermarkText2, x2, y2);
  119. g2d.dispose();
  120. // 保存处理后的图片
  121. // ImageIO.write(image, "jpg", destFile);
  122. String format = sourceFile.getName().substring(sourceFile.getName().lastIndexOf(".") + 1);
  123. ImageIO.write(image, format, destFile);
  124. }
  125. /**
  126. * 判断颜色是否为浅色
  127. *
  128. * @param color 颜色
  129. * @return true 表示浅色,false 表示深色
  130. */
  131. private static boolean isLightColor(Color color) {
  132. // 使用加权公式计算亮度
  133. double brightness = (color.getRed() * 0.299 + color.getGreen() * 0.587 + color.getBlue() * 0.114);
  134. return brightness > 128; // 亮度大于128为浅色
  135. }
  136. /**
  137. * 获取指定区域的平均颜色
  138. *
  139. * @param image 图片
  140. * @param x 起始横坐标
  141. * @param y 起始纵坐标
  142. * @param width 区域宽度
  143. * @param height 区域高度
  144. * @return 平均颜色
  145. */
  146. private static Color getAverageColor(BufferedImage image, int x, int y, int width, int height) {
  147. int r = 0, g = 0, b = 0, count = 0;
  148. for (int i = x; i < x + width && i < image.getWidth(); i++) {
  149. for (int j = y; j < y + height && j < image.getHeight(); j++) {
  150. Color pixelColor = new Color(image.getRGB(i, j));
  151. r += pixelColor.getRed();
  152. g += pixelColor.getGreen();
  153. b += pixelColor.getBlue();
  154. count++;
  155. }
  156. }
  157. return new Color(r / count, g / count, b / count);
  158. }
  159. /**
  160. * 生成缩略图并进行压缩
  161. *
  162. * @param originalImagePath 原始图片路径
  163. * @param thumbImagePath 缩略图保存路径
  164. * @param width 缩略图宽度
  165. * @param height 缩略图高度
  166. * @param quality 压缩质量,范围0-1,值越低压缩越厉害
  167. * @throws IOException IO异常
  168. */
  169. public static void compressAndGenerateThumbnail(String originalImagePath, String thumbImagePath, int width, int height, float quality) throws IOException {
  170. // 压缩图片并生成缩略图
  171. Thumbnails.of(new File(originalImagePath))
  172. .size(width, height) // 设置缩略图的宽高
  173. .outputQuality(quality) // 设置图片压缩质量
  174. .toFile(new File(thumbImagePath)); // 输出文件
  175. }
  176. }