CnPack Forum » CnVCL 组件包 » AAFont精度采样


2005-10-18 08:59 croslq
AAFont精度采样

zjy,你的字体精度采样哪段的确做得好。
下面一段
  BytesLineGray := (GrayBmp.Width + 3) div 4 * 4; //扫描线宽度
  BytesLineMask := (FMaskPathBmp.Width + 3) div 4 * 4;

  pS1 := GrayBmp.ScanLine[0];           //源灰度图
  pS2 := PByteArray(Integer(pS1) - BytesLineGray);
  pS3 := PByteArray(Integer(pS2) - BytesLineGray);
  pS4 := PByteArray(Integer(pS3) - BytesLineGray);
  pDes := FMaskPathBmp.ScanLine[0];
//  pDes := PByteArray(Integer(FMaskBmp.scanLine[0]) + (FMaskBmp.Height - 1) * BytesLineMask);
    //目标灰度为源矩形块的平均值
  case Quality of
    aqHigh:
      begin                             //高精度4X4采样
        for i := 0 to FMaskPathBmp.Height - 1 do
        begin
          for j := 0 to FmaskPathBmp.Width - 1 do
          begin
            x := j * 4;
            pDes^[j] :=
              (pS1^[x] + pS1^[x + 1] + pS1^[x + 2] + pS1^[x + 3] +
              pS2^[x] + pS2^[x + 1] + pS2^[x + 2] + pS2^[x + 3] +
              pS3^[x] + pS3^[x + 1] + pS3^[x + 2] + pS3^[x + 3] +
              pS4^[x] + pS4^[x + 1] + pS4^[x + 2] + pS4^[x + 3]) shr 4;
          end;
          pS1 := PByteArray(Integer(pS4) - BytesLineGray);
          pS2 := PByteArray(Integer(pS1) - BytesLineGray);
          pS3 := PByteArray(Integer(pS2) - BytesLineGray);
          pS4 := PByteArray(Integer(pS3) - BytesLineGray);
          pDes := PByteArray(Integer(pDes) - BytesLineMask);
        end;
      end;
    aqNormal:
      begin                             //普通精度3X3采样
        for i := 0 to FMaskPathBmp.Height - 1 do
        begin
          for j := 0 to FMaskPathBmp.Width - 1 do
          begin
            x := j * 3;
            pDes^[j] :=
              (pS1^[x] + pS1^[x + 1] + pS1^[x + 2] shr 1 +
              pS2^[x] + pS2^[x + 1] + pS2^[x + 2] +
              pS3^[x] shr 1 + pS3^[x + 1] + pS3^[x + 2]) shr 3;
          end;
          pS1 := PByteArray(Integer(pS3) - BytesLineGray);
          pS2 := PByteArray(Integer(pS1) - BytesLineGray);
          pS3 := PByteArray(Integer(pS2) - BytesLineGray);
          pDes := PByteArray(Integer(pDes) - BytesLineMask);
        end;
      end;
    aqLow:
      begin                             //低精度2X2采样
        for i := 0 to FMaskPathBmp.Height - 1 do
        begin
          for j := 0 to FMaskPathBmp.Width - 1 do
          begin
            x := j * 2;
            pDes^[j] :=
              (pS1^[x] + pS1^[x + 1] +
              pS2^[x] + pS2^[x + 1]) shr 2;
          end;
          pS1 := PByteArray(Integer(pS2) - BytesLineGray);
          pS2 := PByteArray(Integer(pS1) - BytesLineGray);
          pDes := PByteArray(Integer(pDes) - BytesLineMask);
        end;
      end;
    aqNone:
      begin                             //无平滑效果
        for i := 0 to FMaskPathBmp.Height - 1 do
        begin
          CopyMemory(pDes, pS1, FMaskPathBmp.Width);
          pS1 := PByteArray(Integer(pS1) - BytesLineGray);
          pDes := PByteArray(Integer(pDes) - BytesLineMask);
        end;
      end;
  end;
   


比起这段代码快多了。虽然下面这段代码更小,由于要在内循环内运行许多次加法 除法运算,
速度要慢很多


    for y := 0 to GrayBmp.Height Div Scale -1 do
    begin
      DestScan := FMaskPathBmp.ScanLine[y];
      for x := 0 to GrayBmp.Width Div Scale -1 do
      begin
        tot := 0;

        for j := 0 to Scale - 1 do
        begin
          BigScan := pByteArray(GrayBmp.ScanLine[Scale * y + j] );
          for i := 0 to Scale -1 do
          begin
            tot := tot + BigScan[Scale * x+i];
          end;
        end;
        DestScan[x] := tot div (Scale * Scale);
      end;
    end;


我找到一个MMX的,不过用你哪个也像是性能差不多

////////////////////////////////////////////////////////////////////////////////
// File:       PegtopResampleUtils.pas
// Version:    1.00
// Date:       16 Mar 2005 created 1.00
// Author:     Jens Gruschel (GRU)
// Copyright:  (c) 2005 Jens Gruschel
// Website:    [url]http://www.pegtop.net/delphi[/url]
////////////////////////////////////////////////////////////////////////////////
// Description:
// Procedures to resample bitmaps using MMX.
////////////////////////////////////////////////////////////////////////////////
// License:
// Please read the license.txt file that comes with this software
// and visit [url]http://www.pegtop.net/delphi[/url]
////////////////////////////////////////////////////////////////////////////////
// Documentation / Installation:
// Please read the readme.txt file that comes with this software
// and visit [url]http://www.pegtop.net/delphi[/url]
////////////////////////////////////////////////////////////////////////////////

unit PegtopResampleUtils;

interface

uses
  Windows;

// Bitmap resampling (without clipping):
procedure PegtopResample2x32MMX(const DestOrigin: Pointer; const DestPitch: Integer; const DestRect: TRect;
  const SourceOrigin: Pointer; const SourcePitch: Integer; const SourceX, SourceY: Integer);
procedure PegtopResample4x32MMX(const DestOrigin: Pointer; const DestPitch: Integer; const DestRect: TRect;
  const SourceOrigin: Pointer; const SourcePitch: Integer; const SourceX, SourceY: Integer);

implementation

////////////////////////////////////////////////////////////////////////////////
// Bitmap resampling (without clipping)
////////////////////////////////////////////////////////////////////////////////

procedure PegtopResample2x32MMX(const DestOrigin: Pointer; const DestPitch: Integer; const DestRect: TRect;
  const SourceOrigin: Pointer; const SourcePitch: Integer; const SourceX, SourceY: Integer);
var
  W, Y: Integer;
  DestQ: Pointer;
  SourceQ: Pointer;
begin
  DestQ := Pointer(Integer(DestOrigin) + DestRect.Top * DestPitch + DestRect.Left * 4);
  SourceQ := Pointer(Integer(SourceOrigin) + SourceY * SourcePitch + SourceX * 4);
  W := DestRect.Right - DestRect.Left;
  asm
    // we need mm0 to be zero during the whole loop:
    db $0F,$EF,$C0           /// pxor      mm0, mm0
  end;
  for Y := DestRect.Top to DestRect.Bottom - 1 do begin
    asm
      mov       eax, SourceQ
      mov       edx, DestQ
      mov       ecx, W
      @xloop:
        // source pixels (0,0) and (1,0):
        db $0F,$6F,$08           /// movq      mm1, [eax]
        db $0F,$6F,$D1           /// movq      mm2, mm1
        db $0F,$60,$C8           /// punpcklbw mm1, mm0
        db $0F,$68,$D0           /// punpckhbw mm2, mm0
        db $0F,$DD,$CA           /// paddusw   mm1, mm2
        // source pixels (0,1) and (1,1):
        add       eax, SourcePitch
        db $0F,$6F,$10           /// movq      mm2, [eax]
        db $0F,$6F,$DA           /// movq      mm3, mm2
        db $0F,$60,$D0           /// punpcklbw mm2, mm0
        db $0F,$68,$D8           /// punpckhbw mm3, mm0
        db $0F,$DD,$CA           /// paddusw   mm1, mm2
        db $0F,$DD,$CB           /// paddusw   mm1, mm3
        // set average color (divide by 4):
        db $0F,$71,$D1,$02       /// psrlw mm1, 2
        db $0F,$67,$C8           /// packuswb  mm1, mm0
        db $0F,$7E,$0A           /// movd      [edx], mm1
        // next source pixel block:
        sub       eax, SourcePitch
        add       eax, 8
        // next destination pixel:
        add       edx, 4
        dec ecx
      jnz @xloop
    end;
    DestQ := Pointer(Integer(DestQ) + DestPitch);
    SourceQ := Pointer(Integer(SourceQ) + SourcePitch + SourcePitch);
  end;
  asm
    // finish MMX usage:
    db $0F,$77               /// emms
  end;
end;

procedure PegtopResample4x32MMX(const DestOrigin: Pointer; const DestPitch: Integer; const DestRect: TRect;
  const SourceOrigin: Pointer; const SourcePitch: Integer; const SourceX, SourceY: Integer);
var
  W, Y: Integer;
  DestQ: Pointer;
  SourceQ: Pointer;
  BlockStep: Integer;
begin
  DestQ := Pointer(Integer(DestOrigin) + DestRect.Top * DestPitch + DestRect.Left * 4);
  SourceQ := Pointer(Integer(SourceOrigin) + SourceY * SourcePitch + SourceX * 4);
  BlockStep := SourcePitch * 4 - 16;
  W := DestRect.Right - DestRect.Left;
  asm
    // we need mm0 to be zero during the whole loop:
    db $0F,$EF,$C0           /// pxor      mm0, mm0
  end;
  for Y := DestRect.Top to DestRect.Bottom - 1 do begin
    asm
      mov       eax, SourceQ
      mov       edx, DestQ
      mov       ecx, W
      @xloop:
        push ecx
        db $0F,$EF,$C9           /// pxor      mm1, mm1
        // process 4 lines of source bitmap:
        mov ecx, 4
        @ploop:
          // source pixels (0,p) and (1,p):
          db $0F,$6F,$10           /// movq      mm2, [eax]
          db $0F,$6F,$DA           /// movq      mm3, mm2
          db $0F,$60,$D0           /// punpcklbw mm2, mm0
          db $0F,$68,$D8           /// punpckhbw mm3, mm0
          db $0F,$DD,$CA           /// paddusw   mm1, mm2
          db $0F,$DD,$CB           /// paddusw   mm1, mm3
          // source pixels (2,p) and (3,p):
          add       eax, 8
          db $0F,$6F,$10           /// movq      mm2, [eax]
          db $0F,$6F,$DA           /// movq      mm3, mm2
          db $0F,$60,$D0           /// punpcklbw mm2, mm0
          db $0F,$68,$D8           /// punpckhbw mm3, mm0
          db $0F,$DD,$CA           /// paddusw   mm1, mm2
          db $0F,$DD,$CB           /// paddusw   mm1, mm3
          // next source line:
          sub       eax, 8
          add       eax, SourcePitch
          dec ecx
        jnz @ploop
        // set average color (divide by 16):
        db $0F,$71,$D1,$04       /// psrlw mm1, 4
        db $0F,$67,$C8           /// packuswb  mm1, mm0
        db $0F,$7E,$0A           /// movd      [edx], mm1
        // next source pixel block:
        sub       eax, BlockStep
        // next destination pixel:
        add       edx, 4
        pop ecx
        dec ecx
      jnz @xloop
    end;
    DestQ := Pointer(Integer(DestQ) + DestPitch);
    SourceQ := Pointer(Integer(SourceQ) + SourcePitch * 4);
  end;
  asm
    // finish MMX usage:
    db $0F,$77               /// emms
  end;
end;

end.

[[i] Last edited by croslq on 2005-10-18 at 09:06 [/i]]

页: [1]
查看完整版本: AAFont精度采样


Powered by Discuz! Archiver 5.0.0  © 2001-2006 Comsenz Inc.