This commit is contained in:
Looly 2023-12-12 20:01:04 +08:00
parent 11990ba904
commit 79b38c19c9
4 changed files with 225 additions and 176 deletions

View File

@ -0,0 +1,176 @@
package org.dromara.hutool.swing.img;
import java.awt.Color;
import java.awt.Font;
import java.awt.Point;
import java.io.Serializable;
import java.util.Objects;
/**
* 显示文本用于保存在图片上绘图的文本信息包括内容字体大小位置和透明度等
*
* @author looly
* @since 6.0.0
*/
public class DisplayText implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 构建DisplayText
*
* @param text 文本
* @param color 文本颜色
* @param font 文本显示字体
* @param point 起始左边位置
* @param alpha 透明度
* @return DisplayText
*/
public static DisplayText of(final String text, final Color color, final Font font, final Point point, final float alpha) {
return new DisplayText(text, color, font, point, alpha);
}
private String pressText;
private Color color;
private Font font;
private Point point;
private float alpha;
/**
* 构造
*
* @param text 文本
* @param color 文本颜色
* @param font 文本显示字体
* @param point 起始左边位置
* @param alpha 透明度
*/
public DisplayText(final String text, final Color color, final Font font, final Point point, final float alpha) {
this.pressText = text;
this.color = color;
this.font = font;
this.point = point;
this.alpha = alpha;
}
/**
* 获取文本
*
* @return 获取文本
*/
public String getPressText() {
return pressText;
}
/**
* 设置文本
*
* @param pressText 文本
*/
public void setPressText(final String pressText) {
this.pressText = pressText;
}
/**
* 获取文本颜色
*
* @return 文本颜色
*/
public Color getColor() {
return color;
}
/**
* 设置文本颜色
*
* @param color 文本颜色
*/
public void setColor(final Color color) {
this.color = color;
}
/**
* 获取字体
*
* @return 字体
*/
public Font getFont() {
return font;
}
/**
* 设置字体
*
* @param font 字体
*/
public void setFont(final Font font) {
this.font = font;
}
/**
* 获取二维坐标点
*
* @return 二维坐标点
*/
public Point getPoint() {
return point;
}
/**
* 设置二维坐标点
*
* @param point 二维坐标点
*/
public void setPoint(final Point point) {
this.point = point;
}
/**
* 获取透明度
*
* @return 透明度
*/
public float getAlpha() {
return alpha;
}
/**
* 设置透明度
*
* @param alpha 透明度
*/
public void setAlpha(final float alpha) {
this.alpha = alpha;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final DisplayText that = (DisplayText) o;
return Float.compare(alpha, that.alpha) == 0
&& Objects.equals(pressText, that.pressText)
&& Objects.equals(color, that.color)
&& Objects.equals(font, that.font)
&& Objects.equals(point, that.point);
}
@Override
public int hashCode() {
return Objects.hash(pressText, color, font, point, alpha);
}
@Override
public String toString() {
return "DisplayText{" +
"pressText='" + pressText + '\'' +
", color=" + color +
", font=" + font +
", point=" + point +
", alpha=" + alpha +
'}';
}
}

View File

@ -477,23 +477,20 @@ public class Img implements Serializable {
* @return 处理后的图像 * @return 处理后的图像
*/ */
public Img pressText(final String pressText, final Color color, final Font font, final int x, final int y, final float alpha) { public Img pressText(final String pressText, final Color color, final Font font, final int x, final int y, final float alpha) {
return pressText(pressText, color, font, new Point(x, y), alpha); return pressText(DisplayText.of(pressText, color, font, new Point(x, y), alpha));
} }
/** /**
* 给图片添加文字水印<br> * 给图片添加文字水印<br>
* 此方法只在给定位置写出一个水印字符串 * 此方法只在给定位置写出一个水印字符串
* *
* @param pressText 水印文字 * @param displayText 显示的文本信息
* @param color 水印的字体颜色
* @param font {@link Font} 字体相关信息
* @param point 绘制字符串的位置坐标
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
* @return 处理后的图像 * @return 处理后的图像
*/ */
public Img pressText(final String pressText, final Color color, Font font, final Point point, final float alpha) { public Img pressText(final DisplayText displayText) {
final BufferedImage targetImage = ImgUtil.toBufferedImage(getValidSrcImg(), this.targetImageType); final BufferedImage targetImage = ImgUtil.toBufferedImage(getValidSrcImg(), this.targetImageType);
Font font = displayText.getFont();
if (null == font) { if (null == font) {
// 默认字体 // 默认字体
font = FontUtil.createSansSerifFont((int) (targetImage.getHeight() * 0.75)); font = FontUtil.createSansSerifFont((int) (targetImage.getHeight() * 0.75));
@ -501,16 +498,17 @@ public class Img implements Serializable {
final Graphics2D g = targetImage.createGraphics(); final Graphics2D g = targetImage.createGraphics();
// 透明度 // 透明度
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, displayText.getAlpha()));
final Point point = displayText.getPoint();
// 绘制 // 绘制
if (positionBaseCentre) { if (positionBaseCentre) {
// 基于中心绘制 // 基于中心绘制
GraphicsUtil.drawString(g, pressText, font, color, GraphicsUtil.drawString(g, displayText.getPressText(), font, displayText.getColor(),
new Rectangle(point.x, point.y, targetImage.getWidth(), targetImage.getHeight())); new Rectangle(point.x, point.y, targetImage.getWidth(), targetImage.getHeight()));
} else { } else {
// 基于左上角绘制 // 基于左上角绘制
GraphicsUtil.drawString(g, pressText, font, color, point); GraphicsUtil.drawString(g, displayText.getPressText(), font, displayText.getColor(), point);
} }
// 收笔 // 收笔
@ -630,11 +628,11 @@ public class Img implements Serializable {
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
//获取水印图片本身的长宽 //获取水印图片本身的长宽
int pressImageWidth = pressImage.getWidth(null); final int pressImageWidth = pressImage.getWidth(null);
int pressImageHeight = pressImage.getHeight(null); final int pressImageHeight = pressImage.getHeight(null);
Dimension dimension = new Dimension(pressImageWidth, pressImageHeight); final Dimension dimension = new Dimension(pressImageWidth, pressImageHeight);
final int intervalHeight = dimension.height * lineHeight; final int intervalHeight = dimension.height * lineHeight;
// 在画笔按照画布中心旋转后达到45度时上下左右会出现空白区此处各延长款的1.5倍实现全覆盖 // 在画笔按照画布中心旋转后达到45度时上下左右会出现空白区此处各延长款的1.5倍实现全覆盖
int y = -targetHeight >> 1 ; int y = -targetHeight >> 1 ;
while (y < targetHeight * 1.5) { while (y < targetHeight * 1.5) {
int x = -targetWidth >> 1; int x = -targetWidth >> 1;

View File

@ -726,14 +726,9 @@ public class ImgUtil {
* @param imageFile 源图像文件 * @param imageFile 源图像文件
* @param destFile 目标图像文件 * @param destFile 目标图像文件
* @param pressText 水印文字 * @param pressText 水印文字
* @param color 水印的字体颜色
* @param font {@link Font} 字体相关信息如果默认则为{@code null}
* @param x 修正值 默认在中间偏移量相对于中间偏移
* @param y 修正值 默认在中间偏移量相对于中间偏移
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
*/ */
public static void pressText(final File imageFile, final File destFile, final String pressText, final Color color, final Font font, final int x, final int y, final float alpha) { public static void pressText(final File imageFile, final File destFile, final DisplayText pressText) {
pressText(read(imageFile), destFile, pressText, color, font, x, y, alpha); pressText(read(imageFile), destFile, pressText);
} }
/** /**
@ -742,32 +737,10 @@ public class ImgUtil {
* *
* @param srcStream 源图像流 * @param srcStream 源图像流
* @param destStream 目标图像流 * @param destStream 目标图像流
* @param pressText 水印文字 * @param pressText 水印文本信息
* @param color 水印的字体颜色
* @param font {@link Font} 字体相关信息如果默认则为{@code null}
* @param x 修正值 默认在中间偏移量相对于中间偏移
* @param y 修正值 默认在中间偏移量相对于中间偏移
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
*/ */
public static void pressText(final InputStream srcStream, final OutputStream destStream, final String pressText, final Color color, final Font font, final int x, final int y, final float alpha) { public static void pressText(final InputStream srcStream, final OutputStream destStream, final DisplayText pressText) {
pressText(read(srcStream), getImageOutputStream(destStream), pressText, color, font, x, y, alpha); pressText(read(srcStream), getImageOutputStream(destStream), pressText);
}
/**
* 给图片添加文字水印<br>
* 此方法并不关闭流
*
* @param srcStream 源图像流
* @param destStream 目标图像流
* @param pressText 水印文字
* @param color 水印的字体颜色
* @param font {@link Font} 字体相关信息如果默认则为{@code null}
* @param x 修正值 默认在中间偏移量相对于中间偏移
* @param y 修正值 默认在中间偏移量相对于中间偏移
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
*/
public static void pressText(final ImageInputStream srcStream, final ImageOutputStream destStream, final String pressText, final Color color, final Font font, final int x, final int y, final float alpha) {
pressText(read(srcStream), destStream, pressText, color, font, x, y, alpha);
} }
/** /**
@ -776,17 +749,12 @@ public class ImgUtil {
* *
* @param srcImage 源图像 * @param srcImage 源图像
* @param destFile 目标流 * @param destFile 目标流
* @param pressText 水印文字 * @param pressText 水印文字信息
* @param color 水印的字体颜色
* @param font {@link Font} 字体相关信息如果默认则为{@code null}
* @param x 修正值 默认在中间偏移量相对于中间偏移
* @param y 修正值 默认在中间偏移量相对于中间偏移
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
* @throws IORuntimeException IO异常 * @throws IORuntimeException IO异常
* @since 3.2.2 * @since 3.2.2
*/ */
public static void pressText(final Image srcImage, final File destFile, final String pressText, final Color color, final Font font, final int x, final int y, final float alpha) throws IORuntimeException { public static void pressText(final Image srcImage, final File destFile, final DisplayText pressText) throws IORuntimeException {
write(pressText(srcImage, pressText, color, font, x, y, alpha), destFile); write(pressText(srcImage, pressText), destFile);
} }
/** /**
@ -795,17 +763,12 @@ public class ImgUtil {
* *
* @param srcImage 源图像 * @param srcImage 源图像
* @param to 目标流 * @param to 目标流
* @param pressText 水印文字 * @param pressText 水印文字信息
* @param color 水印的字体颜色
* @param font {@link Font} 字体相关信息如果默认则为{@code null}
* @param x 修正值 默认在中间偏移量相对于中间偏移
* @param y 修正值 默认在中间偏移量相对于中间偏移
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
* @throws IORuntimeException IO异常 * @throws IORuntimeException IO异常
* @since 3.2.2 * @since 3.2.2
*/ */
public static void pressText(final Image srcImage, final OutputStream to, final String pressText, final Color color, final Font font, final int x, final int y, final float alpha) throws IORuntimeException { public static void pressText(final Image srcImage, final OutputStream to, final DisplayText pressText) throws IORuntimeException {
pressText(srcImage, getImageOutputStream(to), pressText, color, font, x, y, alpha); pressText(srcImage, getImageOutputStream(to), pressText);
} }
/** /**
@ -814,16 +777,11 @@ public class ImgUtil {
* *
* @param srcImage 源图像 * @param srcImage 源图像
* @param destImageStream 目标图像流 * @param destImageStream 目标图像流
* @param pressText 水印文字 * @param pressText 水印文字信息
* @param color 水印的字体颜色
* @param font {@link Font} 字体相关信息如果默认则为{@code null}
* @param x 修正值 默认在中间偏移量相对于中间偏移
* @param y 修正值 默认在中间偏移量相对于中间偏移
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
* @throws IORuntimeException IO异常 * @throws IORuntimeException IO异常
*/ */
public static void pressText(final Image srcImage, final ImageOutputStream destImageStream, final String pressText, final Color color, final Font font, final int x, final int y, final float alpha) throws IORuntimeException { public static void pressText(final Image srcImage, final ImageOutputStream destImageStream, final DisplayText pressText) throws IORuntimeException {
writeJpg(pressText(srcImage, pressText, color, font, x, y, alpha), destImageStream); writeJpg(pressText(srcImage, pressText), destImageStream);
} }
/** /**
@ -831,76 +789,18 @@ public class ImgUtil {
* 此方法并不关闭流 * 此方法并不关闭流
* *
* @param srcImage 源图像 * @param srcImage 源图像
* @param pressText 水印文字 * @param pressText 水印文字信息
* @param color 水印的字体颜色
* @param font {@link Font} 字体相关信息如果默认则为{@code null}
* @param x 修正值 默认在中间偏移量相对于中间偏移
* @param y 修正值 默认在中间偏移量相对于中间偏移
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
* @return 处理后的图像 * @return 处理后的图像
* @since 3.2.2 * @since 3.2.2
*/ */
public static Image pressText(final Image srcImage, final String pressText, final Color color, final Font font, final int x, final int y, final float alpha) { public static Image pressText(final Image srcImage, final DisplayText pressText) {
return Img.from(srcImage).pressText(pressText, color, font, x, y, alpha).getImg(); return Img.from(srcImage).pressText(pressText).getImg();
}
/**
* 给图片添加全屏文字水印<br>
*
* @param imageFile 源图像文件
* @param destFile 目标图像文件
* @param pressText 水印文字
* @param color 水印的字体颜色
* @param font {@link Font} 字体相关信息如果默认则为{@code null}
* @param lineHeight 行高
* @param degree 水印文字旋转角度
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
* @throws IORuntimeException IO异常
*/
public static void pressTextFull(final File imageFile, final File destFile, final String pressText, final Color color, final Font font, final int lineHeight, final int degree, final float alpha) throws IORuntimeException {
pressTextFull(read(imageFile), destFile, pressText, color, font, lineHeight, degree, alpha);
} }
/** /**
* 给图片添加全屏文字水印<br> * 给图片添加全屏文字水印<br>
* 此方法并不关闭流 * 此方法并不关闭流
* *
* @param srcStream 源图像流
* @param destStream 目标图像流
* @param pressText 水印文字
* @param color 水印的字体颜色
* @param font {@link Font} 字体相关信息如果默认则为{@code null}
* @param lineHeight 行高
* @param degree 水印文字旋转角度
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
* @throws IORuntimeException IO异常
*/
public static void pressTextFull(final InputStream srcStream, final OutputStream destStream, final String pressText, final Color color, final Font font, final int lineHeight, final int degree, final float alpha) throws IORuntimeException {
writeJpg(pressTextFull(read(srcStream), pressText, color, font, lineHeight, degree, alpha), destStream);
}
/**
* 给图片添加全屏文字水印<br>
* 此方法并不关闭流
* @param srcImage 源图像
* @param destFile 目标图像文件
* @param pressText 水印文字
* @param color 水印的字体颜色
* @param font {@link Font} 字体相关信息如果默认则为{@code null}
* @param lineHeight 行高
* @param degree 水印文字旋转角度
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
* @throws IORuntimeException IO异常
*/
public static void pressTextFull(final Image srcImage, final File destFile, final String pressText, final Color color, final Font font, final int lineHeight, final int degree, final float alpha) throws IORuntimeException {
write(pressTextFull(srcImage, pressText, color, font, lineHeight, degree, alpha), destFile);
}
/**
* 给图片添加全屏文字水印<br>
* 此方法并不关闭流
* @param srcImage 源图像 * @param srcImage 源图像
* @param pressText 水印文字 * @param pressText 水印文字
* @param color 水印的字体颜色 * @param color 水印的字体颜色
@ -944,22 +844,6 @@ public class ImgUtil {
pressImage(read(srcStream), getImageOutputStream(destStream), pressImg, x, y, alpha); pressImage(read(srcStream), getImageOutputStream(destStream), pressImg, x, y, alpha);
} }
/**
* 给图片添加图片水印<br>
* 此方法并不关闭流
*
* @param srcStream 源图像流
* @param destStream 目标图像流
* @param pressImg 水印图片可以使用{@link ImageIO#read(File)}方法读取文件
* @param x 修正值 默认在中间偏移量相对于中间偏移
* @param y 修正值 默认在中间偏移量相对于中间偏移
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
* @throws IORuntimeException IO异常
*/
public static void pressImage(final ImageInputStream srcStream, final ImageOutputStream destStream, final Image pressImg, final int x, final int y, final float alpha) throws IORuntimeException {
pressImage(read(srcStream), destStream, pressImg, x, y, alpha);
}
/** /**
* 给图片添加图片水印<br> * 给图片添加图片水印<br>
* 此方法并不关闭流 * 此方法并不关闭流
@ -1040,7 +924,6 @@ public class ImgUtil {
return Img.from(srcImage).pressImage(pressImg, rectangle, alpha).getImg(); return Img.from(srcImage).pressImage(pressImg, rectangle, alpha).getImg();
} }
/** /**
* 给图片添加全屏图片水印<br> * 给图片添加全屏图片水印<br>
* *
@ -1052,7 +935,8 @@ public class ImgUtil {
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字 * @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
* @throws IORuntimeException IO异常 * @throws IORuntimeException IO异常
*/ */
public static void pressImageFull(final File imageFile, final File destFile, final File pressImageFile, final int lineHeight, final int degree, final float alpha) throws IORuntimeException { public static void pressImageFull(final File imageFile, final File destFile, final File pressImageFile,
final int lineHeight, final int degree, final float alpha) throws IORuntimeException {
write(pressImageFull(read(imageFile), read(pressImageFile), lineHeight, degree, alpha), destFile); write(pressImageFull(read(imageFile), read(pressImageFile), lineHeight, degree, alpha), destFile);
} }
@ -1068,15 +952,15 @@ public class ImgUtil {
* @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字 * @param alpha 透明度alpha 必须是范围 [0.0, 1.0] 之内包含边界值的一个浮点数字
* @throws IORuntimeException IO异常 * @throws IORuntimeException IO异常
*/ */
public static void pressImageFull(final InputStream srcStream, final OutputStream destStream, final InputStream pressStream, final int lineHeight, final int degree, final float alpha) throws IORuntimeException { public static void pressImageFull(final InputStream srcStream, final OutputStream destStream,
final InputStream pressStream, final int lineHeight, final int degree, final float alpha) throws IORuntimeException {
writeJpg(pressImageFull(read(srcStream), read(pressStream), lineHeight, degree, alpha), destStream); writeJpg(pressImageFull(read(srcStream), read(pressStream), lineHeight, degree, alpha), destStream);
} }
/** /**
* 给图片添加全屏图像水印<br> * 给图片添加全屏图像水印<br>
* 此方法并不关闭流 * 此方法并不关闭流
*
* @param srcImage 源图像 * @param srcImage 源图像
* @param pressImage 水印图像 * @param pressImage 水印图像
* @param lineHeight 行高 * @param lineHeight 行高
@ -1087,8 +971,6 @@ public class ImgUtil {
public static Image pressImageFull(final Image srcImage, final Image pressImage, final int lineHeight, final int degree, final float alpha) { public static Image pressImageFull(final Image srcImage, final Image pressImage, final int lineHeight, final int degree, final float alpha) {
return Img.from(srcImage).pressImageFull(pressImage, lineHeight, degree, alpha).getImg(); return Img.from(srcImage).pressImageFull(pressImage, lineHeight, degree, alpha).getImg();
} }
// endregion // endregion
// region ----- rotate // region ----- rotate

View File

@ -21,10 +21,7 @@ import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.Color; import java.awt.*;
import java.awt.Font;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -95,11 +92,7 @@ public class ImgUtilTest {
ImgUtil.pressText(// ImgUtil.pressText(//
FileUtil.file("d:/test/2.jpg"), // FileUtil.file("d:/test/2.jpg"), //
FileUtil.file("d:/test/2_result.png"), // FileUtil.file("d:/test/2_result.png"), //
"版权所有", Color.RED, // DisplayText.of("版权所有", Color.RED, new Font("黑体", Font.BOLD, 100), new Point(0, 0), 1f));
new Font("黑体", Font.BOLD, 100), //
0, //
0, //
1f);
} }
@Test @Test