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