• Java实现添加文字水印、图片水印


    目录

    前言

    一、获取原图片对象信息

    1、读取本地图片

    2、读取网络图片

    二、处理水印

    三、添加水印

    四、获取目标图片

    五、完整工具类

    六、结果展示


    前言

            现在很多人都喜欢在各种平台上分享自己的照片吧,不管是一些制作出来的媒体图片还是精致的人像图片,相信很多小伙伴都会这样。但同时也有一些让人担心的问题,怕有一些人会随意转发图片,或者盗图冒充本人。其实解决这个问题很简单,只要发布之前给图片加个水印就行了。今天分享如何用Java实现添加水印的功能。


    水印可以是图片或者文字,操作方便。

    java实现给图片添加水印实现步骤:

    • 获取原图片对象信息(本地图片或网络图片)

    • 添加水印(设置水印颜色、字体、坐标等)

    • 处理输出目标图片

    一、获取原图片对象信息

    获取图片的方式,通常有两种:

    • 一种是通过下载到本地,从本地读取(本地图片);

    • 另外一种是通过网络地址进行读取(网络图片)

    1、读取本地图片

    通过代码实现读取本地目录下图片,返回的是图片对象,代码如下:

    1. /**
    2. * 读取本地图片
    3. *
    4. * @param path 本地图片存放路径
    5. */
    6. public static Image readLocalPicture(String path) {
    7. if (null == path) {
    8. throw new RuntimeException("本地图片路径不能为空");
    9. }
    10. // 读取原图片信息 得到文件
    11. File srcImgFile = new File(path);
    12. try {
    13. // 将文件对象转化为图片对象
    14. return ImageIO.read(srcImgFile);
    15. } catch (IOException e) {
    16. throw new RuntimeException(e);
    17. }
    18. }

    2、读取网络图片

    1. /**
    2. * 读取网络图片
    3. *
    4. * @param path 网络图片地址
    5. */
    6. public static Image readNetworkPicture(String path) {
    7. if (null == path) {
    8. throw new RuntimeException("网络图片路径不能为空");
    9. }
    10. try {
    11. // 创建一个URL对象,获取网络图片的地址信息
    12. URL url = new URL(path);
    13. // 将URL对象输入流转化为图片对象 (url.openStream()方法,获得一个输入流)
    14. BufferedImage bugImg = ImageIO.read(url.openStream());
    15. if (null == bugImg) {
    16. throw new RuntimeException("网络图片地址不正确");
    17. }
    18. return bugImg;
    19. } catch (IOException e) {
    20. throw new RuntimeException(e);
    21. }
    22. }

    二、处理水印

    通过上面的步骤,我们已经获取到了原始图片信息,下面需要创建一个画笔进行水印的添加及处理。水印包含文字水印、图片水印。

    画笔可以设置水印颜色、字体大小、字体样式等。

    1. /**
    2. * 水印处理
    3. *
    4. * @param image 图片对象
    5. * @param type 水印类型(1-文字水印 2-图片水印)
    6. * @param watermark 水印内容(文字水印内容/图片水印的存放路径)
    7. */
    8. public static void manageWatermark(Image image, Integer type, String watermark) {
    9. int imgWidth = image.getWidth(null);
    10. int imgHeight = image.getHeight(null);
    11. BufferedImage bufImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
    12. // 加水印:
    13. // 创建画笔
    14. Graphics2D graphics = bufImg.createGraphics();
    15. // 绘制原始图片
    16. graphics.drawImage(image, 0, 0, imgWidth, imgHeight, null);
    17. // 校验水印的类型
    18. if (type == 1) {
    19. if (StringUtils.isEmpty(watermark)) {
    20. throw new RuntimeException("文字水印内容不能为空");
    21. }
    22. // 添加文字水印:
    23. // 根据图片的背景设置水印颜色
    24. graphics.setColor(new Color(255, 255, 255, 128));
    25. // 设置字体 画笔字体样式为微软雅黑,加粗,文字大小为45pt
    26. graphics.setFont(new Font("微软雅黑", Font.BOLD, 45));
    27. // 设置水印的坐标(为原图片中间位置)
    28. int x = (imgWidth - getWatermarkLength(watermark, graphics)) / 2;
    29. int y = imgHeight / 2;
    30. // 画出水印 第一个参数是水印内容,第二个参数是x轴坐标,第三个参数是y轴坐标
    31. graphics.drawString(watermark, x, y);
    32. graphics.dispose();
    33. } else {
    34. // 添加图片水印:
    35. if (StringUtils.isEmpty(watermark)) {
    36. throw new RuntimeException("图片水印存放路径不能为空");
    37. }
    38. Image srcWatermark = readLocalPicture(watermark);
    39. int watermarkWidth = srcWatermark.getWidth(null);
    40. int watermarkHeight = srcWatermark.getHeight(null);
    41. // 设置 alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字
    42. graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.9f));
    43. // 绘制水印图片 坐标为中间位置
    44. graphics.drawImage(srcWatermark, (imgWidth - watermarkWidth) / 2,
    45. (imgHeight - watermarkHeight) / 2, watermarkWidth, watermarkHeight, null);
    46. graphics.dispose();
    47. }
    48. }

    getWatermarkLength() 方法用于计算水印内容的长度:

    1. /**
    2. * 获取水印文字的长度
    3. *
    4. * @param watermarkContent 文字水印内容
    5. * @param graphics 图像类
    6. */
    7. private static int getWatermarkLength(String watermarkContent, Graphics2D graphics) {
    8. return graphics.getFontMetrics(graphics.getFont()).charsWidth(watermarkContent.toCharArray(), 0, watermarkContent.length());
    9. }

    Font 字体说明:

    • Font 类的构造函数为:public Font(String familyName, int style, int size)

    • 参数说明:第一个参数为字体类型,第二个参数为字体风格,第三个参数为字体大小

    字体的风格有:

    • Font.PLAIN(普通)

    • Font.BOLD(加粗)

    • Font.ITALIC(斜体)

    • Font.BOLD+Font.ITALIC(粗斜体)

    PS

    1、size字体大小,默认单位是pt(磅),数字越大,字就越大。

    2、需要注意是,水印坐标位置。设置不当,就看不到水印效果。

    三、添加水印

    直接调用上面封装好的方法。

    1. /**
    2. * 添加水印
    3. *
    4. * @param pictureType 图片来源类型(1-本地图片 2-网络图片)
    5. * @param watermarkType 水印类型(1-文字水印 2-图片水印)
    6. * @param path 图片路径
    7. * @param watermark 水印内容(文字水印内容/图片水印的存放路径)
    8. */
    9. public static void addWatermark(Integer pictureType, Integer watermarkType, String path, String watermark) {
    10. if (null == pictureType) {
    11. throw new RuntimeException("图片来源类型不能为空");
    12. }
    13. if (null == watermarkType) {
    14. throw new RuntimeException("水印类型不能为空");
    15. }
    16. Image image;
    17. if (pictureType == 1) {
    18. // 读取本地图片
    19. image = readLocalPicture(path);
    20. } else {
    21. // 读取网络图片
    22. image = readNetworkPicture(path);
    23. }
    24. if (watermarkType == 1) {
    25. // 添加文字水印
    26. manageWatermark(image, 1, watermark);
    27. } else {
    28. // 添加图片水印
    29. manageWatermark(image, 2, watermark);
    30. }
    31. }

    四、获取目标图片

    经过上面的操作后,我们的图片添加文字水印或图片水印就已经处理完成了。但他现在还保存在Java对象中。

    我们想要看得到效果,需要进行处理,保存图片到本地。

    1. // 定义存储的地址
    2. String tarImgPath = "C:/Users/admin/Desktop/watermark.jpg";
    3. // 输出图片
    4. try {
    5. FileOutputStream outImgStream = new FileOutputStream(tarImgPath);
    6. ImageIO.write(bufImg, "png", outImgStream);
    7. outImgStream.flush();
    8. outImgStream.close();
    9. } catch (IOException e) {
    10. throw new RuntimeException(e);
    11. }

    五、完整工具类

    以上代码,我直接整合成一个工具类。

    1. import org.apache.commons.lang3.StringUtils;
    2. import javax.imageio.ImageIO;
    3. import java.awt.*;
    4. import java.awt.image.BufferedImage;
    5. import java.io.File;
    6. import java.io.FileOutputStream;
    7. import java.io.IOException;
    8. import java.net.URL;
    9. /**
    10. * 添加水印util
    11. */
    12. public class WatermarkUtil {
    13. /**
    14. * 读取本地图片
    15. *
    16. * @param path 本地图片存放路径
    17. */
    18. public static Image readLocalPicture(String path) {
    19. if (null == path) {
    20. throw new RuntimeException("本地图片路径不能为空");
    21. }
    22. // 读取原图片信息 得到文件
    23. File srcImgFile = new File(path);
    24. try {
    25. // 将文件对象转化为图片对象
    26. return ImageIO.read(srcImgFile);
    27. } catch (IOException e) {
    28. throw new RuntimeException(e);
    29. }
    30. }
    31. /**
    32. * 读取网络图片
    33. *
    34. * @param path 网络图片地址
    35. */
    36. public static Image readNetworkPicture(String path) {
    37. if (null == path) {
    38. throw new RuntimeException("网络图片路径不能为空");
    39. }
    40. try {
    41. // 创建一个URL对象,获取网络图片的地址信息
    42. URL url = new URL(path);
    43. // 将URL对象输入流转化为图片对象 (url.openStream()方法,获得一个输入流)
    44. BufferedImage bugImg = ImageIO.read(url.openStream());
    45. if (null == bugImg) {
    46. throw new RuntimeException("网络图片地址不正确");
    47. }
    48. return bugImg;
    49. } catch (IOException e) {
    50. throw new RuntimeException(e);
    51. }
    52. }
    53. /**
    54. * 水印处理
    55. *
    56. * @param image 图片对象
    57. * @param type 水印类型(1-文字水印 2-图片水印)
    58. * @param watermark 水印内容(文字水印内容/图片水印的存放路径)
    59. */
    60. public static String manageWatermark(Image image, Integer type, String watermark) {
    61. int imgWidth = image.getWidth(null);
    62. int imgHeight = image.getHeight(null);
    63. BufferedImage bufImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
    64. // 加水印:
    65. // 创建画笔
    66. Graphics2D graphics = bufImg.createGraphics();
    67. // 绘制原始图片
    68. graphics.drawImage(image, 0, 0, imgWidth, imgHeight, null);
    69. // 校验水印的类型
    70. if (type == 1) {
    71. if (StringUtils.isEmpty(watermark)) {
    72. throw new RuntimeException("文字水印内容不能为空");
    73. }
    74. // 添加文字水印:
    75. // 根据图片的背景设置水印颜色
    76. graphics.setColor(new Color(255, 255, 255, 128));
    77. // 设置字体 画笔字体样式为微软雅黑,加粗,文字大小为45pt
    78. graphics.setFont(new Font("微软雅黑", Font.BOLD, 45));
    79. // 设置水印的坐标(为原图片中间位置)
    80. int x = (imgWidth - getWatermarkLength(watermark, graphics)) / 2;
    81. int y = imgHeight / 2;
    82. // 画出水印 第一个参数是水印内容,第二个参数是x轴坐标,第三个参数是y轴坐标
    83. graphics.drawString(watermark, x, y);
    84. graphics.dispose();
    85. } else {
    86. // 添加图片水印:
    87. if (StringUtils.isEmpty(watermark)) {
    88. throw new RuntimeException("图片水印存放路径不能为空");
    89. }
    90. Image srcWatermark = readLocalPicture(watermark);
    91. int watermarkWidth = srcWatermark.getWidth(null);
    92. int watermarkHeight = srcWatermark.getHeight(null);
    93. // 设置 alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字
    94. graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.9f));
    95. // 绘制水印图片 坐标为中间位置
    96. graphics.drawImage(srcWatermark, (imgWidth - watermarkWidth) / 2,
    97. (imgHeight - watermarkHeight) / 2, watermarkWidth, watermarkHeight, null);
    98. graphics.dispose();
    99. }
    100. // 定义存储的地址
    101. String tarImgPath = "C:/Users/admin/Desktop/watermark.jpg";
    102. // 输出图片
    103. try {
    104. FileOutputStream outImgStream = new FileOutputStream(tarImgPath);
    105. ImageIO.write(bufImg, "png", outImgStream);
    106. outImgStream.flush();
    107. outImgStream.close();
    108. return "水印添加成功";
    109. } catch (IOException e) {
    110. throw new RuntimeException(e);
    111. }
    112. }
    113. /**
    114. * 添加水印
    115. *
    116. * @param pictureType 图片来源类型(1-本地图片 2-网络图片)
    117. * @param watermarkType 水印类型(1-文字水印 2-图片水印)
    118. * @param path 图片路径
    119. * @param watermark 水印内容(文字水印内容/图片水印的存放路径)
    120. */
    121. public static String addWatermark(Integer pictureType, Integer watermarkType, String path, String watermark) {
    122. if (null == pictureType) {
    123. throw new RuntimeException("图片来源类型不能为空");
    124. }
    125. if (null == watermarkType) {
    126. throw new RuntimeException("水印类型不能为空");
    127. }
    128. Image image;
    129. if (pictureType == 1) {
    130. // 读取本地图片
    131. image = readLocalPicture(path);
    132. } else {
    133. // 读取网络图片
    134. image = readNetworkPicture(path);
    135. }
    136. if (watermarkType == 1) {
    137. // 添加文字水印
    138. return = manageWatermark(image, 1, watermark);
    139. } else {
    140. // 添加图片水印
    141. return = manageWatermark(image, 2, watermark);
    142. }
    143. }
    144. /**
    145. * 获取水印文字的长度
    146. *
    147. * @param watermarkContent 文字水印内容
    148. * @param graphics 图像类
    149. */
    150. private static int getWatermarkLength(String watermarkContent, Graphics2D graphics) {
    151. return graphics.getFontMetrics(graphics.getFont()).charsWidth(watermarkContent.toCharArray(), 0, watermarkContent.length());
    152. }
    153. public static void main(String[] args) {
    154. // 本地图片路径:
    155. String localPath = "C:/Users/admin/Desktop/bg.jpg";
    156. // 网络图片地址:
    157. String networkPath = "https://img0.baidu.com/it/u=3708545959,316194769&fm=253&fmt=auto&app=138&f=PNG?w=1000&h=1000";
    158. // 文字水印内容
    159. String textWatermark = "Hello World!";
    160. // 图片水印路径
    161. String pictureWatermark = "C:\\Users\\admin\\Desktop\\wm.jpg";
    162. // 本地图片 添加文字水印
    163. //addWatermark(1, 1, localPath,textWatermark);
    164. // 网络图片 添加文字水印
    165. //addWatermark(2, 1, networkPath, textWatermark);
    166. // 本地图片 添加图片水印
    167. //addWatermark(1, 2, localPath, pictureWatermark);
    168. // 网络图片 添加图片水印
    169. addWatermark(2, 2, networkPath, pictureWatermark);
    170. }
    171. }

    六、结果展示

    1、本地图片+文字水印:

    2、本地图片+图片水印:

    3、网络图片+文字水印:

    4、网络图片+图片水印:

    如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、评论、收藏➕关注,您的支持是我坚持写作最大的动力。 

  • 相关阅读:
    Zabbix监控系统系列之二十二:ESXi虚拟化监控
    用 TensorFlow API:tf.keras 搭建网络八股
    基于springboot实现校友社交平台管理系统项目【项目源码+论文说明】
    Ubuntu中为Python2.7安装pip
    Java知识梳理 第九章 面向对象编程(高级部分)
    Docker网络及CPU资源控制
    [云原生] [Docker] IDEA下Docker推送镜像到阿里云容器镜像
    校招程序员无项目经验如何破局
    使用Krukal算法解决图的最小生成树问题
    图的理论基础
  • 原文地址:https://blog.csdn.net/weixin_42555014/article/details/133994224