在图片上指定区域写文字,超过长度自动换行

    public static void main(String[] args) throws IOException {
        BufferedImage bufferedImage = ImageIO.read(new File("/opt/test/imgTest/xmbg.jpeg"));
        String str = "spark系统执行任务异常:error,Null Point Exception,任务状态【失败】,发生时间:2022-06-17 00:00:00,超过90%任务失败,请尽快查看!下面是瞎写的,模拟很多字的情况,打开手机号多少但还是卡的很两三点非,mission fail!!";
        // 指定区域,左对齐
        drawString(bufferedImage.createGraphics(), str, 350, 50, 200, 200);
        ImageIO.write(bufferedImage, "png", new File("/opt/test/imgTest/xmbg-3.jpeg"));
    }

    /**
     * 在指定区域写文字,超过长度自动换行
     *
     * @param g2d       Graphics2D类
     * @param text      需要写的字符串
     * @param x         第一行文字x坐标
     * @param y         第一行文字y坐标
     * @param maxWidth  一行最大宽度
     * @param maxHeight 文本可展示的最大高度,如果行数过多,会自动缩小字体
     * @return 行数
     */
    public static TextInfoDto drawString(Graphics2D g2d, String text, int x, int y, int maxWidth, int maxHeight) {
        TextInfoDto textInfoDto = new TextInfoDto();

        // 根据规定的最大宽度与高度,自动缩小字体
        fitFontSize(g2d, text, maxWidth, maxHeight);

        FontMetrics fontMetrics = g2d.getFontMetrics();
        // 字符串高、宽
        int textHeight = fontMetrics.getHeight();
        int textWidth = fontMetrics.stringWidth(text);

        textInfoDto.setWidth(textWidth);
        textInfoDto.setHeight(textHeight);

        int lineCount = 0;
        String tempText = text;
        while (textWidth > maxWidth) {
            // 用每个字的宽度累加,计算一行需要多少字
            int lineStrWidth = 0;
            int charCount = 0;
            while (lineStrWidth < maxWidth) {
                lineStrWidth += fontMetrics.charWidth(tempText.charAt(charCount));
                charCount++;
            }

            String drawText = tempText.substring(0, charCount);
            // 本行文本宽度
            int subTxtWidth = fontMetrics.stringWidth(drawText);
            // 如果字数长度不够就加点
            while (subTxtWidth < maxWidth && charCount < tempText.length()) {
                charCount++;
                drawText = tempText.substring(0, charCount);
                subTxtWidth = fontMetrics.stringWidth(drawText);
            }
            // 如果字数长度超了就减点
            while (subTxtWidth > maxWidth) {
                charCount--;
                drawText = tempText.substring(0, charCount);
                subTxtWidth = fontMetrics.stringWidth(drawText);
            }
            lineCount++;
            g2d.drawString(drawText, x, y);
            if (charCount >= tempText.length()) {
                tempText = "";
                break;
            }
            y += textHeight;
            textWidth = textWidth - subTxtWidth;
            tempText = tempText.substring(charCount);
        }
        if (StringUtils.isNotBlank(tempText)) {
            // 本行长度小于最大宽度,或者最后一行剩下的几个字
            g2d.drawString(tempText, x, y);
            lineCount++;
        }

        textInfoDto.setLineCount(lineCount);
        log.info("drawString,textInfoDto={}", textInfoDto);
        return textInfoDto;
    }

    /**
     * 根据规定的最大宽度与高度,自动缩小字体
     */
    public static void fitFontSize(Graphics2D g2d, String text, int maxWidth, int maxHeight) {
        FontMetrics fontMetrics = g2d.getFontMetrics();
        // 字符串高、宽
        int textHeight = fontMetrics.getHeight();
        int textWidth = fontMetrics.stringWidth(text);

        // 当前字体,写全部字大概需要多少行
        int tmpLineCount = textWidth / maxWidth;
        if (textWidth % maxWidth > 0) {
            tmpLineCount++;
        }
        log.info("原字fontSize=" + fontMetrics.getFont().getSize());
        // 修改字体大小
        while (textHeight * tmpLineCount > maxHeight) {
            Font font = g2d.getFont();
            // 太小就看不清了
            if (font.getSize() <= 8) {
                break;
            }
            g2d.setFont(new Font(font.getName(), font.getStyle(), font.getSize() - 1));

            // 重新获取字体宽高
            fontMetrics = g2d.getFontMetrics();
            textHeight = fontMetrics.getHeight();
            textWidth = fontMetrics.stringWidth(text);

            tmpLineCount = textWidth / maxWidth;
            if (textWidth % maxWidth > 0) {
                tmpLineCount++;
            }
        }
        log.info("修改后fontSize=" + g2d.getFont().getSize());
    }


@Data
public class TextInfoDto {

    @ApiModelProperty("文字高度")
    private Integer height;

    @ApiModelProperty("文字宽度")
    private Integer width;

    @ApiModelProperty("换行行数")
    private Integer lineCount;

    @Override
    public String toString() {
        return JSON.toJSONString(this, SerializerFeature.WriteMapNullValue);
    }
}

 

posted @ 2022-06-17 11:54  轨迹320  阅读(324)  评论(0编辑  收藏  举报