编程实现文本文件到图像文件的转化
经常上网的朋友在收发电子邮件时,由于双方的内码不一致或者操作系统有差异,经常会出现乱码。有人就提出了一种解决的途径,即在画笔等图像编辑软件里输入,再存为图片,然后以图像形式发送邮件。但是在图像编辑软件里输入文字总有这样那样的不便之处,而直接把文本文件转换成图像的软件又不多见,下面我们就"自己动手,丰衣足食",用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;
phzk: PByte;
pasc: PByte;
SFile, DFile: string;
procedure HandleRes;
procedure Convert;
procedure WriteLine(str: string; x, y: integer; Can: TCanvas);
为了节省篇幅,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 ");
if hres <> 0 then
begin
hasc := LoadResource(0, hres);
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;
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
if (buf[i] = #9) or (buf[i] = #10) or (buf[i] = #13) then
buf[i] := ' ';
end;
StrLst.Add(buf);
end;
CloseFile(tf);
h := StrLst.Count * 20;
w := 0;
for i := 0 to StrLst.Count - 1 do
begin
w := w * 8;
bmp := TBitMap.Create;
bmp.Monochrome := true;
bmp.Height := h + 60;
bmp.Width := w + 60;
for i := 0 to StrLst.Count - 1 do
begin
WriteLine(StrLst[i], 30, 30 + i * 20, bmp.Canvas);
end;
bmp.SaveToFile(DFile);
Image1.Picture.Bitmap.Assign(bmp);
bmp.Free;
StrLst.Free;
end;
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;
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码文件,有兴趣的读者可进一步修改,到时候别忘了给我一份就行了。
(上海 XD.W)