首页  编辑  

编程实现文本文件到图像文件的转化

Tags: /超级猛料/Report.报表、图表/   Date Created:
编程实现文本文件到图像文件的转化

   经常上网的朋友在收发电子邮件时,由于双方的内码不一致或者操作系统有差异,经常会出现乱码。有人就提出了一种解决的途径,即在画笔等图像编辑软件里输入,再存为图片,然后以图像形式发送邮件。但是在图像编辑软件里输入文字总有这样那样的不便之处,而直接把文本文件转换成图像的软件又不多见,下面我们就"自己动手,丰衣足食",用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 // 计算最长一行字符数
    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;
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码文件,有兴趣的读者可进一步修改,到时候别忘了给我一份就行了。
  (上海 XD.W)