在 PHP 中用描点法“绘制”中文-经典文章-PHP教程-幽默笑话

在 PHP 中用描点法“绘制”中文-经典文章-PHP教程-幽默笑话

行二进制表示十六进制表示0000000000x001001111100x3E2011100000xE03011100000xE04011100000xE05011100000xE06001111100x3E7000000000x00要输出这些点的话,就需要先画第一行,然后第二行、第三行……到最后一行。

用一个循环:for($hang=0;$hang$hang++)在每一行中,有八个格子,需要分别绘制,从第一个,然后第二个、第三个……到最后一个。 用一个循环:for($gezi=0;$gezi$gezi++)两个循环联列:for($hang=0;$hang$hang++)for($gezi=0;$gezi$gezi++){//在这里,我们就能输出点了。 imagesetpixel($image,$gezi,$hang,$color);}但,我们如何知道到哪里去读某个汉字的点阵数据呢?一般的字符,比如ASCII码,是用数字0--127(即二进制00000000到01111111)来表示,而中文,则是用两个高位为1的字节(100000000100000000)表示。 如:半角字符"A",机内码为(01000001)(它实际上是ASCII码值)。

下面,让我们打开"字符映射表"看看吧。 如果你为了节省磁盘,没有安装,那就装一下,不大。 如果不会安装,那你就接下去看我乱侃吧。

在字符映射表里,字体选择"楷体_GB2312",点击"特殊符号",这时,你可以看到国标区位码表,从字符(1011000010100001)开始,一直到(1001111111111111)。 全角字符"A",机内码为:(1010001111000001)(它实际是两个高位为1的ASCII码)。 中文"啊"的机内码,是(1011000010100001);在GB-2312字符集中,"啊"在表中位置是第16区第1位,这个坐标(16,1),用二进制表示,就是(00010000,00000001)。 这,就是"啊"的区位码。 请看:中文字符:啊机内码:(1011000010100001)区位码:(00010000,00000001)相差:(10100000,10100000)所以,区位码与机内码的换算公式为【区位码】+(1010000010100000)=【机内码】。 即:区位码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$hang++)for($j=0;$j$j++)//因为是两个字节,所以插入一个循环for($gezi=0;$gezi$gezi++){imagesetpixel($image,$gezi+8*$j,$hang,$color);}好,我们开始编程吧!/**************************************文件名:**中文显示点阵输出**只提供简单的操作:输出默认大小的纯中文字符串到图片的坐标(0,0)上**更多功能,请见下一版本。

*****************************************/functiondraw($image,$string,$color){$fp=fopen("","rb");//二进制方式读点阵字库(!feof($fp))//如果文件指针到了文件末尾,退出,不要忘记关闭文件{while($string)//当字符串不为0{$qh=ord(substr($string,0,1))-0xa0;$wh=ord(substr($string,1,2))-0xa0;/*这两行代码,其实是获取一个中文的机内码。 substr($string,0,1);是从$string中获取第一个字节,然后,通过ord();将这个字符转换为整数。 (由于PHP不支持无符号整数,所以没有这一步转换的话,你就只能得到一个0。

)在转换为整数之后,就能进行计算了。 机内码减去0xa0(10100000),就得到了区位码。 substr($string,1,2);是获取$string中的第二个字节。 */$offset=(94*($qh-1)+($wh-1))*32;/*得到了汉字的区位值后,就开始计算偏移量了。 */fseek($fp,$offset,SEEK_SET);/*在字库文件$fp中,将文件指针定位到偏移量。

*/$buffer=preg_split(//,fread($fp,32),-1,PREG_SPLIT_NO_EMPTY);/*fread($fp,32);是从$fp中读取32个字节数据,然后通过preg_split();分配到数组$buffer中。

preg_split();是一个支持正则表达的函数。

关于正则表达式,我正在学习中。 为什么这样用,我也不知道。 PHP手册里有本实例。

*/for($i=0;$i$i++)//点阵的行数:16列数也应该是16for($j=0;$j$j++)//因为是两个字节,那么,就要一个一个地画了for($k=0;$k$k++)//每个字节,都有8个点的数据if(((ord($buffer[$i*2+$j])(7-$k))0x01))//如果这个点的值为1,输出;否则,没有{imagesetpixel($image,$x+8*$j+$k,$i,$color);}$string=substr($string,2);//中文由两个字节表示,所以,输出一个汉字后,就要去掉两个字节。 $x=24;//一个汉字输出结束,空开一点,给下一个汉字。 因为这个汉字是16×16点,那么,$x的值设为16,就够了。

但,太挤了不是?}}fclose($fp);}下面,我给出一个测试实例:phpheader("Content-type:image/gif");include;$im=imagecreate(400,300);$black=imagecolorallocate($im,0,0,0);$string="中文";drawer($im,$string);imagepng($im);imagedestroy($im);对于这个函数,我们还可以进行扩充,以实现不同的效果。