这是个例子:实现文本文件到图像文件的转化 作者: 评价: 上站日期: 2001-08-15 内容说明: 来源: -------------------------------------------------------------------------------- 经常上网的朋友在收发电子邮件时,由于双方的内码不一致或者操作系统有差异,经常会出现乱码。有人就提出了一种解决的途径,即在画笔等图像编辑软件里输入,再存为图片,然后以图像形式发送邮件。但是在图像编辑软件里输入文字总有这样那样的不便之处,而直接把文本文件转换成图像的软件又不多见,下面我们就“自己动手,丰衣足食”,用Delphi编程来实现它。 为了保证跨中英文平台使用,我们必须在程序中自带字库,这里我选择UCDOS中的中文点阵字库hzk16和ASC字符字库asc16,首先我们要把它们编译成资源。用任何一个文本编辑器编辑hzk.rc如下: 201 HZK16 DISCARDABLE “Hzk16" 202 ASC16 DISCARDABLE “Asc16" 然后把UCDOS中的两个字库hzk16和asc16拷入当前目录中,在DOS环境下运行brcc32 hzk.rc,其中brcc32.exe位于Delphi安装目录中的bin目录下,如果正常的话,应该在当前目录中生成一个资源文件hzk.res。 下面我们在Delphi中建立一个工程,命名为txt2bmp,命名主Form为MainForm,在TMainForm声明之前加入以下内容: type ByteArray = Array [0..0] of byte; PByte = ^ByteArray; 在TMainForm的Private段中加入以下内容: hhzk : HGlOBAL; //汉字点阵资源句柄 hasc : HGLOBAL; //ASC字符点阵资源句柄 phzk : PByte; //汉字点阵资源指针 pasc : PByte; //ASC字符点阵资源指针 SFile, DFile : string; //转换的源文件和目的文件名 procedure HandleRes; //处理引入的资源 procedure Convert; //Txt2Bmp转换函数 procedure WriteLine(str: string; x,y: integer; Can: TCanvas) //在图像的Canvas中写入一行汉字 为了节省篇幅,SFile和DFile的设置请读者自行完成,我是用一个OpenDialog和一个SaveDialog来实现的,设置好SFile和DFile以后,直接调用Convert即可。下面我们来完成上面三个主要的函数: 首先来定位程序中的点阵资源,即完成HandleRes函数,程序段如下: procedure TMainForm.HandleRes; var hres : HRSRC; begin hres := FindResource(0,PChar(201),“HZK16”); //查找汉字点阵资源 if hres < > 0 then begin hhzk := LoadResource(0,hres); //载入汉字点阵资源 if hhzk < > 0 then begin phzk := LockResource(hhzk); //锁定,得到资源指针 end; end; hres := Find Resource(0,PChar(202),“ASC16”); //查找ASC字符资源 if hres < > 0 then begin hasc := LoadResource(0,hres); //载入ASC字符资源 if hasc < > 0 then begin pasc := LockResource(hasc); //锁定,得到资源指针 end; end; if (phzk = nil) or (pasc = nil) then begin MessageDlg(“Can not load resource!”#10#13“Program stopped!”, mtWarning,[mbOk],0); Application.Terminate; end; end; 为了保证资源正确释放,在FormCreate事件中加入如下代码: hhzk := 0; hasc := 0; phzk := nil; pasc := nil; SFile := “”; DFile := “”; HandleRes; 在FormDestroy事件中加入以下代码: if hhzk < > 0 then FreeResource(hhzk); if hasc < > 0 then FreeResource(hasc); 接着我们来编写Convert函数,源代码如下: procedure TMainForm.Convert; var tf : TextFile; StrLst : TStringList; buf : string; w,h,i : integer; bmp : TBitMap; begin StrLst := TStringList.Create; //用来存为文件内容 AssignFile(tf,SFile); Reset(tf); //打开源文件 while not Eof(tf) do begin ReadLn(tf,buf); //循环读入文件内容 for i := 1 to Length(buf) do begin //把TAB键、回车、换行转为空格 if (buf[i] = #9) or (buf[i] = #10) or (buf[i] = #13) then buf[i] := '' ''; end; StrLst.Add(buf); end; CloseFile(tf); //以下代码计算bmp文件尺寸,由于是16点阵字库, //每个字符高度为16,宽度为8,每行间距取为4 h := StrLst.Count*20; //bmp文件高度 w := 0; for i := 0 to StrLst.Count-1 do begin//计算最长一行字符数 if w end; w := w*8;//bmp文件宽度 bmp := TBitMap.Create; //创建bmp对象 bmp.Monochrome := true; //选择创建黑白图像,缩小尺寸 //设定尺寸,预留页边距 bmp.Height := h + 60; bmp.Width := w + 60; for i := 0 to StrLst.Count-1 do begin//调用WriteLine写入一行 WriteLine(StrLst[i],30,30+i*20,bmp.Canvas); end; bmp.SaveToFile(DFile); //bmp文件存盘 Image1.Picture.Bitmap.Assign(bmp);//此句需在Form上放置Image1,查看结果 bmp.Free; StrLst.Free; end; 下面是最后一个函数WriteLine,其中有关点阵定位的计算,请参见以前DOS下显示汉字的有关文章。 procedure TMainForm.WriteLine(str: string; x, y: integer; Can: TCanvas); var i,m,n,k : integer;//循环变量 leng : integer;//字符串长度 off : integer;//点阵偏移 begin i := 1; leng := Length(str); //计算字符串长度 while(i< =leng) do begin //判断是否是汉字,汉字占两行 if (i and boolean(byte(str[i+1]) and $80) then begin //计算汉字点阵偏移量 off := ((byte(str[i])-$a1) and $7f) * 94 + ((byte(str[i+1])-$a1) and $7f); off := off * 32; //在画布上描绘一个汉字 for m := 0 to 15 do begin for n := 0 to 1 do begin for k := 7 downto 0 do begin if boolean(phzk[off+m*2+n] and (1 shl k)) then begin Can.Pixels[x+n*8+7-k,y+m] := 1; end; end; end; end; inc(x,16); inc(i,2); end else begin //不是汉字 off := byte(str[i])*16;//计算ASC字符点阵偏移 //在画布上描绘一个ASC字符 for m := 0 to 15 do begin for k := 7 downto 0 do begin if boolean(pasc[off+m] and (1 shl k)) then begin Can.Pixels[x+7-k,y+m] := 1; end; end; end; inc(x,8); inc(i); end; end; end; 至此,本程序的主体部分已经基本完成,具体细节可参见源代码(http://home.etang.com/xd_w/software/txt2bmp.zip),程序运行界面如图所示。本程序在Delphi4.0,PWIN98,Celeron366上调试通过。本程序生成bmp文件后,转换成gif文件,将进一步减小尺寸。另外本程序稍加改进即可用于在英文平台上显示中文文本,进一步加入BIG5和GB码的转换码表,还可以作到直接转换BIG5码文件,有兴趣的读者可进一步修改,到时候别忘了给我一份就行了。
作者: 评价: 上站日期: 2001-08-15
内容说明:
来源: -------------------------------------------------------------------------------- 经常上网的朋友在收发电子邮件时,由于双方的内码不一致或者操作系统有差异,经常会出现乱码。有人就提出了一种解决的途径,即在画笔等图像编辑软件里输入,再存为图片,然后以图像形式发送邮件。但是在图像编辑软件里输入文字总有这样那样的不便之处,而直接把文本文件转换成图像的软件又不多见,下面我们就“自己动手,丰衣足食”,用Delphi编程来实现它。
为了保证跨中英文平台使用,我们必须在程序中自带字库,这里我选择UCDOS中的中文点阵字库hzk16和ASC字符字库asc16,首先我们要把它们编译成资源。用任何一个文本编辑器编辑hzk.rc如下: 201 HZK16 DISCARDABLE “Hzk16" 202 ASC16 DISCARDABLE “Asc16" 然后把UCDOS中的两个字库hzk16和asc16拷入当前目录中,在DOS环境下运行brcc32 hzk.rc,其中brcc32.exe位于Delphi安装目录中的bin目录下,如果正常的话,应该在当前目录中生成一个资源文件hzk.res。 下面我们在Delphi中建立一个工程,命名为txt2bmp,命名主Form为MainForm,在TMainForm声明之前加入以下内容: type ByteArray = Array [0..0] of byte; PByte = ^ByteArray; 在TMainForm的Private段中加入以下内容: hhzk : HGlOBAL; //汉字点阵资源句柄 hasc : HGLOBAL; //ASC字符点阵资源句柄 phzk : PByte; //汉字点阵资源指针 pasc : PByte; //ASC字符点阵资源指针 SFile, DFile : string; //转换的源文件和目的文件名 procedure HandleRes; //处理引入的资源 procedure Convert; //Txt2Bmp转换函数 procedure WriteLine(str: string; x,y: integer; Can: TCanvas) //在图像的Canvas中写入一行汉字 为了节省篇幅,SFile和DFile的设置请读者自行完成,我是用一个OpenDialog和一个SaveDialog来实现的,设置好SFile和DFile以后,直接调用Convert即可。下面我们来完成上面三个主要的函数: 首先来定位程序中的点阵资源,即完成HandleRes函数,程序段如下: procedure TMainForm.HandleRes; var hres : HRSRC; begin hres := FindResource(0,PChar(201),“HZK16”); //查找汉字点阵资源 if hres < > 0 then begin hhzk := LoadResource(0,hres); //载入汉字点阵资源 if hhzk < > 0 then begin phzk := LockResource(hhzk); //锁定,得到资源指针 end; end; hres := Find Resource(0,PChar(202),“ASC16”); //查找ASC字符资源 if hres < > 0 then begin hasc := LoadResource(0,hres); //载入ASC字符资源 if hasc < > 0 then begin pasc := LockResource(hasc); //锁定,得到资源指针 end; end; if (phzk = nil) or (pasc = nil) then begin MessageDlg(“Can not load resource!”#10#13“Program stopped!”, mtWarning,[mbOk],0); Application.Terminate; end; end; 为了保证资源正确释放,在FormCreate事件中加入如下代码: hhzk := 0; hasc := 0; phzk := nil; pasc := nil; SFile := “”; DFile := “”; HandleRes; 在FormDestroy事件中加入以下代码: if hhzk < > 0 then FreeResource(hhzk); if hasc < > 0 then FreeResource(hasc); 接着我们来编写Convert函数,源代码如下: procedure TMainForm.Convert; var tf : TextFile; StrLst : TStringList; buf : string; w,h,i : integer; bmp : TBitMap; begin StrLst := TStringList.Create; //用来存为文件内容 AssignFile(tf,SFile); Reset(tf); //打开源文件 while not Eof(tf) do begin ReadLn(tf,buf); //循环读入文件内容 for i := 1 to Length(buf) do begin //把TAB键、回车、换行转为空格 if (buf[i] = #9) or (buf[i] = #10) or (buf[i] = #13) then buf[i] := '' ''; end; StrLst.Add(buf); end; CloseFile(tf); //以下代码计算bmp文件尺寸,由于是16点阵字库, //每个字符高度为16,宽度为8,每行间距取为4 h := StrLst.Count*20; //bmp文件高度 w := 0; for i := 0 to StrLst.Count-1 do begin//计算最长一行字符数 if w end; w := w*8;//bmp文件宽度 bmp := TBitMap.Create; //创建bmp对象 bmp.Monochrome := true; //选择创建黑白图像,缩小尺寸 //设定尺寸,预留页边距 bmp.Height := h + 60; bmp.Width := w + 60; for i := 0 to StrLst.Count-1 do begin//调用WriteLine写入一行 WriteLine(StrLst[i],30,30+i*20,bmp.Canvas); end; bmp.SaveToFile(DFile); //bmp文件存盘 Image1.Picture.Bitmap.Assign(bmp);//此句需在Form上放置Image1,查看结果 bmp.Free; StrLst.Free; end; 下面是最后一个函数WriteLine,其中有关点阵定位的计算,请参见以前DOS下显示汉字的有关文章。 procedure TMainForm.WriteLine(str: string; x, y: integer; Can: TCanvas); var i,m,n,k : integer;//循环变量 leng : integer;//字符串长度 off : integer;//点阵偏移 begin i := 1; leng := Length(str); //计算字符串长度 while(i< =leng) do begin //判断是否是汉字,汉字占两行 if (i and boolean(byte(str[i+1]) and $80) then begin //计算汉字点阵偏移量 off := ((byte(str[i])-$a1) and $7f) * 94 + ((byte(str[i+1])-$a1) and $7f); off := off * 32; //在画布上描绘一个汉字 for m := 0 to 15 do begin for n := 0 to 1 do begin for k := 7 downto 0 do begin if boolean(phzk[off+m*2+n] and (1 shl k)) then begin Can.Pixels[x+n*8+7-k,y+m] := 1; end; end; end; end; inc(x,16); inc(i,2); end else begin //不是汉字 off := byte(str[i])*16;//计算ASC字符点阵偏移 //在画布上描绘一个ASC字符 for m := 0 to 15 do begin for k := 7 downto 0 do begin if boolean(pasc[off+m] and (1 shl k)) then begin Can.Pixels[x+7-k,y+m] := 1; end; end; end; inc(x,8); inc(i); end; end; end; 至此,本程序的主体部分已经基本完成,具体细节可参见源代码(http://home.etang.com/xd_w/software/txt2bmp.zip),程序运行界面如图所示。本程序在Delphi4.0,PWIN98,Celeron366上调试通过。本程序生成bmp文件后,转换成gif文件,将进一步减小尺寸。另外本程序稍加改进即可用于在英文平台上显示中文文本,进一步加入BIG5和GB码的转换码表,还可以作到直接转换BIG5码文件,有兴趣的读者可进一步修改,到时候别忘了给我一份就行了。
hres := Find Resource(0, PChar(202), 'ASC16'); 应该是
hres := Find Resource(0, PChar('202'), 'ASC16'); 〈----类型转换在此多余了。
或者是
hres := Find Resource(0, '202', 'ASC16'); 〈----字符串常量会自动转换指向#0结尾的字串的。