本文介绍如何使用 Java 程序在图片下方居中添加文字,以及中文字体的判断与加载。

准备

本例使用的图片如下,尺寸为1000 * 1000

代码逻辑


import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;

public class AddTextToImage {
    public static void main(String[] args) throws Exception {
        // 加载原图
        BufferedImage originalImage = ImageIO.read(new File("/Users/lin/Desktop/demo.jpg"));

        // 添加的文字
        String text = "机器猫";
        // 加载字体
        Font font = loadFont("宋体", Font.BOLD, 16);

        // 创建新的图片,新图片比旧图高100
        BufferedImage newImage = new BufferedImage(originalImage.getWidth(), originalImage.getHeight() + 100, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = newImage.createGraphics();


        // 计算文字的宽高
        FontMetrics metrics = graphics.getFontMetrics();
        int textWidth = metrics.stringWidth(text);
        int textHeight = metrics.getHeight();

        // 计算文字的居中位置
        int x = (newImage.getWidth() - textWidth) / 2;
        int y = originalImage.getHeight() + 50; // 50:文字在图片下方的距离

        // 在新图上绘制文字
        graphics.setFont(font);
        graphics.drawString(text, x, y);

        // 将原始图片的内容复制到新图片上
        graphics.drawImage(originalImage, 0, 0, null);

        // 保存新图片
        ImageIO.write(newImage, "jpg", new File("/Users/lin/Desktop/demo_new.jpg"));

        graphics.dispose();
    }

    /**
     * 加载字体。
     * 指定的字体不支持中文的话,则使用系统中支持中文的字体
     *
     * @param fontName 字体名称
     * @param style 样式
     * @param size 字体大小
     * @return
     */
    public static Font loadFont(String fontName, int style, int size) {
        // “中”子的 unicode 编码
        char verifyText = '\u4e2d';
        Font font = new Font(fontName, Font.BOLD, 16);
        if (font.canDisplay(verifyText)) {
            return font;
        }

        Font[] systemFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
        for (Font systemFont : systemFonts) {
            if (systemFont.canDisplay(verifyText)) {
                return systemFont;
            }
        }
        return font;
    }
}

生成效果:

优化

生成的图片有 2 个问题:

  • 尺寸由原来的1000 * 1000变成1000 * 1100
  • 增加的高度为黑色的背景

优化结果:

  • 维持新图尺寸的对称,变为1100 * 1100
  • 使用原背景色填充新增加的背景

代码实现:

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;

public class AddTextToImage {
    public static void main(String[] args) throws Exception {
        // 加载原图
        BufferedImage originalImage = ImageIO.read(new File("/Users/lin/Desktop/demo.jpg"));

        // 添加的文字
        String text = "机器猫";
        // 加载字体
        Font font = loadFont("宋体", Font.BOLD, 16);

        // 创建新的图片,新图片比旧图宽100,高100
        BufferedImage newImage = new BufferedImage(originalImage.getWidth() + 100, originalImage.getHeight() + 100, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = newImage.createGraphics();
        // 设置抗锯齿
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);


        //设置新图背景色
        graphics.setColor(new Color(222,235,252));
        graphics.fillRect(0, 0, newImage.getWidth(), newImage.getHeight());

        // 将原始图片的内容复制到新图片上,原图在新图上左右居中
        graphics.drawImage(originalImage, 50, 0, null);

        // 计算文字的宽高
        FontMetrics metrics = graphics.getFontMetrics();
        int textWidth = metrics.stringWidth(text);
        int textHeight = metrics.getHeight();
        int ascent = metrics.getAscent();//字符最高点距离基线上方的距离

        // 计算文字的居中位置
        int x = (newImage.getWidth() - textWidth) / 2;
        int y = originalImage.getHeight() + (100 - textHeight) / 2 + ascent; // 文字在图片下方 100 区域内的上下居中距离

        // 在新图上绘制文字
        graphics.setFont(font);
        graphics.setColor(Color.BLACK);
        graphics.drawString(text, x, y);


        // 保存新图片
        ImageIO.write(newImage, "jpg", new File("/Users/lin/Desktop/demo_new.jpg"));

        graphics.dispose();
    }

    /**
     * 加载字体。
     * 指定的字体不支持中文的话,则使用系统中支持中文的字体
     *
     * @param fontName 字体名称
     * @param style    样式
     * @param size     字体大小
     * @return
     */
    public static Font loadFont(String fontName, int style, int size) {
        // “中”子的 unicode 编码
        char verifyText = '\u4e2d';
        Font font = new Font(fontName, Font.BOLD, 16);
        if (font.canDisplay(verifyText)) {
            return font;
        }

        Font[] systemFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
        for (Font systemFont : systemFonts) {
            if (systemFont.canDisplay(verifyText)) {
                return systemFont;
            }
        }
        return font;
    }
}

生成效果: