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 這兩個參數可以不需要;這兩個的作用是查詢對應的水印模板,獲取參數,自己根據自己的業務場景更換即可