富群兴 网络设计工作室
企业智慧ERP应用软件服务商

详解PHP 的imageTtfText()函数

 二维码 621
发表时间:2017-04-10 23:24作者:smstong来源: 绝对详解PHP 的imageTtfText()函数网址:http://blog.csdn.net/smstong/article/details/43955

图片处理,是许多程序的功能之一;而文字渲染则是绘图的基本组成部分。PHP通过很多扩展库来支持图片的处理,最常用的还是GD库,通过一系列imagexxx()函数来提供绘图功能。本文专注于非常细小的一点:绘制文字。熟悉Win32的人都知道,TextOut()就可以轻松显示任何文字了,然而到了PHP的世界里,有些事情并不轻松。

1 详细解释imageTtfText()函数


对于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*像素数)/磅值。实验得出的结论是:
[plain] view plain copy
在CODE上查看代码片派生到我的代码片
  1. 1磅==>4像素, PPI=288  

  2. 2磅==>5像素, PPI=180  

  3. 3磅==>7像素, PPI=168  

  4. 4磅==>8像素, PPI=144  

  5. 5磅==>9像素, PPI=129.6  

  6. 6磅==>10像素, PPI=120  

  7. 7磅==>11像素, PPI=113.14285714286  

  8. 8磅==>12像素, PPI=108  

  9. 9磅==>14像素, PPI=112  

  10. 10磅==>15像素, PPI=108  

  11. 11磅==>16像素, PPI=104.72727272727  

  12. 12磅==>17像素, PPI=102  

  13. 13磅==>18像素, PPI=99.692307692308  

  14. 14磅==>19像素, PPI=97.714285714286  

  15. 15磅==>21像素, PPI=100.8  

  16. 16磅==>22像素, PPI=99  

  17. 17磅==>23像素, PPI=97.411764705882  

  18. 18磅==>25像素, PPI=100  

  19. 19磅==>26像素, PPI=98.526315789474  

  20. 20磅==>27像素, PPI=97.2  

  21. 21磅==>28像素, PPI=96  

  22. 22磅==>29像素, PPI=94.909090909091  

  23. 23磅==>30像素, PPI=93.913043478261  

  24. 24磅==>32像素, PPI=96  

  25. 25磅==>33像素, PPI=95.04  

  26. 26磅==>34像素, PPI=94.153846153846  

  27. 27磅==>35像素, PPI=93.333333333333  

  28. 28磅==>36像素, PPI=92.571428571429  

  29. 29磅==>38像素, PPI=94.344827586207  

  30. 30磅==>39像素, PPI=93.6  

  31. 31磅==>40像素, PPI=92.903225806452  

  32. 32磅==>41像素, PPI=92.25  

  33. 33磅==>43像素, PPI=93.818181818182  

  34. 34磅==>44像素, PPI=93.176470588235  

  35. 35磅==>46像素, PPI=94.628571428571  

  36. 36磅==>47像素, PPI=94  

  37. 37磅==>48像素, PPI=93.405405405405  

  38. 38磅==>48像素, PPI=90.947368421053  

  39. 39磅==>50像素, PPI=92.307692307692  

  40. 40磅==>51像素, PPI=91.8  

  41. 41磅==>52像素, PPI=91.317073170732  

  42. 42磅==>53像素, PPI=90.857142857143  

  43. 43磅==>55像素, PPI=92.093023255814  

  44. 44磅==>56像素, PPI=91.636363636364  

  45. 45磅==>57像素, PPI=91.2  

  46. 46磅==>58像素, PPI=90.782608695652  

  47. 47磅==>60像素, PPI=91.914893617021  

  48. 48磅==>62像素, PPI=93  

  49. 49磅==>63像素, PPI=92.571428571429  

  50. 50磅==>63像素, PPI=90.72  

  51. 51磅==>64像素, PPI=90.352941176471  

  52. 52磅==>67像素, PPI=92.769230769231  

  53. 53磅==>68像素, PPI=92.377358490566  

  54. 54磅==>69像素, PPI=92  

  55. 55磅==>70像素, PPI=91.636363636364  

  56. 56磅==>71像素, PPI=91.285714285714  

  57. 57磅==>72像素, PPI=90.947368421053  

  58. 58磅==>74像素, PPI=91.862068965517  

  59. 59磅==>75像素, PPI=91.525423728814  

  60. 60磅==>76像素, PPI=91.2  

  61. 61磅==>77像素, PPI=90.885245901639  

  62. 62磅==>78像素, PPI=90.58064516129  

  63. 63磅==>79像素, PPI=90.285714285714  

  64. 64磅==>81像素, PPI=91.125  

  65. 65磅==>83像素, PPI=91.938461538462  

  66. 66磅==>84像素, PPI=91.636363636364  

  67. 67磅==>85像素, PPI=91.34328358209  

  68. 68磅==>86像素, PPI=91.058823529412  

  69. 69磅==>86像素, PPI=89.739130434783  

  70. 70磅==>88像素, PPI=90.514285714286  

  71. 71磅==>90像素, PPI=91.267605633803  

  72. 72磅==>91像素, PPI=91  

  73. 73磅==>92像素, PPI=90.739726027397  

  74. 74磅==>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存储。

2 几个小技巧

(1)字处理软件的复杂之处
尽管这个函数可以显示字符串,但是针对于字处理软件(如Word)来说,并不能使用。因为一旦涉及到对其的问题,此函数即不能使用了。因为它不能处理字间距,当然也就无法实现分散对齐等功能。再加上每行的“避首尾”(如,不能位于行首)要求,做好字处理并不简单。

变通的方式是,首先通过复杂的公式计算出各个字符的准确位置,然后针对每一个字符调用此函数。

(2)如何显示加粗字体
对于本身就有粗体的字体文件来说,这不存在任何问题,只要使用粗体文件就可以了。问题是很多字体文件并没有针对粗体单独设计。GD库中也没有一个能加粗显示的函数。其解决方法说出来有点可笑,就是针对每个字符绘制两次,第二次绘制时的$x会第一次的$x多1个像素即可。


在线留言

在线留言

了解更多软件开发、行业ERP、企业官网应用服务

公司
*
手机
*
描述
*
验证码
 换一张
*
提交留言
联系QQ:2590552134
手机号码:13682478927
联系邮箱:2590552134@qq.com
联系地址:广东省深圳市龙岗区横岗镇新光一街35号
热搜词:ERP软件开发,进销存管理软件免费下载,企业管理软件,企业ERP管理系统
粤公网安备 44030702000841号
我们的使命是助力商家全渠道管理与业务拓展,同时在供应链重塑的背景下,实现商业模式的全新升级
——————
热线电话
136 8247 8927
website qrcode