java水印可自动调节字体大小支持透明度,字体,大小,颜色等设置

该博客介绍了如何使用Java生成带背景透明的水印图片,包括设置水印的颜色、尺寸、顺序、透明度等属性,并通过前端HTTP响应返回PNG格式的水印图像。示例代码展示了如何调整字体大小以适应水印区域,并实现文字倾斜和居中对齐。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

//如果没有使用lombok,请删除注解,执行实现构造方法和getter,setter
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Watermark implements Serializable {
    private String color = "#c7d4df";//"#e4ebf0";
    private Integer width = 200;
    private Integer height = 200;
    private String order;//顺序
    private String oa;
    private String username;
    private String telSuffix;//手机尾号
    private Integer fontSize = 20;
    private String fontFamily="microsoft-yahei";
    private Integer lineGap = 20;//水印图片中每行字符串的间隔
    private Float alpha=1.0f;//透明度
}
//生成背景透明的水印图片
import java.awt.*;
import java.awt.image.BufferedImage;

public class FontImage {

    public static boolean isEmpty(String str) {
        return (str == null || str.length() == 0);
    }

    public static BufferedImage buildWatermarkImage(Watermark watermark) {

        String oa = watermark.getOa();
        String username = watermark.getUsername();
        String telSuffix = watermark.getTelSuffix();

        telSuffix = isEmpty(telSuffix) ? "" : telSuffix;//为null的话,置为空串


        String longerString = oa.length() > username.length() ? oa : username;
        if (longerString.length() < telSuffix.length()) {
            longerString = telSuffix;
        }

        int defaultSize = watermark.getFontSize();
        Font font = new Font(watermark.getFontFamily(), Font.PLAIN, defaultSize);

        BufferedImage image = new BufferedImage(watermark.getWidth(), watermark.getHeight(), BufferedImage.TYPE_INT_ARGB);
        // background transparent start
        Graphics2D g = image.createGraphics();

        image = g.getDeviceConfiguration().createCompatibleImage(watermark.getWidth(), watermark.getHeight(), Transparency.TRANSLUCENT);//Transparency.TRANSLUCENT
        g.dispose();

        // background transparent end
        g = image.createGraphics();

        Color color = new Color(Integer.parseInt(watermark.getColor().substring(1), 16));
        g.setColor(new Color(color.getRed(),color.getGreen() ,color.getBlue() , new Float(255*watermark.getAlpha()).intValue()));


        g.setFont(font);// Set pen font


        int stringWidth = g.getFontMetrics(font).stringWidth(longerString);
        int size = defaultSize;

        //自动根据水印大小调节字体大小
        while (stringWidth > watermark.getWidth() && size >= 10) {
            size -= 1;
            font = new Font(watermark.getFontFamily(), Font.PLAIN, size);
            g.setFont(font);// Set pen font
            stringWidth = g.getFontMetrics(font).stringWidth(longerString);
        }


        g.shear(0.1, -0.6);// set the tilt

        // Set font smoothing
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        int y = watermark.getHeight() / 3 * 2;


        String order = watermark.getOrder();
        order = isEmpty(order) ? "out" : order;

        int lineGap = watermark.getLineGap();


        //顺序:o=oa,u=username,t=telsuffix
        for (int i = 0; i < order.length(); i++) {
            String chars = "";
            switch (order.charAt(i)) {
                case 'o':
                    chars += oa;
                    break;
                case 'u':
                    chars += username;
                    break;
                case 't':
                    chars += telSuffix;
                    break;
            }


            //align center

            int iStringWidth = g.getFontMetrics(font).stringWidth(chars);

            int x = watermark.getWidth() / 2 - iStringWidth / 2 - 10;

            g.drawString(chars, x, y);// draw a string
            y = y + (lineGap>0?lineGap:font.getSize());

            chars = "";
        }

        g.dispose();// Release the brush
        return image;

    }
}
//处理前端请求(这里省略Service,将逻辑放到controller)
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;

@Controller
public class WatermarkController{

    /**
     * @param oa       oa账户,以此获得账户名和手机尾号
     * @param w        水印宽度
     * @param h        水印高度
     * @param hexColor 十六进制颜色
     * @param order    顺序,用oa,username, tel首字母(o,u,t)排列(可重复)
     * @param response
     */
    @RequestMapping(value = "/wk_image", method = RequestMethod.GET, produces = MediaType.IMAGE_PNG_VALUE)
    public void image(String oa, String w, String h, String hexColor,String fontSize ,String fontFamily,String lineGap,String alpha, String order, HttpServletResponse response) {
        if (FontImage.isEmpty(oa)) {
            //自行处理异常
        }


        {
            //TODO 可以考虑将图像文件放到缓存里面,每次根据oa,从缓存里面获取
        }


        try (ServletOutputStream outputStream = response.getOutputStream()) {//这样写可以自动关闭流

            Watermark watermark = new Watermark();

            watermark.setOa(oa);
            watermark.setTelSuffix("测试账户名");//只要4位尾号,或者是加密的11位
            watermark.setUsername("1234");


            if (!FontImage.isEmpty(w) && w.matches("\\d+")) {
                watermark.setWidth(Integer.parseInt(w));
            }

            if (!FontImage.isEmpty(h) && h.matches("\\d+")) {
                watermark.setHeight(Integer.parseInt(h));
            }

            if (!FontImage.isEmpty(fontSize) && fontSize.matches("\\d+")) {
                watermark.setFontSize(Integer.parseInt(fontSize));
            }
            if (!FontImage.isEmpty(lineGap) && lineGap.matches("\\d+")) {
                watermark.setLineGap(Integer.parseInt(lineGap));
            }
            if (!FontImage.isEmpty(alpha) && alpha.matches("\\d+(\\.\\d*)?")) {
                watermark.setAlpha(Math.min(Float.parseFloat(alpha), 1.0f));
            }

            if (!FontImage.isEmpty(hexColor)) {
                watermark.setColor("#"+hexColor);
            }

            if (!FontImage.isEmpty(order)) {
                watermark.setOrder(order);
            }
            if (!FontImage.isEmpty(fontFamily)) {
                watermark.setFontFamily(fontFamily);
            }


            BufferedImage bufferedImage = FontImage.buildWatermarkImage(watermark);

            ImageIO.write(bufferedImage, "png", outputStream);


        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

效果图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值