登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Lethe

 

 
 
 

日志

 
 

PHP调用GD库将文字转为图片大标题分析  

2011-08-19 09:11:16|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

        问题出现:        

        单位正在组织人员用phpcms2008进行二次开发,建立门户网站。为了方便编辑人员制做头条新闻的大标题,做了一个文字转图片的功能,实现编辑人员在后台录入文字标题,发布首页后则按设定的参数自动生成图片大标题。

        乙方人员很快就做出了该功能,但在使用中一直有问题。主要表现为一些汉字,如“日”字,在使用方正大黑简体时会出现文字间距严重不均匀的现象。乙方采取的补救措施是对我们在工作中发现的会导致异常的汉字,进行逐个特殊处理。但治标不治本,而且这种方法的成本也相当高。责成乙方分析问题根源,一直没有结果。

      

        寻求解决:

         在编辑人员的再三抱怨下,只好越俎代庖。首先了解一下同行,大部分地方报社和广电的门户网站,在这个问题上是手工制做标题图片,然后上传,包括宁波网也是这样,他们用的是北方网的后台。有个别网站用了自动生成的功能,也是PHP调用GD库实现的,他们也有在调用某些字体时有个别汉字偏移的现象,解决的方法是统一采用方正超粗黑。后来发现phpcms v9也提供了相应的功能,但是也有同样的bug,而且也可以通过使用方正超粗黑来规避。在网上找了一些示例代码,比较著名的有一个老外Stewart Rosenberger 和国内一位macleo的,macleo的代码还将汉字逐个输出,但是两位的代码都有上述的bug。

        看来重视这个问题并加以解决的人不多。前阵子在一个年会上碰见钟胜辉,他已经离开了phpcms,现在做了一个新的产品cmstop,我在车上看了他的演示,功能很好。我讲了遇到的问题,用他的系统试一下,居然完全正常。回单位后以又发了一些文字和字体文件给他,他那边测试都正常。问一下他的实现思路,只说也是GD库,具体实现,是其他人在做。所以不好意思再多问。

        于是利用周末在家的时间,将常出问题的汉字,使用方正大黑简体在word和photoshop中进行了详细的测试,又用GD库输出各字的宽度和占位,经过比对分析,发现了部分规律,并解决了文字偏移的问题,效果可以接受,但没有word的处理方案完美。解释如下:

 

GD库输出汉字基本策略分析:

1.每个汉字所占的版心(可用imagettfbbox()函数获得)不是完全相同的。

2.每个汉字所占的画布也不是完全相同的。观测结果为当版心小于某个值时,画布大小固定;当版心超出时,画布会扩充。但是在word中,各汉字所占宽度是相同的。

3.整串输出时,第一个汉字书写的起始点可以在magettftext()函数中指定,即版心的左下角,但第二个汉字的起始点目前不清楚。

4.整串输出时,imagettftext()书写时,汉字之间是否有间距,大小如何确定,是在版心之间计算还是在画布之间计算,目前不明。

5.单字输出时,每个字的左起座标都是-1。底线座标不确定,中点的横座标确定,纵座标不确定。但总体上,字的高度越小,顶线及中点纵座标越低,底线纵座标越高。

 

解决思路:

1.以常见字,如“点”字的版心宽度为基准,设为常量NormalWidth。

2.字符串进数组,为每个字符分配版心宽度。如果不是汉字,直接用imagettfbbox()函数获得。如果是汉字,获得后在返回值与NormalWidth之间取Max。

3.字符逐个输出,并校正各字版心的起始横座标,按居中(或留白左0.6右0.4)策略,纵座标保持不变。横座标递进量为上一个字符的宽度加上预设的间隔。在word中,不是居中,而是各个字不同,但视觉效果最佳。初步推测是GD库imagettfbbox()函数获得的汉字座标被整体平移过,字体中的部分座标信息丢失,导致每个字的左起座标都是-1,而word则取出了字体中各个汉字的横向偏移值,该值是与各个汉字一一对应的。

 

方正超粗黑与其他字体(如方正大黑简体 )的不同:

上面提到,一些系统可以用方正超粗黑来规避上述问题。原理是方正超粗黑输出的文字,一方面各个汉字的版心宽度差别很小,各字宽度相似,另一方面版心宽度绝对值较大,与各字所占画布的宽度差别较小。所以按相同的原始策略输出,使用方正超粗黑,看起来效果不错,但用方正大黑,因为各字的宽度差别明显,加上字宽与画布差别较大,所以效果就会难以接受。

 

附测试返回值: 

$FontName = 'fzdhj.ttf';

$FontSize = 50;

$FontAngle = 0;

 

"中":

font_coordinate[0] = -1

font_coordinate[1] = 7

font_coordinate[2] = 52

font_coordinate[3] = 7

font_coordinate[4] = 52

font_coordinate[5] = -54

font_coordinate[6] = -1

font_coordinate[7] = -54

FontWidth = 53

FontHeight = 61

FontMiddleH = 25.5

FontMiddleV = -23.5

 

"日":

font_coordinate[0] = -1

font_coordinate[1] = 5

font_coordinate[2] = 39

font_coordinate[3] = 5

font_coordinate[4] = 39

font_coordinate[5] = -49

font_coordinate[6] = -1

font_coordinate[7] = -49

FontWidth = 40

FontHeight = 54

FontMiddleH = 19

FontMiddleV = -22

 

"皮":

font_coordinate[0] = -1

font_coordinate[1] = 8

font_coordinate[2] = 60

font_coordinate[3] = 8

font_coordinate[4] = 60

font_coordinate[5] = -55

font_coordinate[6] = -1

font_coordinate[7] = -55

FontWidth = 61

FontHeight = 63

FontMiddleH = 29.5

FontMiddleV = -23.5

 

"满":

font_coordinate[0] = -1

font_coordinate[1] = 7

font_coordinate[2] = 59

font_coordinate[3] = 7

font_coordinate[4] = 59

font_coordinate[5] = -55

font_coordinate[6] = -1

font_coordinate[7] = -55

FontWidth = 60

FontHeight = 62

FontMiddleH = 29

FontMiddleV = -24

 

 // *************************************************************************************************************

//         只交流实现思路,不提供程序代码。而且这个代码也不复杂,最好自己动手试一下。

//**************************************************************************************************************

  评论这张
 
阅读(1834)| 评论(0)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018