Java Font 居中


居中

看到网上经常有这样的一些头像,是纯色加上第一个文字,类似于这样子的:
 
我们也想自己做一套,考虑到有很多端都要用,因此选择在服务端实现这样的头像。开发语言是Java。
 
在java里面往图片里面写一段文字一般采用 Graphic类的drawString方法,看下drawString方法的介绍:
public abstract void drawString(String str,int x,int y)
 

Draws the text given by the specified string, using this graphics context's current font and color. The baseline of the leftmost character is at position (x, y) in this graphics context's coordinate system.
显然此处的str字段只需要写一个字符的即可。x和y表示的是起始的位置,在这儿和图像的不大一样,指的是右下角的位置。
根据要求我要生成的图片大小是216*216的,字体大小是136px。 对于ASCII码表上面的字母、字符和数字,通常宽度都是为汉字的一半,因此在调用的时候要注意好起始点的间距。拿汉字来举例的话,应该文字是处在 (40,40)到 (176,176)的正方形里面。因此此处的x和y我填写的是40和176.

看下生成的图片:
绿色的线表示的就是(40,40)到(176,176)的正方形。可以看到在x轴上面是居中的,但是在y轴上却明显地偏下方。那么到底偏了多少,怎么补偿呢?不能瞎算,此处肯定跟字体是有关系的!搜索没得要领(估计是自己没找对关键字),然后幸好手头有本《Java核心技术 卷1:基础知识》,看了看里面字体的一节,解答了我的疑惑。
其实在这个类的说明里面指出了一些线索,不过刚接触的时候很难知道有这个类:
FontMetrics   里面有段话是这样的:
When an application asks to place a character at the position (x, y), the character is placed so that its reference point (shown as the dot in the accompanying image) is put at that position. The reference point specifies a horizontal line called the baseline of the character. In normal printing, the baselines of characters should align。
意思是,我们设置x和y的时候实际上设置的是参考点的位置,参考点就是上面的那个点。参考点所在的水平线是 baseline 基线,最上面的线是坡顶(ascenter),, 最下面的线是坡底(descenter)。坡顶到基线的距离是 上坡度(ascent), 坡底到基线的距离是下坡度。
 

基准点是baseline
Ascent是baseline之上至字符最高处的距离
Descent是baseline之下至字符最低处的距离
Leading表示本文行之间的距离
getheight() //字体高度 ascent+Descent+ Leading
StringWidth(String) //字符串宽度

看下图:

 

 

 
  
java中计算以上值的方法如下:
FontRenderContext context = g2d.getFontRenderContext(); LineMetrics lineMetrics = font.getLineMetrics(str, context); System.out.println("lineMetrics.getAscent()=" + lineMetrics.getAscent()); System.out.println("lineMetrics.getDescent()=" + lineMetrics.getDescent()); System.out.println("lineMetrics.getHeight()=" + lineMetrics.getHeight()); System.out.println("lineMetrics.getLeading()=" + lineMetrics.getLeading());

计算下x,y的位置, 对于水平方向的位置,很简单:

int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();

double x = (width - 136) /2;
对于垂直方向上的位置,上下边留空白是: height - (ascend + descend)/ 2;
注意字的位置不是左上角算起的,因此套住字的左下角的框框是: height - 上面的式子 = (height + ascend + descend) / 2;
再注意,x,y指的是baseline的,因此还需要减去一个descend的距离,因此最终应该是 (height + ascend - descend)/2 的距离,不过最后测试,还要减去一个leading的距离

最终的y  =  (height +ascend - descend - leading()) / 2

最后要开启抗锯齿模式

graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);  

 完整的代码如下:

 1     public static void main(String[] args) throws IOException {
 2 
 3         String str = "吴";
 4         int size = 216; // 图片的宽和高
 5         int fontSize = 136; // 字体大小
 6         BufferedImage bufferedImage = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
 7 
 8         Graphics2D g2d = bufferedImage.createGraphics();
 9 
10         g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
11 
12         Font font = new Font("宋体", Font.PLAIN, fontSize);
13         g2d.setFont(font);
14 
15         g2d.setBackground(new Color(103, 172, 237));// 设置背景色
16         g2d.clearRect(0, 0, size, size);// 通过使用当前绘图表面的背景色进行填充来清除指定的矩形。
17         g2d.setPaint(Color.WHITE);// 设置画笔,设置Paint属性
18 
19         FontRenderContext context = g2d.getFontRenderContext();
20         LineMetrics lineMetrics = font.getLineMetrics(str, context);
21 
22         System.out.println("lineMetrics.getAscent()=" + lineMetrics.getAscent());
23         System.out.println("lineMetrics.getDescent()=" + lineMetrics.getDescent());
24 
25         System.out.println("lineMetrics.getHeight()=" + lineMetrics.getHeight());
26         System.out.println("lineMetrics.getLeading()=" + lineMetrics.getLeading());
27 
28         float offset = (size - fontSize) / 2;
29         float y = (size + lineMetrics.getAscent() - lineMetrics.getDescent() - lineMetrics.getLeading()) / 2;
30 
31         g2d.drawString(str, offset, y);
32 
33         g2d.dispose();
34 
35         ImageIO.write(bufferedImage, "JPEG", new File("d:\\wu.jpg"));
36     }
View Code

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM