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:
http://www.pegtop.net/delphi
////////////////////////////////////////////////////////////////////////////////
// Description:
// Procedures to resample bitmaps using MMX.
////////////////////////////////////////////////////////////////////////////////
// License:
// Please read the license.txt file that comes with this software
// and visit
http://www.pegtop.net/delphi
////////////////////////////////////////////////////////////////////////////////
// Documentation / Installation:
// Please read the readme.txt file that comes with this software
// and visit
http://www.pegtop.net/delphi
////////////////////////////////////////////////////////////////////////////////
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.
[
Last edited by croslq on 2005-10-18 at 09:06 ]