之前已经写过一篇博文来记录 halo 图片添加水印的方法,如下:
那时候 halo 使用的还是 jdk8,现在最新版的 halo jdk 版本已经升级到了 11,所以相对之前的步骤有些许修改,这里重新做下记录。
我这里是在 Linux 下进行操作,步骤如下。
1、拉取源代码:
$ git clone https://github.com/halo-dev/halo.git
2、添加 gradle 依赖并取消代码风格检查:
$ cd halo
$ vim build.gradle
// 取消使用代码风格检查插件
plugins {
id "org.springframework.boot" version "2.5.1"
id "io.spring.dependency-management" version "1.0.11.RELEASE"
// id "checkstyle"
id "java"
}
// checkstyle {
// toolVersion = "8.39"
// showViolations = false
// ignoreFailures = false
// }
...
// 修改 gradle 源为国内源加快打包速度
repositories {
mavenLocal()
maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }
maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter'}
mavenCentral()
//maven { url 'https://repo.spring.io/milestone' }
jcenter()
}
...
// 引入绘图依赖
implementation "commons-fileupload:commons-fileupload:1.4"
implementation "commons-io:commons-io:2.6"
...
3、添加工具类:
$ touch src/main/java/run/halo/app/utils/ImageWatermarkUtil.java
其内容如下:
package run.halo.app.utils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
public class ImageWatermarkUtil {
// 水印透明度
private static float alpha = 0.2f;
// 水印文字大小
public static final int FONT_SIZE = 25;
// 水印文字字体
private static Font font = new Font("微软雅黑", Font.BOLD, FONT_SIZE);
// 水印文字颜色
private static Color color = Color.gray;
// 水印文字
private static String word = "张种恩的技术小栈 www.zze.xyz";
// 水印之间的间隔
private static final int XMOVE = 80;
// 水印之间的间隔
private static final int YMOVE = 80;
/**
* 加水印
*/
public static MultipartFile addWorkMarkToMutipartFile(MultipartFile multipartFile) throws IOException {
MultipartFile newFile = null;
// 获取图片文件名 xxx.png xxx
String originFileName = multipartFile.getOriginalFilename();
// 获取原图片后缀 png
int lastSplit = originFileName.lastIndexOf(".");
String suffix = originFileName.substring(lastSplit + 1);
// 获取图片原始信息
String dOriginFileName = multipartFile.getOriginalFilename();
String dContentType = multipartFile.getContentType();
// 是图片且不是gif才加水印
if (!suffix.equalsIgnoreCase("gif") && dContentType.contains("image")) {
// 获取水印图片
InputStream inputImg = multipartFile.getInputStream();
Image img = ImageIO.read(inputImg);
// 加图片水印
int imgWidth = img.getWidth(null);
int imgHeight = img.getHeight(null);
BufferedImage bufImg = new BufferedImage(imgWidth, imgHeight,
BufferedImage.TYPE_INT_RGB);
//调用画文字水印的方法
markWord(bufImg, img, word);
ByteArrayOutputStream bs = new ByteArrayOutputStream();
ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);
ImageIO.write(bufImg, suffix, imOut);
InputStream is = new ByteArrayInputStream(bs.toByteArray());
FileItemFactory factory = new DiskFileItemFactory(16, null);
FileItem item = factory.createItem(dOriginFileName, dContentType, true, originFileName);
int bytesRead = 0;
byte[] buffer = new byte[8192];
try {
OutputStream os = item.getOutputStream();
while ((bytesRead = is.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
newFile = new CommonsMultipartFile(item);
}
//返回加了水印的上传对象
return newFile;
}
public static void markWord(BufferedImage buffImg, Image srcImg, String text) {
Graphics2D g = buffImg.createGraphics();
// 设置对线段的锯齿状边缘处理
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(srcImg.getScaledInstance(srcImg.getWidth(null), srcImg.getHeight(null), Image.SCALE_SMOOTH),
0, 0, null);
Integer degree = 35;
// 设置水印旋转
if (null != degree) {
g.rotate(Math.toRadians(degree), (double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2);
}
int width = srcImg.getWidth(null);// 原图宽度
int height = srcImg.getHeight(null);// 原图高度
// 设置水印文字颜色
g.setColor(color);
// 设置水印文字Font
g.setFont(font);
// 设置水印文字透明度
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
int x = -width / 2;
int markWidth = FONT_SIZE * getTextLength(text);// 字体长度
int markHeight = FONT_SIZE;// 字体高度
int loopIndex = 0;
// 循环添加水印
while (x < width * 1.5) {
int y = -height / 2;
while (y < height * 1.5) {
g.drawString(text.split(" ")[loopIndex % 2], x, y);
y += markHeight + YMOVE;
loopIndex++;
}
x += markWidth + XMOVE;
}
// 释放资源
g.dispose();
}
private static int getTextLength(String text) {
int length = text.length();
for (int i = 0; i < text.length(); i++) {
String s = String.valueOf(text.charAt(i));
if (s.getBytes().length > 1) {
length++;
}
}
length = length % 2 == 0 ? length / 2 : length / 2 + 1;
return length;
}
}
4、修改 AttachmentServiceImpl
类的 upload
方法,在方法首部加上加水印代码:
// 导包
import java.io.*;
...
public Attachment upload(MultipartFile file) {
// 加水印
try {
file = ImageWatermarkUtil.addWorkMarkToMutipartFile(file);
} catch (IOException e) {
e.printStackTrace();
}
...
5、编译输出 jar 包:
$ ./gradlew clean build -x test
$ ls build/libs/halo-*.jar
build/libs/halo-1.4.13-SNAPSHOT.jar build/libs/halo-1.4.13-SNAPSHOT-plain.jar
6、安装中文字体库解决渲染中文乱码:
$ yum install fontconfig mkfontscale -y
# 检查中文字体库,如果下面命令没有任何输出就说明当前 jdk 不支持中文渲染
$ fc-list :lang=zh
$ mkdir /usr/share/fonts/chinese && cd /usr/share/fonts/chinese && chmod -R 755 /usr/share/fonts/chinese
# mysh.ttf 是微软雅黑字体库文件,它的下载链接我放在下面
$ cp /root/msyh.ttf .
# 关联字体库
$ mkfontscale
# 再次检查中文字体库
$ fc-list :lang=zh
/usr/share/fonts/chinese/msyh.ttf: Microsoft YaHei:style=Regular,Normal
msyh.ttf
- 链接: https://pan.baidu.com/s/1czx-yPZ83hU6rDpaKX4cUQ 提取码:9adl
7、最后使用新编译的 Jar 替换原来的 Jar 重启 halo 服务即可。
$ systemctl restart halo
评论区