絕對詳解PHP 的imageTtfText 函式

2021-10-20 11:19:04 字數 4595 閱讀 1775

對於php繪圖初學者,首先遇到的乙個問題就是,imagestring()這個函式並不支援漢字的繪製。這往往會給入門者當頭一棒,不過不要著急,因為還有乙個imagettftext()函式,這個函式能繪製utf-8編碼的字串,當然可以繪製漢字了。然而使用它並不十分簡單。先來看看其原型宣告:

一共有8個引數,缺一不可,而且官方文件這些引數的解釋並不透徹,這裡筆者盡力做更詳細清晰的解釋:

(1)$image 這個是畫布資源,無需再解釋;

(2)$size,官方文件的解釋是,字型大小,其長度單位依賴於gd庫的版本,對於gd1來說是畫素,對於gd2來說是磅(point)。現在一般都是gd2了,那麼這個磅究竟是什麼意思呢?這涉及到字型設計的基本知識。

簡單來說,磅是乙個長度度量單位,如果把一英吋等分成72份,每乙份就是1磅。這裡需要強調的是,磅是個絕對物理單位,與顯示裝置無關。

而畫素呢?畫素沒有固定的大小,而是與解析度相關,高解析度的顯示器畫素就很小,如iphone視網膜屏上乙個畫素的大小要比普通lcd顯示器的畫素小很多。然而有些東西是不存在解析度這個概念的,如單純的點陣圖,它的最小組成部分就是畫素,本身也是通過每個畫素的顏色值來定義的。把同樣的顯示在不同解析度的顯示器上,最終呈現出的大小是不同的。

操作點陣圖時,以畫素位單位最精確合理,那麼使用gd2庫的時候,如何繪製大小為20畫素的字呢?也就是多少磅才能等於20個畫素呢?這必須通過解析度才能計算出來,而問題是點陣圖本身並沒有解析度的概念。

現在把問題返回來,如果給定$size=20磅,那麼imagettftext()繪製完成時,究竟會占用多少畫素。無論如何,imagettftext()最終還是要把文字繪製落實到具體的位影象素上。

1磅 = ppi/72 個畫素

這個問題確實非常棘手,此函式內部必然會使用某個解析度ppi來計算被渲染的畫素區域。而gd2庫卻沒有提供任何讓使用者設定或者讀取這個解析度的方法。那麼,我們只能動手測試了。使用不同的磅值繪製文字,然後測量文字佔據的畫素,通過公式:

ppi = (72*畫素數)/磅值。實驗得出的結論是:

1磅==>4畫素, ppi=2882磅==>5畫素, ppi=1803磅==>7畫素, ppi=1684磅==>8畫素, ppi=1445磅==>9畫素, ppi=129.66磅==>10畫素, ppi=1207磅==>11畫素, ppi=113.142857142868磅==>12畫素, ppi=1089磅==>14畫素, ppi=11210磅==>15畫素, ppi=10811磅==>16畫素, ppi=104.7272727272712磅==>17畫素, ppi=10213磅==>18畫素, ppi=99.69230769230814磅==>19畫素, ppi=97.71428571428615磅==>21畫素, ppi=100.816磅==>22畫素, ppi=9917磅==>23畫素, ppi=97.41176470588218磅==>25畫素, ppi=10019磅==>26畫素, ppi=98.52631578947420磅==>27畫素, ppi=97.221磅==>28畫素, ppi=9622磅==>29畫素, ppi=94.90909090909123磅==>30畫素, ppi=93.91304347826124磅==>32畫素, ppi=9625磅==>33畫素, ppi=95.0426磅==>34畫素, ppi=94.15384615384627磅==>35畫素, ppi=93.33333333333328磅==>36畫素, ppi=92.57142857142929磅==>38畫素, ppi=94.34482758620730磅==>39畫素, ppi=93.631磅==>40畫素, ppi=92.90322580645232磅==>41畫素, ppi=92.2533磅==>43畫素, ppi=93.81818181818234磅==>44畫素, ppi=93.17647058823535磅==>46畫素, ppi=94.62857142857136磅==>47畫素, ppi=9437磅==>48畫素, ppi=93.40540540540538磅==>48畫素, ppi=90.94736842105339磅==>50畫素, ppi=92.30769230769240磅==>51畫素, ppi=91.841磅==>52畫素, ppi=91.31707317073242磅==>53畫素, ppi=90.85714285714343磅==>55畫素, ppi=92.09302325581444磅==>56畫素, ppi=91.63636363636445磅==>57畫素, ppi=91.246磅==>58畫素, ppi=90.78260869565247磅==>60畫素, ppi=91.91489361702148磅==>62畫素, ppi=9349磅==>63畫素, ppi=92.57142857142950磅==>63畫素, ppi=90.7251磅==>64畫素, ppi=90.35294117647152磅==>67畫素, ppi=92.76923076923153磅==>68畫素, ppi=92.37735849056654磅==>69畫素, ppi=9255磅==>70畫素, ppi=91.63636363636456磅==>71畫素, ppi=91.28571428571457磅==>72畫素, ppi=90.94736842105358磅==>74畫素, ppi=91.86206896551759磅==>75畫素, ppi=91.52542372881460磅==>76畫素, ppi=91.261磅==>77畫素, ppi=90.88524590163962磅==>78畫素, ppi=90.5806451612963磅==>79畫素, ppi=90.28571428571464磅==>81畫素, ppi=91.12565磅==>83畫素, ppi=91.93846153846266磅==>84畫素, ppi=91.63636363636467磅==>85畫素, ppi=91.3432835820968磅==>86畫素, ppi=91.05882352941269磅==>86畫素, ppi=89.73913043478370磅==>88畫素, ppi=90.51428571428671磅==>90畫素, ppi=91.26760563380372磅==>91畫素, ppi=9173磅==>92畫素, ppi=90.73972602739774磅==>93畫素, ppi=90.486486486486
可見當大於46磅時,ppi穩定在90,而小於46磅時,ppi一直在微變。

所以,如果你想繪製20個畫素大小的字型,那麼必須設定$size引數為:14.5磅。

另外需要注意的是,$size並不完全對應字型的顯示大小,因為同樣的$size,不同的字元佔據的空間並不是一樣的。例如,漢字「國」的寬度會比數字1的寬度大得多,對於標點符號,則更是這樣,半形和全形符號也不同。

總之,使用imagettftext()不可能精確控制到畫素級別,只能大概。這也算是向量字型的乙個小缺陷。

(3)$angle是旋轉角度。這個官網解釋的比較清楚,需要說明有兩點:一是角度單位是度而不是弧度,二是旋轉的中心點就是引數$x,$y。

(4)(5)$x,$y 被繪製字串的第乙個字元的基線點。單位是畫素。這裡涉及到字型設計的基本知識--基線。這個點絕對不是左上角,而具體是什麼取決於所使用的字型是如何設計的。對於宋體、楷體、黑體等常見的字型中的漢字,這個點大概位於字型的左下部分;而對於英文本母和標點符號,則各不相同。如下圖:

(6)$color 字型的顏色,不多解釋。

(7)$fontfile 字型檔案。也就是包含truetype字型字模的檔案,如楷體字庫案simkai.ttf。這種檔案的格式是有標準規範的,而且與平台無關。所以可以直接把windows系統的字型檔案拷貝到linux下使用。

(8)$text 要渲染的字串。需要注意必須是utf-8編碼的字串。說到字串不得不提php的string資料型別。雖然名為string,其實php語言本身並不認識各種字元編碼,它只是簡單的把string看做是動態增長的「位元組」陣列,例如strlen()就是返回的位元組數。而我們知道除了ascii編碼的字元和位元組是相同的外,幾乎沒有其他字元編碼中的字元對應乙個位元組,例如乙個漢字的utf-8編碼占用3個位元組。至於怎麼解釋其中的字元編碼,需要專門的庫函式如iconv_strlen()。如果字串使用字面量,那麼其所在的php原始檔就必須編碼為utf-8儲存。

(1)字處理軟體的複雜之處

儘管這個函式可以顯示字串,但是針對於字處理軟體(如word)來說,並不能使用。因為一旦涉及到對其的問題,此函式即不能使用了。因為它不能處理字間距,當然也就無法實現分散對齊等功能。再加上每行的「避首尾」(如,不能位於行首)要求,做好字處理並不簡單。

變通的方式是,首先通過複雜的公式計算出各個字元的準確位置,然後針對每乙個字元呼叫此函式。

(2)如何顯示加粗字型

對於本身就有粗體的字型檔案來說,這不存在任何問題,只要使用粗體檔案就可以了。問題是很多字型檔案並沒有針對粗體單獨設計。gd庫中也沒有乙個能加粗顯示的函式。其解決方法說出來有點可笑,就是針對每個字元繪製兩次,第二次繪製時的$x會第一次的$x多1個畫素即可。

絕對詳解PHP 的imageTtfText 函式

對於php繪圖初學者,首先遇到的乙個問題就是,imagestring 這個函式並不支援漢字的繪製。這往往會給入門者當頭一棒,不過不要著急,因為還有乙個imagettftext 函式,這個函式能繪製utf 8編碼的字串,當然可以繪製漢字了。然而使用它並不十分簡單。先來看看其原型宣告 一共有8個引數,缺...

詳解Sticky Footer 絕對底部的兩種套路

最近面了好幾個前端,工作經驗有高有低,居然都不知道絕對底部是什麼,也沒有人能說出一種實現方式,讓我不禁感慨前端領域的良莠不齊 絕對底部,或者說 sticky footer,是一種古老且經典的頁面效果 當頁面內容超出螢幕,頁尾模組會像正常頁面一樣,被推到內容下方,需要拖動滾動條才能看到 而當頁面內容小...

c string類詳解 學會絕對有用

之所以拋棄char 的字串而選用c 標準程式庫中的string類,是因為他和前者比較起來,不必擔心記憶體是否足夠 字串長度等等,而且作為乙個類出現,他整合的操作函式足以完成我們大多數情況下 甚至是100 的需要。我們可以用 進行賦值操作,進行比較,做串聯 是不是很簡單?我們盡可以把它看成是c 的基本...