diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3d782dcc6..f128f444f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,7 +3,7 @@
-------------------------------------------------------------------------------------------------------------
-# 5.8.0.M3 (2022-04-12)
+# 5.8.0.M3 (2022-04-13)
### ❌不兼容特性
* 【core 】 StreamProgress#progress方法参数变更为2个(pr#594@Gitee)
@@ -17,6 +17,7 @@
* 【core 】 Snowflake支持sequence使用随机数(issue#I51EJY@Gitee)
* 【core 】 JarClassLoader增加构造(pr#593@Gitee)
* 【core 】 增加Pid,以便获取单例pid
+* 【core 】 Img增加全覆盖水印pressTextFull(pr#595@Gitee)
### 🐞Bug修复
* 【core 】 修复UserAgentUtil识别Linux出错(issue#I50YGY@Gitee)
diff --git a/hutool-core/src/main/java/cn/hutool/core/img/Img.java b/hutool-core/src/main/java/cn/hutool/core/img/Img.java
index 430657305..754ce85ef 100644
--- a/hutool-core/src/main/java/cn/hutool/core/img/Img.java
+++ b/hutool-core/src/main/java/cn/hutool/core/img/Img.java
@@ -12,12 +12,24 @@ import cn.hutool.core.util.StrUtil;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
-import java.awt.*;
+import java.awt.AlphaComposite;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Stroke;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.RoundRectangle2D;
-import java.awt.image.*;
+import java.awt.image.BufferedImage;
+import java.awt.image.CropImageFilter;
+import java.awt.image.ImageFilter;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
@@ -249,8 +261,8 @@ public class Img implements Serializable {
* 缩放图像(按长宽缩放)
* 注意:目标长宽与原图不成比例会变形
*
- * @param width 目标宽度
- * @param height 目标高度
+ * @param width 目标宽度
+ * @param height 目标高度
* @param scaleType 缩放类型,可选{@link Image#SCALE_SMOOTH}平滑模式或{@link Image#SCALE_DEFAULT}默认模式
* @return this
* @since 5.7.18
@@ -435,7 +447,8 @@ public class Img implements Serializable {
}
/**
- * 给图片添加文字水印
+ * 给图片添加文字水印
+ * 此方法只在给定位置写出一个水印字符串
*
* @param pressText 水印文字
* @param color 水印的字体颜色
@@ -446,13 +459,29 @@ public class Img implements Serializable {
* @return 处理后的图像
*/
public Img pressText(String pressText, Color color, Font font, int x, int y, float alpha) {
+ return pressText(pressText, color, font, new Point(x, y), alpha);
+ }
+
+ /**
+ * 给图片添加文字水印
+ * 此方法只在给定位置写出一个水印字符串
+ *
+ * @param pressText 水印文字
+ * @param color 水印的字体颜色
+ * @param font {@link Font} 字体相关信息
+ * @param point 绘制字符串的位置坐标
+ * @param alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字
+ * @return 处理后的图像
+ */
+ public Img pressText(String pressText, Color color, Font font, Point point, float alpha) {
final BufferedImage targetImage = ImgUtil.toBufferedImage(getValidSrcImg(), this.targetImageType);
- final Graphics2D g = targetImage.createGraphics();
if (null == font) {
// 默认字体
font = FontUtil.createSansSerifFont((int) (targetImage.getHeight() * 0.75));
}
+
+ final Graphics2D g = targetImage.createGraphics();
// 透明度
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
@@ -460,11 +489,10 @@ public class Img implements Serializable {
if (positionBaseCentre) {
// 基于中心绘制
GraphicsUtil.drawString(g, pressText, font, color,
- new Rectangle(x, y, targetImage.getWidth(), targetImage.getHeight()));
+ new Rectangle(point.x, point.y, targetImage.getWidth(), targetImage.getHeight()));
} else {
// 基于左上角绘制
- GraphicsUtil.drawString(g, pressText, font, color,
- new Point(x, y));
+ GraphicsUtil.drawString(g, pressText, font, color, point);
}
// 收笔
@@ -478,73 +506,56 @@ public class Img implements Serializable {
/**
* 给图片添加全屏文字水印
*
- * @param pressText 水印文字
- * @param color 水印的字体颜色
- * @param font {@link Font} 字体相关信息
- * @param degree 旋转角度,(单位:弧度),以圆点(0,0)为圆心,正代表顺时针,负代表逆时针
- * @param alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字
+ * @param pressText 水印文字,文件间的间隔使用尾部添加空格方式实现
+ * @param color 水印的字体颜色
+ * @param font {@link Font} 字体相关信息
+ * @param lineHeight 行高
+ * @param degree 旋转角度,(单位:弧度),以圆点(0,0)为圆心,正代表顺时针,负代表逆时针
+ * @param alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字
* @return 处理后的图像
+ * @since 5.8.0
*/
- public Img pressTextFullScreen(String pressText, Color color, Font font, int degree, float alpha) {
+ public Img pressTextFull(String pressText, Color color, Font font, int lineHeight, int degree, float alpha) {
final BufferedImage targetImage = ImgUtil.toBufferedImage(getValidSrcImg(), this.targetImageType);
- final int targetwidth = targetImage.getWidth();
- final int targetheight = targetImage.getHeight();
- return pressImage(createFullScreenPressImage(targetwidth, targetheight, pressText, color, font, degree, alpha).getImg(), 0, 0, alpha);
- }
- /**
- * 水印文字生成全屏水印图片
- *
- * @param targetwidth 水印图片宽
- * @param targetheight 水印图片高
- * @param pressText 水印字符串
- * @param color 水印的字体颜色
- * @param font {@link Font} 字体相关信息
- * @param degree 旋转角度,(单位:弧度),以圆点(0,0)为圆心,正代表顺时针,负代表逆时针
- * @param alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字
- * @return Img
- */
- private static Img createFullScreenPressImage(int targetwidth, int targetheight, String pressText, Color color, Font font, int degree, float alpha) {
- ColorModel cm = ColorModel.getRGBdefault();
- WritableRaster wr = cm.createCompatibleWritableRaster(targetwidth, targetheight);
- BufferedImage pressImg = new BufferedImage(cm, wr, cm.isAlphaPremultiplied(), null);
+ if (null == font) {
+ // 默认字体
+ font = FontUtil.createSansSerifFont((int) (targetImage.getHeight() * 0.75));
+ }
+ final int targetHeight = targetImage.getHeight();
+ final int targetWidth = targetImage.getWidth();
+
+ // 创建画笔,并设置透明度和角度
+ final Graphics2D g = targetImage.createGraphics();
+ g.setColor(color);
+ // 基于图片中心旋转
+ g.rotate(Math.toRadians(degree), targetWidth >> 1, targetHeight >> 1);
+ g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
- // 水印图片放大倍数
- final float scale = 2;
- font = font.deriveFont(font.getSize() / scale);
- final Graphics2D g = pressImg.createGraphics();
//获取字符串本身的长宽
Dimension dimension;
try {
- // 3字间隔
- dimension = FontUtil.getDimension(g.getFontMetrics(font), pressText + " ");
+ dimension = FontUtil.getDimension(g.getFontMetrics(font), pressText);
} catch (Exception e) {
// 此处报告bug某些情况下会抛出IndexOutOfBoundsException,在此做容错处理
- dimension = new Dimension(targetwidth / 3, targetheight / 3);
+ dimension = new Dimension(targetWidth / 3, targetHeight / 3);
}
-
- // 3倍间宽 间隔
- final int intervalHeight = dimension.height * 4;
- // 循环写
- int y = dimension.height;
- while (y < targetheight) {
- int x = 0;
- while (x < targetwidth) {
-
- GraphicsUtil.drawString(g, pressText, font, color,
- new Point(x, y));
+ final int intervalHeight = dimension.height * lineHeight;
+ // 在画笔按照画布中心旋转后,达到45度时,上下左右会出现空白区,此处各延申长款的1.5倍实现全覆盖
+ int y = -targetHeight >> 1;
+ while (y < targetHeight * 1.5) {
+ int x = -targetWidth >> 1;
+ while (x < targetWidth * 1.5) {
+ GraphicsUtil.drawString(g, pressText, font, color, new Point(x, y));
x += dimension.width;
}
y += intervalHeight;
}
g.dispose();
- // 水印图片旋转,放大,剪切
- return Img.from(pressImg)
- .rotate(degree)
- .scale(scale)
- .cut(new Rectangle(0, 0, targetwidth, targetheight));
- }
+ this.targetImage = targetImage;
+ return this;
+ }
/**
* 给图片添加图片水印
@@ -629,30 +640,30 @@ public class Img implements Serializable {
* @return this
* @since 5.4.1
*/
- public Img stroke(Color color, float width){
+ public Img stroke(Color color, float width) {
return stroke(color, new BasicStroke(width));
}
/**
* 描边,此方法为向内描边,会覆盖图片相应的位置
*
- * @param color 描边颜色,默认黑色
+ * @param color 描边颜色,默认黑色
* @param stroke 描边属性,包括粗细、线条类型等,见{@link BasicStroke}
* @return this
* @since 5.4.1
*/
- public Img stroke(Color color, Stroke stroke){
+ public Img stroke(Color color, Stroke stroke) {
final BufferedImage image = ImgUtil.toBufferedImage(getValidSrcImg(), this.targetImageType);
int width = image.getWidth(null);
int height = image.getHeight(null);
Graphics2D g = image.createGraphics();
g.setColor(ObjectUtil.defaultIfNull(color, Color.BLACK));
- if(null != stroke){
+ if (null != stroke) {
g.setStroke(stroke);
}
- g.drawRect(0, 0, width -1 , height - 1);
+ g.drawRect(0, 0, width - 1, height - 1);
g.dispose();
this.targetImage = image;
diff --git a/hutool-core/src/test/java/cn/hutool/core/img/ImgTest.java b/hutool-core/src/test/java/cn/hutool/core/img/ImgTest.java
index 606de6cde..09a52a681 100644
--- a/hutool-core/src/test/java/cn/hutool/core/img/ImgTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/img/ImgTest.java
@@ -55,12 +55,14 @@ public class ImgTest {
@Test
@Ignore
- public void testPressTextFullScreen() {
- Img.from(FileUtil.file("d:/test/2.jpg"))
- .pressTextFullScreen("版权所有 仿冒必究", Color.LIGHT_GRAY,
- new Font("微软雅黑", Font.BOLD, 100),
- -30,
- 1f)
+ public void pressTextFullScreenTest() {
+ Img.from(FileUtil.file("d:/test/1435859438434136064.jpg"))
+ .setTargetImageType(ImgUtil.IMAGE_TYPE_PNG)
+ .pressTextFull("版权所有 ", Color.LIGHT_GRAY,
+ new Font("黑体", Font.PLAIN, 30),
+ 4,
+ 30,
+ 0.8f)
.write(FileUtil.file("d:/test/2_result.png"));
}