字符画软件的四个关键技术

原创 2004年03月24日 10:02:00

字符画软件的四个关键技术

第一个关键技术:汉字库读取技术

  使用汉字库技术可以做到和操作系统无关性,我们先了解一下点阵字库的基本原理
如下所示,下面是一个“字”的点阵图,在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>!":-';. ”


第四个关键技术:把文本转换为图像
  要把文本转换为图片,必须获取两个重要参数:转换后的宽和高,要取得这两个参数,我们可以使用 GetTextExtentPoint32 函数,该函数的定义如下:
function GetTextExtentPoint32(DC: HDC; Str: PChar; Count: Integer; var Size: TSize): BOOL;
DC 传入设备句柄
Str 为文本内容
Count 为文本的长度(字节)
Size 返回宽和高
在实际应用中,往往被转换的文本有多行,且每一行的长度不定,
所以我们还需要在生成图像前进行一遍预扫,以便获得完整的图像大小

下面演示了文本转换为图像的代码

////////////////////////////////////////////////////////////////////////////////
// 功能     : 把文本转换为位图
// AOwner   : 窗体参数
// AText    : 要转换的文本
// AFont    : 文本的字体
// ABitmap  : 转换后的位图对象
// 日期     : 2003.12.15
////////////////////////////////////////////////////////////////////////////////
procedure TextToBitmap(AOwner:TObject;const AText:TStrings;AFont:TFont;ABitmap:TBitmap);
var
    i               :integer;
    iWidth,iHeight  :integer;
    iCharHeight     :integer;
    s               :string;
    r               :TRect;
    size            :TSize;
    lblTemp         :TLabel;
begin
    iWidth:=0;
    iHeight:=0;

    lblTemp:=TLabel.Create(nil);
    r.Top:=0;
    try
        lblTemp.Visible:=false;
        lblTemp.Parent:=TWinControl(AOwner);
        lblTemp.Font.Assign(AFont);

        ABitmap.Canvas.Brush.Style:=bsClear;
        ABitmap.Canvas.Pen.Color:=rgb(0,0,0);
        ABitmap.Canvas.Brush.Color:=RGB(255,255,255);
        ABitmap.Canvas.Font.Assign(AFont);

        // 下面代码用户获得文本的最大宽度和高度
        for i:=0 to AText.Count-1 do
        begin
            s:=AText.Strings[i];
            if s='' then s:=' ';
            lblTemp.Caption:=s;

            GetTextExtentPoint32(lblTemp.Canvas.Handle,pchar(lblTemp.Caption),lblTemp.GetTextLen,size);
            if iWidth<size.cx then iWidth:=Size.cx;
            iHeight:=iHeight+Size.cy;
        end;

        // 获得一个字符的高度
        GetTextExtentPoint32(lblTemp.Canvas.Handle,pchar('   '),length('   '),size);
        iCharHeight:=size.cy;

        ABitmap.Width:=iWidth;
        ABitmap.Height:=iHeight;
        for i:=0 to AText.Count-1 do
        begin
            s:=AText.Strings[i];

            r.Left:=0;
            r.Right:=ABitmap.Width;
            r.Bottom:=r.Bottom+iCharHeight;

            DrawText(ABitmap.Canvas.Handle,PChar(s),length(s),r,0);
            r.Top:=r.Top+iCharHeight;
        end;
    finally
        lblTemp.Free;
    end;
end;

2003.12.15
凌丽软件工作室
http://china.wosens.net

第一个项目:字符画神器——全程制作历程

第一个项目:字符画神器——全程制作历程本文适用于:java入门程序员 **读本文你可以学到: 1、一个初级程序员是如何设计初级程序的。 2、字符画的设计原理。 ...
  • qq_36325305
  • qq_36325305
  • 2017年02月09日 21:07
  • 532

让技术人员看得懂的流程(3)——领域模型

让技术人员看得懂的流程(3)                             ——领域模型 按照一般的项目管理过程,“需求”之后是“分析”,那么在分析阶段对应的技术流程又是哪个?如何将需求...
  • z69183787
  • z69183787
  • 2014年06月04日 20:44
  • 1029

用32位int型变量表示单引号括起来的四个字符

在C、C++中可以用32位int型变量表示单引号括起来的四个字符,例如下面代码中的示例: // 字符c的16进制值是0x63,字符o的16进制值是0x6f, // 字符n的16进制值是0x6...
  • ameyume
  • ameyume
  • 2013年01月02日 22:52
  • 1764

彩色字符画转换软件

一款很有意思的小软件,可以将图片转化为彩色字符画,介绍在这里:http://www.appinn.com/image2html/ 别的不多说,看看我家曈曈的照片,能看出全是字符拼成的么?(当然,这个...
  • x86
  • x86
  • 2009年04月30日 17:08
  • 1133

字符画

●●█〓█████████▅▄▄▄▄▄▄▄▃▃▃▃▄ ●● █ █ ███▄ ▄▅███ ████████████████████▅▄▃ █...
  • CLeopard
  • CLeopard
  • 2014年08月21日 17:08
  • 6390

字符画——ASCII art

首先先推荐几个生成字符画的网址 http://www.topster.de/zh/text-to-ascii/ https://linux.cn/article-3405-1.html     ...
  • fairyloycine
  • fairyloycine
  • 2017年04月13日 18:18
  • 1290

Linux 字符画趣味用法

做码农是很苦逼,但要有苦中作乐的精神。推荐个好玩的字符画玩法。首先看下效果:每次连接上一个session,都会跳出这种有趣的字符画界面。字符画可以网上下载,不过linux本身也自带了一些字符画工具。我...
  • scjthree
  • scjthree
  • 2014年05月23日 11:09
  • 2880

【003】Python实现图片转字符画(pillow 库的使用)

在常见的RGB(A)模式图片中,利用每个像素点的R,G,B值按照公式转换成灰度值(0~255),然后在自己创建的字符表中找到灰度值对应的字符,添加到一个文本文件中,就实现了图片转字符画(黑白)。...
  • m0_37884857
  • m0_37884857
  • 2017年08月30日 19:29
  • 388

opencv学习——利用轮廓画矩阵、外接圆、拟合曲线

import cv2 import numpy as npimg = cv2.imread('images/th.jpg')ret,thresh = cv2.threshold(cv2.cvtColo...
  • ei1990
  • ei1990
  • 2017年10月30日 20:55
  • 223

正则表达式学习(四)匹配单个字符

正则表达式学习(四)匹配单个字符 标签: 正则表达式regexjavajavascriptstring测试 2012-07-28 19:39 4122人阅读 评论(0) 收藏 举报 ...
  • evilcry2012
  • evilcry2012
  • 2016年11月24日 09:55
  • 349
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:字符画软件的四个关键技术
举报原因:
原因补充:

(最多只允许输入30个字)