Jade Dungeon

Java2D

字体

加载外部字体

package net.jadedungeon.javautil.image;

import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.imageio.ImageIO;

public class FontUtils {

	/**
	 * Print fonts on image
	 * 
	 * @param text   text Str
	 * @param font   text font
	 * @param width  image width
	 * @param height image height
	 * @param x      text x pos
	 * @param y      text y pos
	 * @return image
	 */
	public static BufferedImage drawChars(
			String text, Font font, int width, int height, int x, int y) //
	{
		BufferedImage bimg = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
		Graphics2D gph = bimg.createGraphics();
		gph.setFont(font);
		gph.drawString(text, x, y);
		return bimg;
	}

	/**
	 * load a ttf Fonts File
	 * 
	 * @param fontFileName full path name of ttf File
	 * @param fontSize     font size
	 * @return font
	 */
	public static Font loadTTF(String fontFileName, float fontSize) {
		try (FileInputStream fi = new FileInputStream(fontFileName)) {
			Font dynamicFont = Font.createFont(Font.TRUETYPE_FONT, fi);
			Font dynamicFontPt = dynamicFont.deriveFont(fontSize);
			return dynamicFontPt;
		} catch (Exception e) {
			e.printStackTrace();
			return new java.awt.Font("宋体", Font.PLAIN, (int) fontSize);
		}
	}

	public static void main(String[] args) throws Exception {
		Font font = loadTTF("/AaSpot.ttf", 20);// 调用
		BufferedImage img = drawChars("Hello World", font, 138, 38, 10, 25);
		ImageIO.write(img, "jpg", new FileOutputStream(new File("/out.jpg")));
	}

}

字体高宽位置

java.awt.FontMetrics这个类对文字的宽高位置有详细的介绍。 计算使用字体的一段字符串的宽与高:

	/**
	 * caculate the image size of a line of chars
	 * 
	 * @param font    using font
	 * @param content text contenx
	 * @return int arr [width, height]
	 */
	public static int[] calLineSize(Font font, String content) {
		int[] result = { 0, 0 };
		FontDesignMetrics fm = FontDesignMetrics.getMetrics(font);
		int height = fm.getHeight();
		int width = 0;
		for (int i = 0; i < content.length(); i++) {
			width += fm.charWidth(content.charAt(i));
		}
		result[0] = width;
		result[1] = height;
		return result;
	}

字体基线高度

Ascent是从基线到顶部最大的高,也可以当做一个种字体画图时最有可以点用的高度:

graphics.drawString(content, 0, metrics.getAscent());

一个有中文与英文的字符串。 中文与英文字符的宽高是不一样的:

chinese.english

如果想要生成一张宽高刚的图片,这样我就需要计算每一个字符的宽度,及合适的高;

import sun.font.FontDesignMetrics;
 
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.LineMetrics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
 
/**
 * Created by zengrenyuan on 18/5/11.
 */
public class ImageTest {
 
	public static void main(String[] args) throws IOException {
		Font font = new Font("微软雅黑", Font.BOLD, 32);
		String content = "你好Java!";
		FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font);
		int width = getWordWidth(font, content);//计算图片的宽
		int height = metrics.getHeight();//计算高
		
		BufferedImage bufferedImage = new BufferedImage(
				width, height, BufferedImage.TYPE_INT_RGB);
		
		Graphics2D graphics = bufferedImage.createGraphics();
		graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, //
				RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		graphics.setComposite(//
				AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
		//设置背影为白色
		graphics.setColor(Color.WHITE);
		graphics.fillRect(0, 0, bufferedImage.getWidth(), //
				bufferedImage.getHeight());
		graphics.setFont(font);
		graphics.setColor(Color.BLACK);
		graphics.drawString(content, 0, metrics.getAscent());//图片上写文字
		graphics.dispose();
		write(bufferedImage, "/data/test.png");
	}
 
	public static int getWordWidth(Font font, String content) {
		FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font);
		int width = 0;
		for (int i = 0; i < content.length(); i++) {
			width += metrics.charWidth(content.charAt(i));
		}
		return width;
	}
 
	public static void write(BufferedImage bufferedImage, String target) //
		throws IOException //
	{
		File file = new File(target);
		if (!file.getParentFile().exists()) {
			file.getParentFile().mkdirs();
		}
		try (OutputStream os = new FileOutputStream(target)) {
			ImageIO.write(bufferedImage, "PNG", os);
		}
	}
	
}