Java Graphics2D 图片加水印

近期接到了一个新需求:

  • 将图片左上角和右下角上水印,具体图如下:

  • 需要编写一个Java工具类。

参考代码:Java给图片增加水印,根据图片大小自适应,右下角/斜角/平铺

完整代码如下:

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;


public class ImageWatermarkUtils {
    /**
     * 图片输入路径
     */
    private static final String INPUT_PATH = "D:\\code\\July2023\\werunJuly\\testImage\\img_9.png";
    /**
     * 图片输出格式
     */
    private static final String OUTPUT_FORMAT = "Output_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMdd_HH_mm_ss")) + ".png";
    /**
     * 图片输出路径
     */
    private static final String OUTPUT_PATH = "D:\\code\\July2023\\werunJuly\\testImage\\";
    /**
     * 人像Icon图片路径
     */
    private static final String PORTRAIT_ICON_PATH = "testImage/person.png";
    /**
     * 地址Icon图片路径
     */
    private static final String LOCATION_ICON_PATH = "testImage/location.png";

    /**
     * 添加图片水印
     * @param name 姓名
     * @param location 地址
     */
    public static void addWatermark(String name, String location) throws IOException {
        // 初始化,加载输入图片
        File file = new File(INPUT_PATH);
        BufferedImage inputImage = ImageIO.read(file);

        // 获取源图片的长度和宽度
        int imageWidth = inputImage.getWidth();
        int imageHeight = inputImage.getHeight();

        // 根据图片分辨率确定水印基准的大小
        int baseSize;
        if (inputImage.getHeight() > inputImage.getWidth()) {
            baseSize = inputImage.getWidth() / 40;
        }
        else {
            baseSize = inputImage.getHeight() / 30;
        }
        // 基本字体基准大小
        int fontBaseSize = (int) (baseSize * 1.3);

        // 创建输出g2d
        BufferedImage outputImage = new BufferedImage(inputImage.getWidth(), inputImage.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = outputImage.createGraphics();
        // 绘制原始图片
        g2d.drawImage(inputImage, 0, 0, null);

        // 绘制左上角时间
        g2d.setFont(new Font("黑体", Font.PLAIN, baseSize * 3));
        g2d.setColor(Color.WHITE);
        g2d.drawString(
                LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm")),
                (int) (2.0 * baseSize),
                (int) (4.3 * baseSize)
        );


        String[] weekDays = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
        Calendar calendar= Calendar.getInstance();
        // 绘制左上角日期
        g2d.setFont(new Font("黑体", Font.PLAIN, fontBaseSize));
        g2d.drawString(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy.MM.dd " + weekDays[calendar.get(Calendar.DAY_OF_WEEK)-1])),
                (int) (2.2 * baseSize),
                (int) (6.1 * baseSize));

        // 绘制右下角姓名
        g2d.drawString(
                name,
                imageWidth - getStrWidth(name, fontBaseSize) - (int) (0.7 * baseSize),
                imageHeight - (int) 3.5 * baseSize
        );

        // 绘制右下角地址
        g2d.drawString(
                location,
                imageWidth - getStrWidth(location, fontBaseSize) - (int) (0.7 * baseSize),
                imageHeight - baseSize
        );

        // 载入人像Icon图片
        File portraitIconFile = new File(PORTRAIT_ICON_PATH);
        BufferedImage portraitImage = ImageIO.read(portraitIconFile);
        // 绘制人像Icon图片
        g2d.drawImage(
                portraitImage,
                imageWidth - getStrWidth(name, fontBaseSize) - fontBaseSize - (int) (0.8 * baseSize),
                imageHeight - (int) 3.1 * baseSize - fontBaseSize,
                fontBaseSize, fontBaseSize,
                null
        );


        // 载入地址Icon图片
        File locationIconFile = new File(LOCATION_ICON_PATH);
        BufferedImage locationImage = ImageIO.read(locationIconFile);
        // 绘制地址Icon图片
        g2d.drawImage(
                locationImage,
                imageWidth - getStrWidth(location, fontBaseSize) - fontBaseSize - (int) (0.8 * baseSize),
                imageHeight - fontBaseSize - (int) (0.8 * baseSize),
                fontBaseSize, fontBaseSize,
                null
        );

        // 输出
        ImageIO.write(outputImage,"png",new File(OUTPUT_PATH + OUTPUT_FORMAT));
    }

    // 绘制右下角区域时需要的相关方法
    private static int getStrWidth(String str, int fontSize) {
        char[] chars = str.toCharArray();
        int fontSize2 = fontSize / 2;

        int width = 0;

        for (char c : chars) {
            int len = String.valueOf(c).getBytes().length;
            // 汉字为3,其余1
            // 可能还有一些特殊字符占用2等等,统统计为汉字
            if (len != 1) {
                width += fontSize;
            } else {
                width += fontSize2;
            }
        }
        return width;
    }
    public static void main(String[] args) throws IOException {
        addWatermark("小趴菜才","V专分发基地");
    }
}