项目中遇到要在图片上添加水印文字,类似于像生日贺卡那种推送,就是有一张底图,然后我们需要动态替换掉上面名字,性别,部门啥的给公司人员推送一个生日祝福,一开始使用富文本和一些html转图片的工具来做,发现效果不佳,许多样式无法识别等等,后来还是决定使用Java自带的Graphics2D来实现,通过坐标来控制位置,但是颜色和字体那些可能没有前端那么丰富,简单分享一下吧。
水印实体
/**
* 水印辅助类
*/
@Data
public class WatermarkAssist {
/**
* 参数key
*/
private String paramKey;
/**
* 参数value
*/
private String paramValue;
/**
* 字体字体类型
*/
private String fontType;
/**
* 字体字体风格
*/
private String fontStyle;
/**
* 字体大小
*/
private String fontSize;
/**
* 字体颜色
*/
private String fontColor;
/**
* 字体横坐标
*/
private String fontAbscissa;
/**
* 字体纵坐标
*/
private String fontOrdinate;
}
水印批量处理实体
@Data
public class WatermarkAssistBatch {
/**
* 水印集合
*/
private List<WatermarkAssist> watermarkAssists;
/**
* 原图片路径
*/
private String imagePath;
/**
* 生成图片输出位置
*/
private String imageOutPath;
}
水印生成工具类
public class MyDraw {
public static void main(String[] args) throws IOException {
List<WatermarkAssist> watermarkAssists = new ArrayList<>();
WatermarkAssist watermark1 = new WatermarkAssist();
watermark1.setFontColor("red");
watermark1.setFontSize("36");
watermark1.setFontStyle("PLAIN");
watermark1.setFontType("MingLiU");
watermark1.setFontAbscissa("118");
watermark1.setFontOrdinate("161");
watermark1.setParamValue("张三");
WatermarkAssist watermark2 = new WatermarkAssist();
watermark2.setFontColor("cyan");
watermark2.setFontSize("22");
watermark2.setFontStyle("PLAIN");
watermark2.setFontType("NSimSun");
watermark2.setFontAbscissa("118");
watermark2.setFontOrdinate("331");
watermark2.setParamValue("香港洪兴");
WatermarkAssist watermark3 = new WatermarkAssist();
watermark3.setFontColor("green");
watermark3.setFontSize("12");
watermark3.setFontStyle("PLAIN");
watermark3.setFontType("FangSong_GB2312");
watermark3.setFontAbscissa("124");
watermark3.setFontOrdinate("383");
watermark3.setParamValue("男");
watermarkAssists.add(watermark1);
watermarkAssists.add(watermark2);
watermarkAssists.add(watermark3);
WatermarkAssistBatch batch = new WatermarkAssistBatch();
batch.setWatermarkAssists(watermarkAssists);
batch.setImagePath("C:\\Users\\Administrator\\Desktop\\生日推送.jpg");
batch.setImageOutPath("C:\\Users\\Administrator\\Desktop\\新推送.jpg");
String s = new MyDraw().addWaterMark(batch);
System.out.println(s);
}
/**
* 生成水印
* @param batch
*/
public String addWaterMark(WatermarkAssistBatch batch) throws IOException {
if (StringUtils.isBlank(batch.getImagePath())){
throw new RuntimeException("获取不到图片的位置!");
}
//项目中是将图片转base64再返回,这里演示就不转base64了
String base64String= null;
if (batch.getWatermarkAssists() != null && batch.getWatermarkAssists().size() > 0){
// 读取原图片信息,得到文件
File srcImgFile = new File(batch.getImagePath());
//文件转化为图片
Image srcImg = ImageIO.read(srcImgFile);
//获取图片的宽
int srcImgWidth = srcImg.getWidth(null);
//获取图片的高
int srcImgHeight = srcImg.getHeight(null);
System.out.println("图片的宽度是=" + srcImgWidth + "; 图片的高度是=" + srcImgHeight);
// 加水印
BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bufImg.createGraphics();
g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
for (WatermarkAssist watermark:batch.getWatermarkAssists()){
g.setColor(matchColor(watermark.getFontColor()));
g.setFont(matchFont(watermark.getFontType(), watermark.getFontStyle(), watermark.getFontSize()));
//画出水印
g.drawString(watermark.getParamValue()
, transformDataType(watermark.getFontAbscissa())
, transformDataType(watermark.getFontOrdinate()) + transformDataType(watermark.getFontSize()));
}
g.dispose();
// 输出图片
FileOutputStream outImgStream = new FileOutputStream(batch.getImageOutPath());
ImageIO.write(bufImg, "jpg", outImgStream);
System.out.println("添加水印完成");
outImgStream.flush();
outImgStream.close();
}else{
throw new RuntimeException("文字信息缺失!");
}
return base64String;
}
/**
* 颜色匹配
* @param fontColor 字体颜色
* @return 返回颜色对象
*/
private Color matchColor(String fontColor){
Color color = null;
switch (fontColor){
case "red" :
color = Color.red;
break;
case "white" :
color = Color.white;
break;
case "lightGray" :
color = Color.lightGray;
break;
case "gray" :
color = Color.gray;
break;
case "darkGray" :
color = Color.darkGray;
break;
case "pink" :
color = Color.pink;
break;
case "orange" :
color = Color.orange;
break;
case "yellow" :
color = Color.yellow;
break;
case "green" :
color = Color.green;
break;
case "magenta" :
color = Color.magenta;
break;
case "cyan" :
color = Color.cyan;
break;
case "blue" :
color = Color.blue;
break;
default:
color = Color.black;
}
return color;
}
/**
* 匹配字体
* @param familyName 字体类型,例如宋体、仿宋等;
* @param fontStyle 字体风格,例如斜体字、加粗等;
* @param fontSize 字体大小;
* @return 返回字体对象
*/
private Font matchFont(String familyName,String fontStyle,String fontSize){
int style = 0;
switch (fontStyle){
case "PLAIN" :
//普通
style = Font.PLAIN;
break;
case "BOLD" :
//加粗
style = Font.BOLD;
break;
case "ITALIC" :
//斜体
style = Font.ITALIC;
break;
default:
//粗斜体
style = Font.BOLD+ Font.ITALIC;
}
return new Font(familyName, style, Integer.parseInt(fontSize));
}
/**
* 转换字体的宽高
* @param fontData 字体数据
* @return 返回int类型
*/
private int transformDataType(String fontData){
return new Double(Double.parseDouble(fontData)).intValue();
}
}
颜色这边若要根据取色器来制作字体颜色的话,可以获取取色器传过来的16进制码来转成color对象,贴出工具类
@Slf4j
public class ColorUtil {
/**
* 16进制码转Color对象
* @param str
* @return
*/
public static Color fromStrToARGB(String str) {
if (str.length() == 7 && StringUtils.startsWith(str, "#")){
str = str.replace("#", "FF");
}
String str1 = str.substring(0, 2);
String str2 = str.substring(2, 4);
String str3 = str.substring(4, 6);
String str4 = str.substring(6, 8);
int alpha = Integer.parseInt(str1, 16);
int red = Integer.parseInt(str2, 16);
int green = Integer.parseInt(str3, 16);
int blue = Integer.parseInt(str4, 16);
Color color = new Color(red, green, blue, alpha);
return color;
}
/**
* Color对象转16进制码
* @param color
* @return
*/
public static String colorToHexValue(Color color) {
return intToHexValue(color.getAlpha()) + intToHexValue(color.getRed()) + intToHexValue(color.getGreen()) + intToHexValue(color.getBlue());
}
public static String intToHexValue(int number) {
String result = Integer.toHexString(number & 0xff);
while (result.length() < 2) {
result = "0" + result;
}
return result.toUpperCase();
}
}