PHP的imageTtfText()函数深入详解


Posted in PHP onMarch 03, 2021

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

1 详细解释imageTtfText()函数

对于PHP绘图初学者,首先遇到的一个问题就是,imageString()这个函数并不支持汉字的绘制。这往往会给入门者当头一棒,不过不要着急,因为还有一个imageTtfText()函数,这个函数能绘制UTF-8编码的字符串,当然可以绘制汉字了。然而使用它并不十分简单。先来看看其原型声明:

PHP的imageTtfText()函数深入详解

一共有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 被绘制字符串的第一个字符的基线点。单位是像素。这里涉及到字体设计的基本知识--基线。这个点绝对不是左上角,而具体是什么取决于所使用的字体是如何设计的。对于宋体、楷体、黑体等常见的字体中的汉字,这个点大概位于字体的左下部分;而对于英文字母和标点符号,则各不相同。如下图:

PHP的imageTtfText()函数深入详解

PHP的imageTtfText()函数深入详解

PHP的imageTtfText()函数深入详解

PHP的imageTtfText()函数深入详解

PHP的imageTtfText()函数深入详解

(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个像素即可。

到此这篇关于PHP的imageTtfText()函数深入详解的文章就介绍到这了,更多相关PHP的imageTtfText()函数内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

PHP 相关文章推荐
用session做客户验证时的注意事项
Oct 09 PHP
PHP如何编写易读的代码
Jul 10 PHP
10个实用的PHP代码片段
Sep 02 PHP
PHP基础知识回顾
Aug 16 PHP
三个类概括PHP的五种设计模式
Sep 05 PHP
浅析使用Turck-mmcache编译来加速、优化PHP代码
Jun 20 PHP
curl不使用文件存取cookie php使用curl获取cookie示例
Jan 26 PHP
PHP图片库imagemagick安装方法
Sep 23 PHP
详解WordPress中简码格式标签编写的基本方法
Dec 22 PHP
PHP实现导出带样式的Excel
Aug 28 PHP
在Laravel的Model层做数据缓存的实现
Sep 26 PHP
关于Yii2框架跑脚本时内存泄漏问题的分析与解决
Dec 01 PHP
PHP实现爬虫爬取图片代码实例
Mar 03 #PHP
PHP执行系统命令函数实例讲解
Mar 03 #PHP
Git命令之分支详解
Mar 02 #PHP
PHP之header函数详解
Mar 02 #PHP
laravel与thinkphp之间的区别与优缺点
Mar 02 #PHP
php中array_fill函数的实例用法
Mar 02 #PHP
PHP网站常见安全漏洞,及相应防范措施总结
Mar 01 #PHP
You might like
PHP中的加密功能
2006/10/09 PHP
第五节--克隆
2006/11/16 PHP
php下通过curl抓取yahoo boss 搜索结果的实现代码
2011/06/10 PHP
php实例分享之mysql数据备份
2014/05/19 PHP
PHP实现长文章分页实例代码(附源码)
2016/02/03 PHP
Laravel框架下载,安装及路由操作图文详解
2019/12/04 PHP
9个javascript语法高亮插件 推荐
2009/07/18 Javascript
Js 时间间隔计算的函数(间隔天数)
2011/11/15 Javascript
JS对img进行操作(换图片/切图/轮换/停止)
2013/04/17 Javascript
js实现局部页面打印预览原理及示例代码
2014/07/03 Javascript
浅谈javascript的分号的使用
2015/05/12 Javascript
javascript设计简单的秒表计时器
2020/09/05 Javascript
学习Javascript面向对象编程之封装
2016/02/23 Javascript
RequireJs的使用详解
2017/02/19 Javascript
React Native 集成jpush-react-native的示例代码
2017/08/16 Javascript
Vue 开发音乐播放器之歌手页右侧快速入口功能
2018/08/08 Javascript
Kettle中使用JavaScrip调用jar包对文件内容进行MD5加密的操作方法
2020/09/04 Javascript
[02:22]2018DOTA2亚洲邀请赛VG赛前采访
2018/04/03 DOTA
[01:02:18]VGJ.S vs infamous Supermajor 败者组 BO3 第一场 6.4
2018/06/05 DOTA
Python操作CouchDB数据库简单示例
2015/03/10 Python
python通过加号运算符操作列表的方法
2015/07/28 Python
Python利用递归和walk()遍历目录文件的方法示例
2017/07/14 Python
tensorflow 使用flags定义命令行参数的方法
2018/04/23 Python
kali中python版本的切换方法
2019/07/11 Python
Pytorch之卷积层的使用详解
2019/12/31 Python
使用TensorFlow直接获取处理MNIST数据方式
2020/02/10 Python
jupyter notebook中新建cell的方法与快捷键操作
2020/04/22 Python
YBF Beauty官网:美丽挚友,美国知名彩妆品牌
2020/11/22 全球购物
英国银首饰公司:e&e Jewellery
2021/02/11 全球购物
CSS代码检查工具stylelint的使用方法详解
2021/03/27 HTML / CSS
信息科学与技术专业求职信范文
2014/02/20 职场文书
超市客服工作职责
2014/06/11 职场文书
2015新生加入学生会自荐书
2015/03/24 职场文书
2015年学校教科室工作总结
2015/07/20 职场文书
机关干部正风肃纪心得体会
2016/01/15 职场文书
Python函数中的不定长参数相关知识总结
2021/06/24 Python