package com.epean.trade.lms.util;
import com.alibaba.fastjson.JSONObject;
import com.epean.trade.component.entity.watermark.SysWatermark;
import com.epean.trade.component.enums.WatermarkCodeEnum;
import com.epean.trade.component.mapper.watermark.SysWatermarkMapper;
import com.epean.trade.framework.exception.BaseAppException;
import com.google.common.io.FileBackedOutputStream;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.font.FontDesignMetrics;
import tk.mybatis.mapper.entity.Example;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 添加水印工具类
* Created by IntelliJ IDEA.
* Date: 2019-07-29
* Since: JDK1.8
*/
public class WatermarkUtils implements Serializable {
private static final long serialVersionUID = -184614654848842705L;
private static final Logger logger = LoggerFactory.getLogger(WatermarkUtils.class);
/**
* 添加水印
*
* @param srcImagePath 需要添加水印的文件(文件全路径)
* @param watermarkIds 水印的ids (多个id使用 "," 分隔)
* @param imgPrefix 水印图片所在位置前缀
* @param sysWatermarkMapper 水印管理mapper对象
* @return 返回ftp需要的输入流
*/
public static InputStream addWatermark(String srcImagePath, String watermarkIds, String imgPrefix, SysWatermarkMapper sysWatermarkMapper) throws Exception {
if (StringUtils.isBlank(srcImagePath)) throw new BaseAppException(WatermarkCodeEnum.ERROR_SRC_CODE.getValue());
String fileSuffix = srcImagePath.substring(srcImagePath.lastIndexOf(".") + 1);
if (StringUtils.isBlank(watermarkIds)) throw new BaseAppException(WatermarkCodeEnum.ERROR_ID_CODE.getValue());
List<String> ids = Arrays.stream(watermarkIds.split(",")).collect(Collectors.toList());
Example example = new Example(SysWatermark.class);
Example.Criteria criteria = example.createCriteria();
criteria.andIn("id", ids);
criteria.andEqualTo("status", 1);
List<SysWatermark> sysWatermarks = sysWatermarkMapper.selectByExample(example);
if (CollectionUtils.isEmpty(sysWatermarks))
throw new BaseAppException(WatermarkCodeEnum.ERROR_TEMPLATE_CODE.getValue());
logger.info("查询得到的水印个数{}", sysWatermarks.size());
File srcFile = new File(srcImagePath);
Image srcImage = ImageIO.read(srcFile);
//创建画板
BufferedImage bufferedImage = new BufferedImage(srcImage.getWidth(null), srcImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
//创建画笔
Graphics2D graphics = bufferedImage.createGraphics();
graphics.drawImage(srcImage, 0, 0, srcImage.getWidth(null), srcImage.getHeight(null), null);
//添加水印
Map<String, Double> coordinate;
logger.info("开始绘制水印,水印个数{}", sysWatermarks.size());
for (SysWatermark temp : sysWatermarks) {
//水印类型(0:图片水印;1文字水印)
if (!temp.getWatermarkType()) {
File watermarkFile = new File(imgPrefix + temp.getWatermarkUrl());
Image watermarkImage = ImageIO.read(watermarkFile);
ImageIcon imageIcon = new ImageIcon(watermarkImage);
Image watermarkIconImage = imageIcon.getImage();
//填充属性
logger.info("开始填充图片水印属性值");
//透明度(注意此处如果事int类型,需要转成float类型,否则你会发现计算结果一直是0,导致显示不出来你的水印!!!!)
float transparency = (float) temp.getWatermarkTransparency() / 100;
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, transparency));
coordinate = changeStringToMap(temp.getWatermarkCoordinate());
graphics.drawImage(watermarkIconImage,
(int) (coordinate.get("width") / 100 * srcImage.getWidth(null)),
(int) (coordinate.get("height") / 100 * srcImage.getHeight(null)), null);
continue;
}
//将16进制的颜色转化为rgb
Color fontColor = new Color(Integer.valueOf(temp.getWatermarkFontColor().substring(1), 16));
Font font = new Font(temp.getWatermarkFontType(), Font.PLAIN, temp.getWatermarkSize());
FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font);
//绘制矩形
coordinate = changeStringToMap(temp.getWatermarkCoordinate());
//设置填充矩形背景颜色:(需要先画一个空心的矩形,然后再画一个实心的矩形就可以实现透明度,否则没有办法达到效果)
graphics.setColor(new Color(Integer.valueOf(temp.getWatermarkFontBackgroundColor().substring(1), 16)));
graphics.drawRect(
(int) ((coordinate.get("width") / 100) * srcImage.getWidth(null)),
(int) ((coordinate.get("height") / 100) * srcImage.getHeight(null)),
metrics.stringWidth(temp.getWatermarkFontContent()), metrics.getHeight());
//设置矩形的透明度
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ((float) temp.getWatermarkTransparency() / 100)));
graphics.fillRect(
(int) ((coordinate.get("width") / 100) * srcImage.getWidth(null))
, (int) ((coordinate.get("height") / 100) * srcImage.getHeight(null))
, metrics.stringWidth(temp.getWatermarkFontContent()), metrics.getHeight());
//设置字体
graphics.setColor(fontColor);
graphics.setFont(font);
graphics.drawString(temp.getWatermarkFontContent(),
(int) ((coordinate.get("width") / 100) * srcImage.getWidth(null)),
(int) ((coordinate.get("height") / 100) * srcImage.getHeight(null)) + metrics.getAscent());
}
logger.info("绘制水印结束");
graphics.dispose();
//本地测试开始
OutputStream out = new FileOutputStream(new File("D:/test.jpg"));
ImageIO.write(bufferedImage, fileSuffix, out);
//本地测试结束(如果是本地测试下面的不需要)
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, fileSuffix, os);
return new ByteArrayInputStream(os.toByteArray());
}
/**
* @param string 图片定位
* @return [keys: width , height]
*/
private static Map<String, Double> changeStringToMap(String string) {
Map<String, Double> map = new HashMap<>();
JSONObject object = JSONObject.parseObject(string);
map.put("width", (double) (int) object.get("width"));
map.put("height", (double) (int) object.get("height"));
return map;
}
}
测试类 :
@RunWith(SpringRunner.class)
@SpringBootTest(classes = EpTradeLmsApplication.class)
public class WaterMarkTest {
@Resource
private SysWatermarkMapper sysWatermarkMapper;
@Test
public void test1() throws Exception {
InputStream inputStream = WatermarkUtils.addWatermark("C:\\Users\\admin\\Desktop\\2.JPG",
"12,13", "C:\\Users\\admin\\Desktop\\", sysWatermarkMapper);
}
}
在使用这个的时候,, watermarkIds 和 sysWatermarkMapper 这两个参数可以不需要;这两个的作用是查询对应的水印模板,获取参数,自己根据自己的业务场景更换即可