图片增加水印功能
package com.gofun.api.utils; import org.springframework.mock.web.MockMultipartFile; import org.springframework.web.multipart.MultipartFile; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; /** * @Author ZhangYuLong * @Description 图片水印工具类 * @Date 2023/7/19 11:29 * @Version 1.0 **/ public class PicWaterMarkUtil { private static Color textColor = Color.RED; /** * 把照片增加水印并返回 * @param mfile * @param fontSize * @param dateStr * @param waterMarkContent */ public static MultipartFile addTextWaterMark(MultipartFile mfile, int fontSize, String dateStr, String waterMarkContent) { try { BufferedImage targetImg = ImageIO.read(mfile.getInputStream()); int width = targetImg.getWidth(); //图片宽 int height = targetImg.getHeight(); //图片高 BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_BGR); Graphics2D g = bufferedImage.createGraphics(); g.drawImage(targetImg, 0, 0, width, height, null); g.setColor(textColor); //水印颜色 g.setFont(new Font("微软雅黑", Font.ITALIC, fontSize)); // 水印内容日期 居中 //int x = (width - (dateStr.length()) * fontSize)/2; int x = width - 2*getWatermarkLength(dateStr, g); int y = height- fontSize * 2; g.drawString(dateStr, x, y); // 水印内容地址换行居中//todo begin int fontLength = getWatermarkLength(waterMarkContent, g); // 实际生成的水印文字,实际文字行数 Double textLineCount = Math.ceil(Integer.valueOf(fontLength).doubleValue() / Integer.valueOf(width).doubleValue()); // 实际所有的水印文字的高度 int textHeight = textLineCount.intValue() * fontSize; // 相对与X的起始的位置 int originX = 0; // 相对与Y的起始的位置 int originY = 0; // 实际文字大于1行,则x则为默认起始0, if (1 == textLineCount.intValue()) { // 实际文字行数是1,1/2个图片高度,减去1/2个字符高度 originY = height- fontSize; // 实际文字行数是1,计算x的居中的起始位置 originX = (width - fontLength) / 2; } else { // 实际文字行数大于1,1/2个图片高度减去文字行数所需的高度 originY = height - textHeight+fontSize; } System.out.println("水印文字总长度:" + fontLength + ",图片宽度:" + width + ",字符个数:" + waterMarkContent.length()); //文字叠加,自动换行叠加 int tempX = originX; int tempY = originY; int tempCharLen = 0;//单字符长度 int tempLineLen = 0;//单行字符总长度临时计算 StringBuffer stringBuffer = new StringBuffer(); for (int i = 0; i < waterMarkContent.length(); i++) { char tempChar = waterMarkContent.charAt(i); tempCharLen = getCharLen(tempChar, g); if (tempLineLen >= width) { // 绘制前一行 g.drawString(stringBuffer.toString(), tempX, tempY); //清空内容,重新追加 stringBuffer.delete(0, stringBuffer.length()); //文字长度已经满一行,Y的位置加1字符高度 tempY = tempY + fontSize; tempLineLen = 0; } //追加字符 stringBuffer.append(tempChar); tempLineLen += tempCharLen; } //最后叠加余下的文字 g.drawString(stringBuffer.toString(), tempX, tempY); //todo end //创建一个ByteArrayOutputStream ByteArrayOutputStream os = new ByteArrayOutputStream(); //把BufferedImage写入ByteArrayOutputStream ImageIO.write(bufferedImage, "jpg", os); //ByteArrayOutputStream转成InputStream InputStream input = new ByteArrayInputStream(os.toByteArray()); //InputStream转成MultipartFile MultipartFile multipartFile =new MockMultipartFile("file", "file.jpg", "text/plain", input); g.dispose(); return multipartFile; } catch (Exception e) { e.printStackTrace(); } return null; } private static int getCharLen(char c, Graphics2D g) { return g.getFontMetrics(g.getFont()).charWidth(c); } /** * 获取水印文字总长度 * * @paramwaterMarkContent水印的文字 * @paramg * @return水印文字总长度 */ private static int getWatermarkLength(String waterMarkContent, Graphics2D g) { return g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0, waterMarkContent.length()); } }
注意:图片水印增加中文时,显示方框解决方案
1、新建文件夹chinese,复制C:\Windows\Fonts下的字体文件到chinese目录
2、把chinese文件夹上传到centos下的/usr/share/fonts目录
3、执行cd /usr/share/fonts/chinese进入到chinese执行如下命令,生成一个fonts.scale文件.
注意:提示命令不存在则执行sudo dnf install ttmkfdir安装
ttmkfdir -e /usr/share/X11/fonts/encodings/encodings.dir
4、执行vim /etc/fonts/fonts.conf编辑配置文件,添加中文字体文件目录<dir>/usr/share/fonts/chinese</dir>
如果没有fonts.conf,则执行yum -y install fontconfig安装
5、刷新缓存
fc-cache fc-list|grep chinese