|
字符画软件的四个关键技术
第一个关键技术:汉字库读取技术
使用汉字库技术可以做到和操作系统无关性,我们先了解一下点阵字库的基本原理 如下所示,下面是一个“字”的点阵图,在16点阵字库中一个汉字为16x16点,每一行使用两个字节表示,如下面示例第一行的十六进制为:0x02和0x00,所以,一个汉字在16点阵字库中需要占用2x16个字节,24点阵字库需要3x24个字节,下面我们仅以16点阵字库为例,其他点阵类似。
██████ █████████ ███████ ████████ ██ ██ ██ ██████████ ██ █ ██████████ ███ ███ █████ █████████ ██████ ████████ ███████ ███████ █████ ██ █ ███████ ████████ ███████ ████████ ███████ ████████ ███████ ████████ █████ █ ████████ ██████ █████████
下面的函数返回指定字符串的字符画文本 function Get16(const AWord,AForeground,ABackground:string):string; function GetBit(const c,n:byte):integer; begin result:=(c shr n) and 1; end; var iLen :integer; iFileSize :integer; s :string; k,l,i,p :integer; cw:array[0..31] of char; qu_ma,wei_ma:integer; File16 :file; begin iLen:=length(AWord); AssignFile(File16,piProgramInfo.Path+''''HZK16''''); FileMode := fmOpenRead; try Reset(File16,1); finally FileMode:=fmOpenReadWrite; end; iFileSize:=FileSize(File16); try for l:=1 to iLen div 2 do begin k:=l*2-1; // 如果不是汉字,往前进一位 while k<=iLen do begin if ByteType(AWord,k)=mbLeadByte then break; inc(k); end; if k>iLen then break; if ((ord(AWord[k]) and $80)<>0) then begin qu_ma:=ord(AWord[k])-161; wei_ma:=ord(AWord[k+1])-161; if (94*qu_ma+wei_ma)*32+32>iFileSize then continue; try seek(File16,(94*qu_ma+wei_ma)*32); except myMessageBox(''''fseek call fail!''''); exit; end; BlockRead(File16,cw,32);
for i:=0 to 15 do begin for p:=7 downto 0 do begin if GetBit(ord(cw[i*2]),p)=1 then s:=s+AForeground else s:=s+ABackground; end; for p:=7 downto 0 do begin if GetBit(ord(cw[i*2+1]),p)=1 then s:=s+AForeground else s:=s+ABackground; end; s:=s+#13#10; end; end; end; finally CloseFile(File16); end;
result:=s; end;
第二个关键技术:使用系统字库进行转换 其实使用系统字库是极为自由的方式,因为这样我们完全不必关心字库的技术,这一切都交给系统好了,让我们充分利用系统资源。 如果我们定义一个设备,然后设定好设备的各种属性,包括宽度、高度、字体、颜色等,然后在上面绘制文本就可以了,要转换为字符画,只需要把设备上的点阵信息转换为文本即可。 配合 CreateFontIndirect 函数,使用 DrawText 可以绘制丰富的文本效果。实现完整的字符画效果
下面是十二号宋体的转换结果 █████ ██████ █ █ ████████ █ ██ ███ ██████ █████ █████ ██████ █ █████ ██████ █████ ██████ █████ ██████ ███ ██████ ████████████
下面是九号@黑体的转换结果 ████████████ ██ ███ ████ ██ ████ ████ ██ █ ██ ████ ██ █ █ ████ █ █ █ █ ██ ██ █ ██ █ ██ ██ █ ██ █ ██ ████ ██ ████ ████ ██ ███ ████ ████████████
第三个关键技术:图片转换为文本 要把图像转换为文本,这其中有一个很大的困难,就是文本没有颜色,所以我们特别引进了一个概念:文本灰度,就是把不同字母在屏幕上显示的大小排序,得到一张灰度表,用这个灰度表来转换图片,可以达到比较好的效果。 下面的函数可以把一个位图转换成文本,ABit 是位图,AGray 是灰度 function ImageToText(ABit:TBitmap;const AGray:string):string; var x,y :integer; s :string; pColor :Longint; R,G,B :byte; iGray :integer;
sGrayPer :string; iGrayLen :integer; iIndex :integer; begin s:=''''''''; sGrayPer:=AGray; iGrayLen:=Length(sGrayPer); for y:=0 to ABit.Height-1 do begin for x:=0 to ABit.Width-1 do begin pColor:=ABit.Canvas.Pixels[x,y]; R:=pColor and $FF; G:=(pColor shr 8) and $FF; B:=(pColor shr 16) and $FF;
iGray:=HiByte(R*77+G*151+B*28); iIndex:=(iGray*iGrayLen div 255); if iIndex<1 then iIndex:=1; if iIndex>iGrayLen then iIndex:=iGrayLen; s:=s+sGrayPer[iIndex]; end; s:=s+Crlf; end; result:=s; end; 这是一个常用且效果比较好的灰度:“MNHQ$OC?7>!":-' [1] [2] 下一页 |