|
|
|
package com.ruoyi.quartz.util;
|
|
|
|
|
|
|
|
import com.google.common.io.Resources;
|
|
|
|
import com.ruoyi.common.utils.DateUtils;
|
|
|
|
|
|
|
|
import javax.imageio.ImageIO;
|
|
|
|
import java.awt.*;
|
|
|
|
import java.awt.image.BufferedImage;
|
|
|
|
import java.awt.AlphaComposite;
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.util.*;
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
public class MultiTextImageGenerator {
|
|
|
|
|
|
|
|
private static final String savePath = "uploadPath/aquaticPublicOpinion/img/";
|
|
|
|
private static final String backgroundPath = "moban.png";
|
|
|
|
public static void main(String[] args) throws IOException {
|
|
|
|
// 1. 示例数据
|
|
|
|
List<AbstractMap.SimpleEntry<String, String>> dataList = Arrays.asList(
|
|
|
|
new AbstractMap.SimpleEntry<>("水质监测", "用于监测水体中溶氧、温度、pH 等参数,保障水产养殖环境。"),
|
|
|
|
new AbstractMap.SimpleEntry<>("智能告警", "当监测数据异常时,可通过APP或短信方式自动告警提醒。"),
|
|
|
|
new AbstractMap.SimpleEntry<>("移动便携", "设备小巧轻便,支持户外测量,数据实时同步上传。")
|
|
|
|
);
|
|
|
|
// 2. 配置加载
|
|
|
|
generateImage(dataList,new StyleConfig());
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String generateImage(List<AbstractMap.SimpleEntry<String, String>> dataList, StyleConfig style) throws IOException {
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 背景图
|
|
|
|
BufferedImage image = ImageIO.read(new File(backgroundPath));
|
|
|
|
int width = image.getWidth();
|
|
|
|
int height = image.getHeight();
|
|
|
|
BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
|
|
|
Graphics2D g = newImage.createGraphics();
|
|
|
|
g.drawImage(image, 0, 0, null);
|
|
|
|
|
|
|
|
// 抗锯齿
|
|
|
|
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
|
|
|
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
|
|
|
|
|
|
|
int maxTextWidth = width - 2 * style.startX;
|
|
|
|
int currY = style.startY;
|
|
|
|
|
|
|
|
// 4. 绘制每组内容块
|
|
|
|
for (int i = 0; i < dataList.size(); i++) {
|
|
|
|
String title = (i + 1) + ". " + dataList.get(i).getKey();
|
|
|
|
String content = dataList.get(i).getValue();
|
|
|
|
|
|
|
|
g.setFont(style.titleFont);
|
|
|
|
FontMetrics titleMetrics = g.getFontMetrics();
|
|
|
|
int titleHeight = titleMetrics.getHeight();
|
|
|
|
|
|
|
|
g.setFont(style.contentFont);
|
|
|
|
FontMetrics contentMetrics = g.getFontMetrics();
|
|
|
|
List<String> lines = splitTextIntoLines(content, contentMetrics, maxTextWidth);
|
|
|
|
int lineHeight = contentMetrics.getHeight() + style.lineSpacing;
|
|
|
|
int contentHeight = lines.size() * lineHeight;
|
|
|
|
int totalTextHeight = titleHeight + 10 + contentHeight;
|
|
|
|
int blockHeight = totalTextHeight + 2 * style.padding;
|
|
|
|
|
|
|
|
int blockWidth = maxTextWidth + 2 * style.padding;
|
|
|
|
int blockX = style.startX - style.padding;
|
|
|
|
int blockY = currY;
|
|
|
|
|
|
|
|
if (style.showBackgroundBlock)
|
|
|
|
{
|
|
|
|
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, style.backgroundAlpha));
|
|
|
|
g.setColor(style.backgroundColor);
|
|
|
|
g.fillRoundRect(blockX, blockY, blockWidth, blockHeight, style.cornerRadius, style.cornerRadius);
|
|
|
|
}
|
|
|
|
|
|
|
|
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
|
|
|
|
g.setColor(style.textColor);
|
|
|
|
|
|
|
|
int textStartY = blockY + style.padding + (blockHeight - 2 * style.padding - totalTextHeight) / 2;
|
|
|
|
|
|
|
|
g.setFont(style.titleFont);
|
|
|
|
int titleY = textStartY + titleHeight;
|
|
|
|
g.drawString(title, style.startX, titleY);
|
|
|
|
|
|
|
|
g.setFont(style.contentFont);
|
|
|
|
int contentStartY = titleY + 10 + lineHeight;
|
|
|
|
for (int j = 0; j < lines.size(); j++) {
|
|
|
|
int y = contentStartY + j * lineHeight;
|
|
|
|
g.drawString(lines.get(j), style.startX, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
currY = blockY + blockHeight + style.blockSpacing;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 5. 添加文字水印
|
|
|
|
drawTextWatermark(g, width, height, style);
|
|
|
|
|
|
|
|
// 6. 添加图片水印
|
|
|
|
// drawImageWatermark(g, width, height, style);
|
|
|
|
|
|
|
|
g.dispose();
|
|
|
|
|
|
|
|
// 7. 保存输出
|
|
|
|
String saveFile = savePath + DateUtils.getDate()+ "_output.png";
|
|
|
|
ImageIO.write(newImage, "png", new File(saveFile));
|
|
|
|
return saveFile;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 文字自动换行
|
|
|
|
private static List<String> splitTextIntoLines(String text, FontMetrics metrics, int maxWidth) {
|
|
|
|
List<String> lines = new ArrayList<>();
|
|
|
|
StringBuilder line = new StringBuilder();
|
|
|
|
for (char c : text.toCharArray()) {
|
|
|
|
line.append(c);
|
|
|
|
if (metrics.stringWidth(line.toString()) > maxWidth) {
|
|
|
|
line.deleteCharAt(line.length() - 1);
|
|
|
|
lines.add(line.toString());
|
|
|
|
line = new StringBuilder().append(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!line.toString().isEmpty()) {
|
|
|
|
lines.add(line.toString());
|
|
|
|
}
|
|
|
|
return lines;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 文字水印
|
|
|
|
private static void drawTextWatermark(Graphics2D g, int width, int height, StyleConfig style) {
|
|
|
|
g.setFont(style.watermarkFont);
|
|
|
|
g.setColor(style.watermarkColor);
|
|
|
|
FontMetrics metrics = g.getFontMetrics();
|
|
|
|
int textWidth = metrics.stringWidth(style.watermarkText);
|
|
|
|
int x = width - textWidth - style.watermarkTextMarginX;
|
|
|
|
int y = height - style.watermarkTextMarginY;
|
|
|
|
g.drawString(style.watermarkText, x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 图片水印
|
|
|
|
private static void drawImageWatermark(Graphics2D g, int width, int height, StyleConfig style) {
|
|
|
|
try {
|
|
|
|
String watermarkImagePath = style.watermarkImagePath;
|
|
|
|
File file = new File(watermarkImagePath);
|
|
|
|
if (!file.exists()) {
|
|
|
|
System.out.println("⚠️ 水印图片未找到:" + watermarkImagePath);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Image logo = ImageIO.read(file).getScaledInstance(
|
|
|
|
style.watermarkImageWidth,
|
|
|
|
style.watermarkImageHeight,
|
|
|
|
Image.SCALE_SMOOTH
|
|
|
|
);
|
|
|
|
int x = width - style.watermarkImageWidth - style.watermarkImageMarginX;
|
|
|
|
int y = height - style.watermarkImageHeight - style.watermarkImageMarginY;
|
|
|
|
g.drawImage(logo, x, y, null);
|
|
|
|
} catch (IOException e) {
|
|
|
|
System.err.println("❌ 加载图片水印失败:" + e.getMessage());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
...
|
...
|
|