CnPack Forum


 
Subject: AAFont字体描边及32位图像处理
croslq
新警察
Rank: 1



UID 1152
Digest Posts 0
Credits 48
Posts 41
点点分 48
Reading Access 10
Registered 2005-10-10
Status Offline
Post at 2005-10-10 09:38  Profile | Site | Blog | P.M.  | QQ
AAFont字体描边及32位图像处理

使用BeginPath, EndPath, FillPath函数
下载地址: http://lqcros.go1.wy8.net/NewAAFont2.63.rar

我觉得要制作更多的字体效果的话,最好是用,32位图像来制作
TBitmap就支持这个功能,不过,图像合成时需要一个函数CombineAlphaPixel(函数附后,这个函数是FLib里的)
使用Bitmap时请把他设成32位的,如: PixelFormat := pf32Bit;

//===================================================================
// 计算两个32bit象素的等效象素,这个函数非常重要(speed),安全检查就不做了
// cr1:背景    cr2:前景


// 这两个函数引用自FLIB //
// 只处理目标ALPHA通道时,两个函数可以替换到用 //

// 注意这里一下, 替换时请在DrawTo,DrawFrom 里面替换就可以了

//这个函数是以目标像素及源像素的Alpha通道合成
procedure  TBitmap32.CombineAlphaPixel(var pDest: TRGBQuad; cr1: TRGBQuad; nAlpha1: integer; cr2: TRGBQuad; nAlpha2: integer);
var
    nTmp1, nTmp12, nTemp, nTmp2: integer;
begin
        if ((nAlpha1 <> 0) or (nAlpha2 <> 0)) then
        begin
                if (nAlpha2 = 0) then
                begin
                        pDest.rgbBlue  := cr1.rgbBlue ;
                        pDest.rgbGreen := cr1.rgbGreen ;
                        pDest.rgbRed  := cr1.rgbRed ;
                        pDest.rgbReserved := nAlpha1 ;
                        exit;
                end;
                if ((nAlpha1 = 0) or (nAlpha2 = $FF)) then
                begin
                        pDest.rgbBlue  := cr2.rgbBlue ;
                        pDest.rgbGreen := cr2.rgbGreen ;
                        pDest.rgbRed   := cr2.rgbRed ;
                        pDest.rgbReserved := nAlpha2 ;
                        exit;
        end;


                // 以下用不着判断[0,0xFF],我验算过了
                nTmp1 := $FF * nAlpha1;
        nTmp2 := $FF * nAlpha2 ;
                nTmp12 := nAlpha1 * nAlpha2;
                nTemp  := nTmp1 + nTmp2 - nTmp12 ;
                pDest.rgbBlue  := (nTmp2 * cr2.rgbBlue  + (nTmp1 - nTmp12) * cr1.rgbBlue)  div nTemp ;
                pDest.rgbGreen := (nTmp2 * cr2.rgbGreen + (nTmp1 - nTmp12) * cr1.rgbGreen) div nTemp ;
                pDest.rgbRed   := (nTmp2 * cr2.rgbRed   + (nTmp1 - nTmp12) * cr1.rgbRed)   div nTemp ;
                pDest.rgbReserved := nTemp div $FF ;


//                下面的代码是未优化过的,可读性更好些
{
                nTemp :=  $FF * (nAlpha1 + nAlpha2) - nAlpha1*nAlpha2 ;
                pDest.rgbBlue  := min($FF, ($FF * cr2.rgbBlue  * nAlpha2 + ($FF - nAlpha2) * cr1.rgbBlue  * nAlpha1) div nTemp) ;
                pDest.rgbGreen := min($FF, ($FF * cr2.rgbGreen * nAlpha2 + ($FF - nAlpha2) * cr1.rgbGreen * nAlpha1) div nTemp) ;
                pDest.rgbRed   := min($FF, ($FF * cr2.rgbRed   * nAlpha2 + ($FF - nAlpha2) * cr1.rgbRed   * nAlpha1) div nTemp) ;
                pDest.rgbReserved := nTemp div $FF ;
}
        end
        else
        begin
                pDest.rgbBlue  := $FF;
        pDest.rgbGreen := $FF;
        pDest.rgbRed   := $FF;
                pDest.rgbReserved := 0 ;
        end;
end;

如:
            CombineAlphaPixel(Target^[x], Target^[x], Target^[x].rgbReserved, Source^[x - DstX], Source^[x- DstX].rgbReserved);

// 这个函数就更重要了,安全检查当然不做了:-),根据pSrc中的alpha计算,nAlphaSrc一定要保证在0,0xFF之间

//这个函数只是以源像素的Alpha通道合成
procedure TBitmap32.AlphaBlendPixel(var pDest: TRGBQuad; pSrc: TRGBQuad);
begin
    if (pSrc.rgbReserved = $FF) then
    begin
        PRGBArray(pDest) := PRGBArray(pSrc);
        exit;
    end;

    if (pSrc.rgbReserved = 0) then
    exit;
    // 以下用不着判断[0,0xFF],我验算过了

    if (PRGBArray(pSrc) <> PRGBArray(pDest)) then
    begin
        pDest.rgbBlue := (PSrc.rgbBlue - pDest.rgbBlue) * pSrc.rgbReserved div $FF + pDest.rgbBlue;
        pDest.rgbGreen := (PSrc.rgbGreen - pDest.rgbGreen) * pSrc.rgbReserved div $FF + pDest.rgbGreen;
        pDest.rgbRed := (PSrc.rgbRed - pDest.rgbRed) * pSrc.rgbReserved div $FF + pDest.rgbRed;
    end;
end;

如:
    AlphaBlendPixel(Target^[x], Source^[x]);


    //:o:o:o:o:o//
{    把这个函数写到DrawTo函数以替换CombineAlphaPiexl
     
图层的概念
[
最下层是画布(就是一个TBitmap32对像,也可以是Image1.Picture.Bitmap)
跟着上面的就是图层啦,文字层什么的
]


从最下层的32位图像画起
就可以把许多个32位图层到画布上,显示出来


procedure TBitmap32.DrawTo(DstX, DstY: Integer; Tge: TBitmap);
var
    x, y: integer;
    TR, SR: TRect;
    Source, Target: pRGBQuadArray;
begin
    Tge.PixelFormat := pf32bit;
    SetAlphaChannels(Tge, $FF);

    Tr := Rect(0, 0, Tge.Width, Tge.Height);
    SR := Rect(DstX, DstY, DstX + Width, DstY + Height);

    if IntersectRect(Tr, Tr, SR) = false then
    exit;

    for y := Tr.Top to Tr.Bottom - 1 do
    begin
        Target := Tge.ScanLine[y];
        Source := ScanLine[y - Dsty];


        for x := Tr.Left to Tr.Right - 1 do
        begin
//这里替换了
//            CombineAlphaPixel(Target^[x], Target^[x], Target^[x].rgbReserved, Source^[x - DstX], Source^[x- DstX].rgbReserved);
            AlphaBlendPixel(Target^[x], Source^[x]);
        end;


    end;

end;

for i := 0 to LayerList.Count -1 do
begin
    TBitmap32(LayerList.Items[i ]).DrawTo(0,0, Image1.Picture.Bitmap);
end;

}


    //:o:o:o:o:o:o//

[ Last edited by croslq on 2005-10-15 at 14:39 ]
Top
croslq
新警察
Rank: 1



UID 1152
Digest Posts 0
Credits 48
Posts 41
点点分 48
Reading Access 10
Registered 2005-10-10
Status Offline
Post at 2005-10-10 10:21  Profile | Site | Blog | P.M.  | QQ
请高手把上面哪个函数MMX优化一下

请高手把上面哪个函数MMX优化一下,不然哪个性能就有点差了哈
Top
croslq
新警察
Rank: 1



UID 1152
Digest Posts 0
Credits 48
Posts 41
点点分 48
Reading Access 10
Registered 2005-10-10
Status Offline
Post at 2005-10-10 10:23  Profile | Site | Blog | P.M.  | QQ
TBitmap32的可以这样实现

type
   TBitmap32 := class(TBitmap)


   end;
Top
croslq
新警察
Rank: 1



UID 1152
Digest Posts 0
Credits 48
Posts 41
点点分 48
Reading Access 10
Registered 2005-10-10
Status Offline
Post at 2005-10-10 10:25  Profile | Site | Blog | P.M.  | QQ
哈哈这样就可以处理32位图像了三

type
  TBitmap32 = class(TBitmap)
  private

  protected
  public
    constructor Create; override;
    destructor Destroy; override;

    procedure Assign(Source: TPersistent); override;                //重载,设置为32位
    procedure LoadFromFile(const Filename: string); override;       //重载,设置为32位
  end;



constructor TBitmap32.Create;
begin
    inherited Create;
    PixelFormat := pf32bit;
end;

destructor TBitmap32.Destroy;
begin
    inherited Destroy;
end;

procedure TBitmap32.LoadFromFile(const Filename: string);
begin
    inherited LoadFromFile(FileName);
    PixelFormat := pf32bit;
end;

procedure TBitmap32.Assign(Source: TPersistent);
begin
    inherited Assign(Source);
    PixelFormat := pf32bit;
end;
Top
croslq
新警察
Rank: 1



UID 1152
Digest Posts 0
Credits 48
Posts 41
点点分 48
Reading Access 10
Registered 2005-10-10
Status Offline
Post at 2005-10-10 10:29  Profile | Site | Blog | P.M.  | QQ
TBitmap32的可以这样实现

TBitmap32的FillRect不要使用,因为处理的颜色不是32位

procedure FillLongword(var X; Count: Integer; Value: Longword);
asm
// EAX = X
// EDX = Count
// ECX = Value
        PUSH    EDI

        MOV     EDI,EAX  // Point EDI to destination              
        MOV     EAX,ECX
        MOV     ECX,EDX
        TEST    ECX,ECX
        JS      @exit

        REP     STOSD    // Fill count dwords
@exit:
        POP     EDI
end;

procedure  TBitmap32.Clear(color: TColor32);
var
    x, y: integer;
    t1: int64;
begin

    t1 := timegettime;
    {
    for y := 0 to Height-1 do
    for x := 0 to Width-1 do
    SetPixel(x, y, Color);
    }
//    ZeroMemory(GetBits, Height* width *4);


    FillLongword(GetBits^[0], Width * Height, Color);

    TraceString(IntToStr(timegettime-t1));

end;
Top
zjy
管理员
Rank: 9Rank: 9Rank: 9



UID 2
Digest Posts 6
Credits 2385
Posts 1543
点点分 2385
Reading Access 102
Registered 2002-12-16
Location China
Status Offline
Post at 2005-10-10 10:56  Profile | Site | Blog | P.M. 
有个开放源码的 Graphi32 项目就是专门做 32 位位图处理的,里面有 MMX 优化的。
http://www.graphics32.org/




Zhou JingYu
CnPack Administrator
http://www.cnpack.org/
Top
zjy
管理员
Rank: 9Rank: 9Rank: 9



UID 2
Digest Posts 6
Credits 2385
Posts 1543
点点分 2385
Reading Access 102
Registered 2002-12-16
Location China
Status Offline
Post at 2005-10-10 14:10  Profile | Site | Blog | P.M. 
没地方上传,也可以用附件放到论坛上来。




Zhou JingYu
CnPack Administrator
http://www.cnpack.org/
Top
croslq
新警察
Rank: 1



UID 1152
Digest Posts 0
Credits 48
Posts 41
点点分 48
Reading Access 10
Registered 2005-10-10
Status Offline
Post at 2005-10-10 14:16  Profile | Site | Blog | P.M.  | QQ
这样的说。好的

OK,知道了


Attachment: font32image.rar (2005-10-10 14:16, 90.4 K)
Download count 841


Attachment: font32image.rar (2005-10-10 14:16, 90.4 K)
Download count 729


Attachment: Project1.rar (2005-10-10 14:16, 257.01 K)
Download count 801
Top
croslq
新警察
Rank: 1



UID 1152
Digest Posts 0
Credits 48
Posts 41
点点分 48
Reading Access 10
Registered 2005-10-10
Status Offline
Post at 2005-10-10 14:19  Profile | Site | Blog | P.M.  | QQ
这个是你们网站的AAFont,我加了描边的

这个是你们网站的AAFont,我加了描边的,因为上次给你发了一个,不过性能不佳,
终于找到哪个原因,是因为StrokePath这个微软的函数本身就性能差


Attachment: NewAAFont2.63.rar (2005-10-10 14:19, 449.95 K)
Download count 1120
Top
zjy
管理员
Rank: 9Rank: 9Rank: 9



UID 2
Digest Posts 6
Credits 2385
Posts 1543
点点分 2385
Reading Access 102
Registered 2002-12-16
Location China
Status Offline
Post at 2005-10-10 14:29  Profile | Site | Blog | P.M. 
好,那我把那些链接不能下载的帖子删除吧?




Zhou JingYu
CnPack Administrator
http://www.cnpack.org/
Top
croslq
新警察
Rank: 1



UID 1152
Digest Posts 0
Credits 48
Posts 41
点点分 48
Reading Access 10
Registered 2005-10-10
Status Offline
Post at 2005-10-12 20:34  Profile | Site | Blog | P.M.  | QQ
我用G32库里的BlendLine函数(MMX优化)测试了一下,性能没有明显的提高
可能是DELPHI的编译本身就带有pentium优化
Top
croslq
新警察
Rank: 1



UID 1152
Digest Posts 0
Credits 48
Posts 41
点点分 48
Reading Access 10
Registered 2005-10-10
Status Offline
Post at 2005-10-12 21:07  Profile | Site | Blog | P.M.  | QQ
上面这个32位图像处理的方法,可以开发字体特效(抗锯齿,字体的纹理填充,阴影,描边及描边的纹理填充),也可以开发其他的如图像处理软件(图层什么的),只要再在里面加入一部分功能(如:画线、矩形,非规则区域选择<ALPHA通道(把ALPHA作为一个MASK处理就行)>......)。。。。。。

刘 强 2005.10.13
邮箱地址:lqcros@163.com
主页地址:http://lqcros.go1.wy8.net

[ Last edited by croslq on 2005-10-13 at 14:06 ]
Top
croslq
新警察
Rank: 1



UID 1152
Digest Posts 0
Credits 48
Posts 41
点点分 48
Reading Access 10
Registered 2005-10-10
Status Offline
Post at 2005-10-13 08:53  Profile | Site | Blog | P.M.  | QQ
font32image.rar包里面一个GraphicEx库,通过他可以打开TGA,PSD,BMP,TIFF等图像文件。
我一般是用他来打开32位TGA图像或32位BMP图像,然后通过32位图像处理函数里的DrawTo函数输出到屏幕,DrawTo有2个重载函数,一个是把self写到32位图像,一个是把self写到一般的Tbitmap。
例:
    Bitmap.DrawTo(0,0,Image1.Picture.Bitmap);


刘 强 2005.10.13
邮箱地址:lqcros@163.com
主页地址:http://lqcros.go1.wy8.net

[ Last edited by croslq on 2005-10-13 at 14:07 ]
Top
croslq
新警察
Rank: 1



UID 1152
Digest Posts 0
Credits 48
Posts 41
点点分 48
Reading Access 10
Registered 2005-10-10
Status Offline
Post at 2005-10-13 09:19  Profile | Site | Blog | P.M.  | QQ
刘 强 2005.10.13
邮箱地址:lqcros@163.com
主页地址:http://lqcros.go1.wy8.net

[ Last edited by croslq on 2005-10-13 at 14:07 ]


Attachment: demo.part01.rar (2005-10-13 09:19, 500 K)
Download count 888


Attachment: demo.part02.rar (2005-10-13 09:19, 500 K)
Download count 1007


Attachment: demo.part03.rar (2005-10-13 09:19, 279.73 K)
Download count 1026
Top
croslq
新警察
Rank: 1



UID 1152
Digest Posts 0
Credits 48
Posts 41
点点分 48
Reading Access 10
Registered 2005-10-10
Status Offline
Post at 2005-10-13 13:50  Profile | Site | Blog | P.M.  | QQ
其实 CreateFontIndirect 这个函数就能输出抗锯齿的字体啦

Delphi这样使用:

procedure TForm1.Button1Click(Sender: TObject);
var
  lf : TLogFont;
  Bitmap: TBitmap;
begin
    Bitmap := TBitmap.create;
    Bitmap.Width := 400;
    Bitmap.Height := 200;

    Bitmap.Canvas.Font.Name := '华文行楷';
    Bitmap.Canvas.Font.Size := 72;
    Bitmap.Canvas.Font.Style := [fsBold, fsItalic, fsUnderline, fsStrikeOut];
    GetObject(Bitmap.Canvas.Font.Handle, SizeOf(TLogFont), @lf);
    lf.lfQuality := ANTIALIASED_QUALITY;   //设置输出质量(抗锯齿)
    Bitmap.Canvas.Font.Handle := CreateFontIndirect(lf);
    Bitmap.Canvas.TextOut(0,0,'平滑字体');
    Image1.Picture.Bitmap.Assign(Bitmap);
    Bitmap.Free;
end;


刘 强 2005.10.13
邮箱地址:lqcros@163.com
主页地址:http://lqcros.go1.wy8.net

[ Last edited by croslq on 2005-10-13 at 14:13 ]
Top
croslq
新警察
Rank: 1



UID 1152
Digest Posts 0
Credits 48
Posts 41
点点分 48
Reading Access 10
Registered 2005-10-10
Status Offline
Post at 2005-10-13 14:03  Profile | Site | Blog | P.M.  | QQ
通过函数 GetGlyphOutline 可以取得 TrueType 字体的轮廓,就可以描边啦
可以参考网址:http://www.legalsoft.com.cn/articles/show.asp?id=269

也可以使用beginPath, EndPath, GetPath 提取


        FPathPoints: array of TPoint;
        FPathTypes: array of Byte;
        FNumber: Integer;
        PointIdx: integer;

  BeginPath(GrayBmp.Canvas.Handle);
    SetBkMode(GrayBmp.Canvas.Handle, TRANSPARENT);
    GrayBmp.Canvas.TextOut(0, 0, Text);
  EndPath(GrayBmp.Canvas.Handle);

  FNumber := GetPath(GrayBmp.Canvas.Handle, Pointer(nil^), Pointer(nil^), 0);
  SetLength(FPathPoints, FNumber);
  SetLength(FPathTypes, FNumber);
  FNumber := GetPath(GrayBmp.Canvas.Handle, FPathPoints[0], FPathTypes[0], FNumber);

  PointIdx := 0;  

//+++  描边//
    while PointIdx < FNumber do begin

    case FPathTypes[PointIdx] of PT_MOVETO:
        begin
            GrayBmp.Canvas.MoveTo(FPathPoints[PointIdx].X, FPathPoints[PointIdx].Y);
            LastMove := FPathPoints[PointIdx];
            inc(PointIdx, 1);
        end;
        PT_LINETO:
        begin
            GrayBmp.Canvas.LineTo(FPathPoints[PointIdx].X, FPathPoints[PointIdx].Y);
            inc(PointIdx, 1);
        end;
        PT_BEZIERTO:
        begin
            PolyBezierTo(GrayBmp.Canvas.Handle, FPathPoints[PointIdx], 3);
            inc(PointIdx, 3);
        end;
        PT_LINETO or PT_CLOSEFIGURE:
        begin
            GrayBmp.Canvas.LineTo(FPathPoints[PointIdx].X, FPathPoints[PointIdx].y);
            GrayBmp.Canvas.LineTo(LastMove.x, LastMove.y);
            inc(PointIdx, 1);
        end;
        PT_BEZIERTO or PT_CLOSEFIGURE:
        begin
            PolyBezierTo(GrayBmp.Canvas.Handle, FPathPoints[PointIdx], 3);
            GrayBmp.Canvas.LineTo(LastMove.x, LastMove.y);
            inc(PointIdx, 3);
        end;
    end;
    end;


  SetLength(FPathPoints, 0);
  SetLength(FPathTypes, 0);

刘 强 2005.10.13
邮箱地址:lqcros@163.com
主页地址:http://lqcros.go1.wy8.net

[ Last edited by croslq on 2005-10-13 at 14:07 ]
Top
croslq
新警察
Rank: 1



UID 1152
Digest Posts 0
Credits 48
Posts 41
点点分 48
Reading Access 10
Registered 2005-10-10
Status Offline
Post at 2005-10-15 14:44  Profile | Site | Blog | P.M.  | QQ
32位图层(随手写的,没测试,你们看一下原理就行了哈:P)

type
   TLayerList = class(TList)
   private

   end;

Bitmap32 : TBitmap32;
LayerList := TLayerList.Create;

Bitmap32 := TBitmap32.Create;
Bitmap32.LoadFromFile('1.tga');
LayerList.Items.add(Bitmap32);


for i := 0 to LayerList.Count -1 do
begin
    TBitmap32(LayerList.Items[i ]).DrawTo(0,0, Image1.Picture.Bitmap);
end;


for i := 0 to LayerList.Count -1 do
begin
TBitmap32(LayerList.Items[i ]).Free;
end;
LayerList.Free;

刘 强 2005.10.13
邮箱地址:lqcros@163.com
主页地址:http://lqcros.go1.wy8.net

[ Last edited by croslq on 2005-10-15 at 14:45 ]
Top
croslq
新警察
Rank: 1



UID 1152
Digest Posts 0
Credits 48
Posts 41
点点分 48
Reading Access 10
Registered 2005-10-10
Status Offline
Post at 2005-10-15 18:02  Profile | Site | Blog | P.M.  | QQ
MMX优化AlphaBlendPixel

//                             TColor32(AARRGGBB)     TColor32        0 .. 255
//                                 |            |                |
//               AlphaBlendPixel(Source^[x], Target^[x], AlphaComponent(Source^[x]));
procedure AlphaBlendPixel(Source: TColor32; var Target: TColor32; Alpha: DWORD);
asm
    MOVD            MM1, EAX        // MM1 = 00 00 00 00 ** Fr Fg Fb
    MOVD            MM2,[EDX]      // MM2 = 00 00 00 00 ** Br Bg Bb
    PUNPCKLBW MM1, MM0       // MM1 = 00 ** 00 Fr 00 Fg 00 Fb
    MOVD            MM3, ECX       // MM3 = 00 00 00 00 00 00 00 AA  
    PUNPCKLBW MM2, MM0       // MM2 = 00 ** 00 Br 00 Bg 00 Bb
    PSHUFW       MM3, MM3, 0   // MM3 = 00 AA 00 AA 00 AA 00 AA
    PSUBW         MM1, MM2
    PSLLW          MM2, 8
    PMULLW       MM1, MM3
    PADDW         MM1, MM2
    PSRLW          MM1, 8
    PACKUSWB   MM1, MM0
    MOVD           [EDX],MM1
    emms
end;

[ Last edited by croslq on 2005-10-15 at 20:30 ]
Top
croslq
新警察
Rank: 1



UID 1152
Digest Posts 0
Credits 48
Posts 41
点点分 48
Reading Access 10
Registered 2005-10-10
Status Offline
Post at 2005-10-17 15:40  Profile | Site | Blog | P.M.  | QQ
抗锯齿直线的实现

附件里的自定义的画笔(掩码图),它本身边缘就是羽化了的,所以就能抗锯齿
下面画线函数,首先确定直线的每一点的坐标,然后把自定义画笔画到这个坐标上,直到画完线
(这个抗锯齿直线就画起了三)

这个方法还可以反走样字体的边缘啦
在哪个EndPath后面
加一个FlattenPath函数(平整为直线的)
16楼哪个画直线函数用这个函数替换


procedure DrawMaskPen(TargetBitmap: TBitmap; DstX, DstY: Integer; Mask8: TBitmap);
var
    Source, Target: PByteArray;
    TR, SR: TRect;
    x, y: integer;   
begin

    TR := Rect(0, 0, TargetBitmap.Width, TargetBitmap.Height);
    SR := Rect(DstX, DstY, DstX + Mask8.Width, DstY + Mask8.Height);

    if IntersectRect(TR, TR, SR) = false then
    exit;

    for y := Tr.Top to Tr.Bottom - 1 do
    begin
        Target := TargetBitmap.ScanLine[y];
        Source := Mask8.ScanLine[y - Dsty];
        for x := TR.Left to Tr.Right - 1 do
        begin
            if (Target^[x] + Source^[x - Dstx]) > 255 then
            Target^[x] := 255
            else
            Target^[x] := Target^[x] + Source^[x - Dstx];
        end;
    end;   
end;


//采用Bresenham算法绘制一条颜色相同的直线
//将Bresenham算法写成统一的形式
//x1, y1, x2, y2直线的起点和端点
//通过附件里自定义的画笔,实现了8位蒙板图画抗锯齿直线

procedure LineMaskPen(Target8: TBitmap; x1, y1, x2, y2: integer; MaskPen8: TBitmap);
var
    nDx, nDy: integer;
    nIx, nIy: integer;
    nInc: integer;
    nJudgeX, nJudgeY: integer;
    x, y: integer;
    nTwoIx, nTwoIy: integer;
    i: integer;
    bPlot: boolean;

begin
        //两端点间的水平偏移量和垂直偏移量
        nDx := x2 - x1;
        nDy := y2 - y1;

        //两端点间的水平距离和垂直距离
        nIx := ABS(nDx);
        nIy := ABS(nDy);

        //描点步数(增量总值)
        nInc := MAX(nIx, nIy);

        //绘制第一个点, 即, 直线的起点
//        SetPixel(hdc, x1, y1, clr);
    DrawMaskPen(Target, x1- MaskPen8.Width div 2, y1 - MaskPen8.Height div 2, MaskPen8);

        //不包含终点
        if(nInc < 2) then
    exit;

        //用于判断是否在nJudgeX, nJudgeY方向上向前进
        nJudgeX := -nIy;
    nJudgeY := -nIx;

        //通过增量计算得到的当前点
        x := x1;
    y := y1;
       
        //开始进行增量计算
        //采用Bresenham算法.在这里, 我们将算法进行改进,
        //使其对于任意斜率的直线都能绘制, 而且绘制方向始终为从起点绘制到终点

        //注意, 整数乘2在计算机中采用移位实现
        //Bresenham算法
        nTwoIx := 2 * nIx;
    nTwoIy := 2 * nIy;

        //与Windows相对应, 该算法也不包含最后一个点(x2, y2)
        dec(nInc);

        //开始增量计算
        for i := 0  to nInc -1 do
    begin
                nJudgeX := nJudgeX + nTwoIx;
                nJudgeY := nJudgeY + nTwoIy;

                //通过增量法计算的当前点是否属于直线上的点
                bPlot := FALSE;

                //检测 X 方向
                if(nJudgeX >= 0) then
                begin
                        bPlot := TRUE;
                        nJudgeX := nJudgeX - nTwoIy;

                        //将任意走向的直线统一起来
                        if(nDx > 0) then
            inc(x)
                        else if(nDx < 0) then
            dec(x)
                end;

                //检测 Y 方向
                if(nJudgeY >= 0) then
                begin
                        bPlot := TRUE;
                        nJudgeY := nJudgeY - nTwoIx;

                        //将任意走向的直线统一起来
                        if(nDy > 0) then
            inc(y)
                        else if(nDy < 0) then
            dec(y);
                end;
                //如果当前点在直线上, 则绘制当前点
                if(bPlot) then
//        SetPixel(hdc, x, y, clr);
        DrawMaskPen(Target, x- MaskPen8.Width div 2, y- MaskPen8.Height div 2, MaskPen8);
        end;//end for  
end;

//画32位色直线这样画啦
var
   Bitmap: TBitmap32;
   Mask: TBitmap;
begin
   Bitmap := TBitmap32.Create;
   Bitmap.Width := 500;
   Bitmap.Height := 500;
   Mask := TBitmap.Create;
   Mask.Width := 500;
   Mask.Height := 500;
   
   Image1.Picture.Bitmap.PixelFormat := pf8bit;
   LineMaskPen(Mask, 0, 0, 200, 200, Image1.Picture.Bitmap);  //Image1.Picture.Bitmap 这里保存的是附件里的8位自定义画笔

   Bitmap.Clear($FFFF0000);         //设为红色
   Bitmap.SetAlphaChannels(Mask);   //只有线条显示

   Bitmap.Free;
end;

[ Last edited by croslq on 2005-10-17 at 15:53 ]


Image Attachment: pen08.jpg (2005-10-17 15:40, 1.02 K)



Image Attachment: pen13.jpg (2005-10-17 15:40, 1.16 K)

Top
croslq
新警察
Rank: 1



UID 1152
Digest Posts 0
Credits 48
Posts 41
点点分 48
Reading Access 10
Registered 2005-10-10
Status Offline
Post at 2005-10-20 08:29  Profile | Site | Blog | P.M.  | QQ
定义一个画笔类

定义画笔公用类,就像Windows里的CreatePen,
通过这个函数直接生成自定义大小的反走样8位Bitmap。

//生成掩码灰度画笔

TPenMaskBitmap = class(TBitmap)
public
    constructor Create; override;
    destructor Destroy; override;
    procedure CreateMaskBitmap(w, h: integer);
end;

constructor TPenMaskBitmap.Create;
begin
    inherited Create;
    PixelFormat := pf8bit;
end;

destructor TPenMaskBitmap.Destroy;
begin
    inherited Destroy;
end;

procedure TPenMaskBitmap.CreateMaskBitmap(w, h: integer);
begin
    //这里省了哈

end;

// 这个类在程序启动时就运行,在程序完了时就释放;
// 这个类直接生成32位色画笔,可以设定颜色,纹理,大小,透明度什么的。

TPenBitmap = class(TBitmap)  // class(TBitmap32)

public
    constructor Create; override;
    destructor Destroy; override;
    procedure CreateBitmap(w, h: integer);
end;

constructor TPenBitmap.Create;
begin
    inherited Create;
    PixelFormat := pf32bit;
end;

destructor TPenBitmap.Destroy;
begin
    inherited Destroy;
end;

procedure TPenMaskBitmap.CreateMaskBitmap(w, h: integer);
begin
    //这里省了哈

end;
Top
 




All times are GMT++8, the time now is 2024-11-25 12:19

    本论坛支付平台由支付宝提供
携手打造安全诚信的交易社区 Powered by Discuz! 5.0.0  © 2001-2006 Comsenz Inc.
Processed in 0.017439 second(s), 10 queries , Gzip enabled

Clear Cookies - Contact Us - CnPack Website - Archiver - WAP