Java之Graphics2D图片生成水印

柔光的暖阳◎ 2023-10-12 17:41 116阅读 0赞

目录

一、介绍

二、效果图

三、代码

四、优化方向

五、参考链接


一、介绍

百度百科:Graphics2D ,Graphics 类,提供了对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制

不止通过JDK提供的工具类,还可以使用第三方的Thumbnailator工具,进行添加水印、制作缩略图等功能

二、效果图

1、生成水印前:

![Image 1][]

2、生成水印后:

![Image 1][]

三、代码

  1. public class WaterMarkUtil {
  2. private final static String[] IMAGE_TYPE = {"PNG","JPEG","JPG", "BMP", "GIF"};
  3. private final static int HEADER_SIZE = 4;
  4. public static byte[] getImageWithWaterMark(InputStream inputStream, String waterMarkContent) throws Exception {
  5. if(null == inputStream){
  6. throw new Exception("输入流不能为空");
  7. }
  8. if(null == waterMarkContent || waterMarkContent.isEmpty()){
  9. throw new Exception("水印内容不能为空");
  10. }
  11. // 封装为BufferedInputStream,用于流文件类型读取后的重置
  12. BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
  13. // 标记读取的文件类型长度
  14. bufferedInputStream.mark(HEADER_SIZE);
  15. // 获取文件类型
  16. String fileType = getFileType(bufferedInputStream);
  17. // 重置流到开始位置
  18. bufferedInputStream.reset();
  19. // 判断是否图片,否则结束处理
  20. boolean isImage = matchImageType(fileType);
  21. if(!isImage){
  22. throw new Exception("文件类型非图片类型,支持:png、jpeg、jpg、bmp、gif,当前文件类型:" + fileType);
  23. }
  24. BufferedImage targetImg = ImageIO.read(bufferedInputStream);
  25. int height = targetImg.getHeight();
  26. int width = targetImg.getWidth();
  27. //-------------------------文字水印 start----------------------------
  28. BufferedImage waterMarkImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
  29. // 创建画笔
  30. Graphics2D graphics2D = waterMarkImage.createGraphics();
  31. // 绘制原始图片
  32. graphics2D.drawImage(targetImg, 0, 0, width, height, null);
  33. // 设置水印颜色
  34. graphics2D.setColor(new Color(255, 255, 255, 50));
  35. double scale = 1.0;
  36. if(width < height){
  37. scale = (double) width / height;
  38. }
  39. int fontSize = (int) Math.ceil((double) (height / 25) * scale);
  40. // 设置字体 画笔字体样式为微软雅黑,加粗,文字大小按比例给
  41. graphics2D.setFont(new Font("微软雅黑", Font.BOLD, fontSize));
  42. // 水印旋转度
  43. graphics2D.rotate(Math.toRadians(-25), (double) width / 2, (double) height / 2);
  44. int x = -width * 3;
  45. int y;
  46. // 计算水印文字的宽度
  47. FontMetrics fontMetrics = graphics2D.getFontMetrics();
  48. int watermarkWidth = fontMetrics.stringWidth(waterMarkContent);
  49. // 水印横向间隔
  50. int positionWidth = (int)(width * 0.15);
  51. // 水印竖向间隔
  52. int positionHeight = (int)(height * 0.15);
  53. while (x < width * 3) {
  54. y = -height * 3;
  55. while (y < height * 3) {
  56. graphics2D.drawString(waterMarkContent, x, y);
  57. y += fontSize + positionWidth;
  58. }
  59. x += watermarkWidth + positionHeight;
  60. }
  61. graphics2D.dispose();
  62. //-------------------------文字水印 end----------------------------
  63. ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
  64. ImageIO.write(waterMarkImage, fileType, byteArrayOutputStream);
  65. return byteArrayOutputStream.toByteArray();
  66. }
  67. private static boolean matchImageType(String fileType){
  68. if(null == fileType || fileType.isEmpty()){
  69. return false;
  70. }
  71. for (String type : IMAGE_TYPE) {
  72. if (fileType.equalsIgnoreCase(type)) {
  73. return true;
  74. }
  75. }
  76. return false;
  77. }
  78. private static String getFileType(InputStream is){
  79. String fileType = null;
  80. String fileHeader;
  81. byte[] temp = new byte[HEADER_SIZE];
  82. try {
  83. is.read(temp, 0, HEADER_SIZE);
  84. // 将读取到的字节数组转为十六进制字符串,,方法来自apache的commons-codec包
  85. fileHeader = Hex.encodeHexString(temp).toUpperCase();
  86. // 以下罗列几种类型,更多自行拓展
  87. if (fileHeader.contains("504B0304")) {
  88. fileType = "xlsx";
  89. } else if (fileHeader.contains("FFD8FF")) {
  90. fileType = "jpg";
  91. } else if (fileHeader.contains("89504E47")) {
  92. fileType = "png";
  93. } else if (fileHeader.contains("47494638")) {
  94. fileType = "gif";
  95. } else if (fileHeader.contains("25504446")) {
  96. fileType = "pdf";
  97. } else if (fileHeader.contains("424D")) {
  98. fileType = "bmp";
  99. } else {
  100. fileType = null;
  101. }
  102. } catch (Exception e) {
  103. e.printStackTrace();
  104. }
  105. return fileType;
  106. }
  107. }

四、优化方向

目前这个版本的水印生成还是有局限性的,比如:图片太小、水印内容太长之类的问题,会导致生成的效果有问题,所有如果你遇到这种情况,可以通过以下的方面进行优化:

1、水印文字大小按照图片等比例进行控制

2、限制水印文字大小,水印宽度不得超过图片宽度的百分之多少,通过水印宽度反出水印文字字数过多

3、限制图文长度与宽度,过小就不生成,或者只生成一个水印之类的

五、参考链接

Java实现给图片加单个、多个文字水印_java添加多个水印_斯内克喜欢吃益达的博客-CSDN博客

java实现给图片添加水印(文字水印或图片水印)_12程序猿的博客-CSDN博客

[Image 1]:

发表评论

表情:
评论列表 (有 0 条评论,116人围观)

还没有评论,来说两句吧...

相关阅读