在 php 中用描点法“绘制”中文_php实例
4326 点击·0 回帖
![]() | ![]() | |||||||||||||
![]() | 目前,越来越多的人喜欢上网了,越来越多的人拥有了自己的个人主页。随着各种自动化软件工具的出现,制作网页越来越简单。但,由于特效随处可得,创新的东西,越来越少。说不定,哪天,你会发现某个网站上的计数器和自己的一模相同。网页越做越老练。网页上的东西,也越来越多,越来越丰富。 设问:
为了实现更多的自动控制,能使用CGI(Common Gateway interface)程式来实现这些功能。 软件需求: PHP:GD Library 设置支持PHP的服务器。我用OmniHTTPd Professional 对于计数器和实时数据统计、发布,我们能用图片来完成。在图片中输出文字。 在PHP中,要创建一个图片,并在上面显示点内容,基本步骤如下: 上面示例,在400×300的图片上,自点(10,10)开始,绘制12磅的"1234567890"。你有没有注意到这张图片的大小是:251字节!你也能试试其他的输出格式。 图片的大小,和图片中非背景象素点数有关,跟输出多少象素无关。 然而,有一个问题。 你能用imagestring()输出如下的信息: imagestring($im,1,0,0,"abcdefghijklmnopqrstuvwxyz0123456789~!@#$%^;*()_+{}|:"<>?[];,./",$red); 可是,你无法正确输出中文!!! imagestring($im,1,0,0,"啊",$red); 你看到的,决不是中文!!而是乱码。 PHP默认的字符集是UTF-8,而简体中文是GB2312。 怎么解决?! 为了解决这个问题,你能让PHP加载扩展模块php_iconv.dll(UNIT下的后缀名是.SO),不过,有时候,可能不能正常工作。本来,我要把一段测试代码放上来,可这次,怎么弄都没有成功。为了避免错误,我还是不把他们放上来了。 但,最致命的,如果你的空间服务商关闭了该扩展模块,或,甚至禁止了加载模块的DL()函数,那,你就只能跟中文BYE-BYE了。 还好,更有其他办法。 能通过字符映射,将预先转换好的码表中字符输出来。但,你需要一张码表! 或,手工绘制每一个中文的每一个点!感觉怎么样?! 好,来吧,我们一起来画字! 画字,首先要知道怎么画。 初中的简单函数,学过吧?要画出函数的图像,做过吧?算出某点的坐标,然后连接两相邻点。这种方法,叫描点法。 我们要做的,是尽量多地将点算出来,然后在相应坐标显示出来。 你是否听说过点阵打印机、点阵汉字? 在输出汉字时,他们是用一个个点来表示的。 在某个坐标上显示一个某种颜色的点的函数是: int imagesetpixel ( resource image, int x, int y, int color) 假定我要在坐标(100,100)处显示一个白色的点,那么,只需如下代码: 也就是说,我们只要获取某个汉字的所有点的信息,我们就能够通过这个函数,输出那个汉字。 在文件chs16.fon里,保存的,是国标区位码表(国家标准信息交换用汉字编码基本字符集GB-2312)。他是汉字的点阵字库。(WIN98系统中,此文件在c:windowscommand下。如果你要把他放在UNIX系统下使用,请注意大小写。如果没有,你能在文末找到链接。) 他是MSDOS时代的,但,好东西,还是应该拿出来一用的。 从chs16.fon里,我们能读取汉字的点阵数据。每个汉字,都是由16×16个点构成的。笔划走过的地方,点的值为1,否则为0;每个点占用一个位,每8个点构成一个字节。那么,一个汉字,就需要(16×16÷8=32)字节。 下面这个实例,是为了说明字符点阵的表示方法。 这里,定义了一个8×8的矩阵,显示了一个字母C,白色的方块用0表示,黑色方块用1表示,那么,这八行图像的代码分别是:
要输出这些点的话,就需要先画第一行,然后第二行、第三行……到最后一行。 用一个循环: for($hang=0;$hang<8;$hang++) 在每一行中,有八个格子,需要分别绘制,从第一个,然后第二个、第三个……到最后一个。 用一个循环: for($gezi=0;$gezi<8;$gezi++) 两个循环联列: for($hang=0;$hang<8;$hang++) for($gezi=0;$gezi<8;$gezi++) { //在这里,我们就能输出点了。 imagesetpixel ( $image, $gezi, $hang, $color); } 但,我们怎么知道到哪里去读某个汉字的点阵数据呢? 一般的字符,比如ASCII码,是用数字0--127(即二进制00000000到01111111)来表示,而中文,则是用两个高位为1的字节(100000000 100000000)表示。如: 半角字符"A",机内码为 (01000001)(他实际上是ASCII码值)。 下面,让我们打开"字符映射表"看看吧。如果你为了节省磁盘,没有安装,那就装一下,不大。如果不会安装,那你就接下去看我乱侃吧。 在字符映射表里,字体选择"楷体_GB2312",点击"特别符号",这时,你能看到国标区位码表,从字符(10110000 10100001)开始,一直到(10011111 11111111)。 全角字符"A",机内码为:(10100011 11000001)(他实际是两个高位为1的ASCII码)。 中文"啊"的机内码,是(10110000 10100001); 在GB-2312字符集中,"啊"在表中位置是第16区第1位,这个坐标(16,1),用二进制表示,就是(00010000,00000001)。这,就是"啊"的区位码。 请看: 中文字符: 啊 机内码: (10110000 10100001) 区位码: (00010000,00000001) 相差: (10100000,10100000) 所以, 区位码和机内码的换算公式为 【区位码】+(10100000 10100000)=【机内码】。即: 区位码0 + (10100000) = 机内码0; 区位码1 + (10100000) = 机内码1; 这样的话,点阵数据,就能通过汉字"机内码"-> "区位码"进行索引、查找。 前面已讲了一个汉字,在表中要占用32字节,所以,我们定义了一个含有32个元素的数组: $buffer=array(0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0); 用来保存从字库读出的32个字节数据。 接下来的问题,某一个字符,到底保存在文件的什么位置呢? 由于一个汉字用了32个字节,而GB-2312区位码表表有94行、94列,那么,只要知道该字符在表中是第几个,再乘以32就行了。 所以定义偏移量: $offset=(94*($qh-1)+($wh-1))*32; $qh表示区(qu)、$wh表示位(wei);减1,是因为PHP从0开始计数。 位置找到,就只需要用fseek()函数定到码表的这个位置,然后读32字节到$buffer就行了。 另外,由于中文是由两个字节组成,而前面给出的点阵示例是8位,一个字节,所以,画点的代码要修改一下: for($hang=0;$hang<16;$hang++) for($j=0;$j<2;$j++) //因为是两个字节,所以插入一个循环 for($gezi=0;$gezi<8;$gezi++) { imagesetpixel ( $image, $gezi +8*$j, $hang , $color); } 好,我们开始编程吧! 下面,我给出一个测试实例: 对于这个函数,我们还能进行扩充,以实现不同的效果。 ![]() ![]() 一个实时用户留言板留言数量统计表实例: http://medlem.spray.se/letmegetone/messageboard/userinfo.htm 作者联系方式: Homepage: http://medlem.spray.se/letmegetone E-mail: singlestudio@hotmail.com | |||||||||||||
![]() | ![]() |