📄 gr32_resamplers.pas
字号:
Ca := 0; Cr := 0; Cg := 0; Cb := 0;
for Y := 0 to Length(ClusterY) - 1 do
begin
C := Src.Bits[X + ClusterY[Y].Pos * Src.Width];
ClustYW := ClusterY[Y].Weight;
Inc(Ca, C shr 24 * ClustYW);
Inc(Cr, (C and $00FF0000) shr 16 * ClustYW);
Inc(Cg, (C and $0000FF00) shr 8 * ClustYW);
Inc(Cb, (C and $000000FF) * ClustYW);
end;
with HorzBuffer[X - MapXLoPos] do
begin
R := Cr;
G := Cg;
B := Cb;
A := Ca;
end;
end;
DstLine := Dst.ScanLine[J];
for I := DstClip.Left to DstClip.Right - 1 do
begin
ClusterX := MapX[I - DstClip.Left];
Ca := 0; Cr := 0; Cg := 0; Cb := 0;
for X := 0 to Length(ClusterX) - 1 do
begin
Wt := ClusterX[X].Weight;
with HorzBuffer[ClusterX[X].Pos - MapXLoPos] do
begin
Inc(Ca, A * Wt);
Inc(Cr, R * Wt);
Inc(Cg, G * Wt);
Inc(Cb, B * Wt);
end;
end;
if RangeCheck then
begin
if Ca > $FF0000 then Ca := $FF0000
else if Ca < 0 then Ca := 0
else Ca := Ca and $00FF0000;
if Cr > $FF0000 then Cr := $FF0000
else if Cr < 0 then Cr := 0
else Cr := Cr and $00FF0000;
if Cg > $FF0000 then Cg := $FF0000
else if Cg < 0 then Cg := 0
else Cg := Cg and $00FF0000;
if Cb > $FF0000 then Cb := $FF0000
else if Cb < 0 then Cb := 0
else Cb := Cb and $00FF0000;
C := (Ca shl 8) or Cr or (Cg shr 8) or (Cb shr 16);
end
else
C := ((Ca and $00FF0000) shl 8) or (Cr and $00FF0000) or ((Cg and $00FF0000) shr 8) or ((Cb and $00FF0000) shr 16);
// combine it with the background
case CombineOp of
dmOpaque: DstLine[I] := C;
dmBlend: BlendMemEx(C, DstLine[I], Src.MasterAlpha);
dmTransparent: if C <> Src.OuterColor then DstLine[I] := C;
dmCustom: CombineCallBack(C, DstLine[I], Src.MasterAlpha);
end;
end;
end;
finally
EMMS;
MapX := nil;
MapY := nil;
end;
end;
{$WARNINGS ON}
{ Draft Resample Routines }
function BlockAverage_MMX(Dlx, Dly, RowSrc, OffSrc: Cardinal): TColor32;
asm
push ebx
push esi
push edi
mov ebx, OffSrc
mov esi, eax
mov edi, edx
sub ecx, $04
db $0F,$EF,$C9 /// pxor mm1, mm1
db $0F,$EF,$D2 /// pxor mm2, mm2
db $0F,$EF,$FF /// pxor mm7, mm7
@@LoopY:
mov esi, eax
db $0F,$EF,$C0 /// pxor mm0, mm0
@@LoopX:
db $0F,$6E,$34,$B1 /// movd mm6, [ecx + esi * 4]
db $0F,$60,$F7 /// punpcklbw mm6, mm7
db $0F,$FD,$C6 /// paddw mm0, mm6
dec esi
jnz @@LoopX
db $0F,$6F,$F0 /// movq mm6, mm0
db $0F,$61,$F7 /// punpcklwd mm6, mm7
db $0F,$FE,$CE /// paddd mm1, mm6
db $0F,$6F,$F0 /// movq mm6, mm0
db $0F,$69,$F7 /// punpckhwd mm6, mm7
db $0F,$FE,$D6 /// paddd mm2, mm6
add ecx, ebx
dec edx
jnz @@LoopY
mul edi
mov ecx, eax
mov eax, $01000000
div ecx
mov ecx, eax
db $0F,$7E,$C8 /// movd eax, mm1
mul ecx
shr eax, $18
mov edi, eax
db $0F,$73,$D1,$20 /// psrlq mm1, $20
db $0F,$7E,$C8 /// movd eax, mm1
mul ecx
shr eax, $10
and eax, $0000FF00
add edi, eax
db $0F,$7E,$D0 /// movd eax, mm2
mul ecx
shr eax, $08
and eax, $00FF0000
add edi, eax
db $0F,$73,$D2,$20 /// psrlq mm2, $20
db $0F,$7E,$D0 /// movd eax, mm2
mul ecx
and eax, $FF000000
add eax, edi
pop edi
pop esi
pop ebx
end;
function BlockAverage_3dNow(Dlx, Dly, RowSrc, OffSrc: Cardinal): TColor32;
asm
push ebx
push esi
push edi
mov ebx, OffSrc
mov esi, eax
mov edi, edx
shl esi, $02
sub ebx, esi
db $0F,$EF,$C9 /// pxor mm1, mm1
db $0F,$EF,$D2 /// pxor mm2, mm2
db $0F,$EF,$FF /// pxor mm7, mm7
@@LoopY:
mov esi, eax
db $0F,$EF,$C0 /// pxor mm0, mm0
db $0F,$0D,$34,$F1 /// prefetch [ecx + esi * 8]
@@LoopX:
db $0F,$6E,$31 /// movd mm6, [ecx]
db $0F,$60,$F7 /// punpcklbw mm6, mm7
db $0F,$FD,$C6 /// paddw mm0, mm6
add ecx, $04
dec esi
jnz @@LoopX
db $0F,$6F,$F0 /// movq mm6, mm0
db $0F,$61,$F7 /// punpcklwd mm6, mm7
db $0F,$FE,$CE /// paddd mm1, mm6
db $0F,$6F,$F0 /// movq mm6, mm0
db $0F,$69,$F7 /// punpckhwd mm6, mm7
db $0F,$FE,$D6 /// paddd mm2, mm6
add ecx, ebx
dec edx
jnz @@LoopY
mul edi
mov ecx, eax
mov eax, $01000000
div ecx
mov ecx, eax
db $0F,$7E,$C8 /// movd eax, mm1
mul ecx
shr eax, $18
mov edi, eax
db $0F,$73,$D1,$20 /// psrlq mm1, $20
db $0F,$7E,$C8 /// movd eax, mm1
mul ecx
shr eax, $10
and eax, $0000FF00
add edi, eax
db $0F,$7E,$D0 /// movd eax, mm2
mul ecx
shr eax, $08
and eax, $00FF0000
add edi, eax
db $0F,$73,$D2,$20 /// psrlq mm2, $20
db $0F,$7E,$D0 /// movd eax, mm2
mul ecx
and eax, $FF000000
add eax, edi
pop edi
pop esi
pop ebx
end;
function BlockAverage_IA32(Dlx, Dly, RowSrc, OffSrc: Cardinal): TColor32;
type
PCardinal = ^Cardinal;
PRGBA = ^TRGBA;
TRGBA = record B,G,R,A: Byte end;
var
C: PRGBA;
ix, iy, iA, iR, iG, iB, Area: Cardinal;
begin
iR := 0; iB := iR; iG := iR; iA := iR;
for iy := 1 to Dly do
begin
C:= PRGBA(RowSrc);
for ix := 1 to Dlx do
begin
inc(iB, C.B);
inc(iG, C.G);
inc(iR, C.R);
inc(iA, C.A);
inc(C);
end;
inc(RowSrc, OffSrc);
end;
Area := Dlx * Dly;
Area := $1000000 div Area;
Result := iA * Area and $FF000000 or
iR * Area shr 8 and $FF0000 or
iG * Area shr 16 and $FF00 or
iB * Area shr 24 and $FF;
end;
procedure DraftResample(Dst: TBitmap32; DstRect: TRect; DstClip: TRect;
Src: TBitmap32; SrcRect: TRect; Kernel: TCustomKernel;
CombineOp: TDrawMode; CombineCallBack: TPixelCombineEvent);
var
SrcW, SrcH,
DstW, DstH,
DstClipW, DstClipH: Cardinal;
RowSrc, OffSrc,
dy, dx,
c1, c2, r1, r2,
xs, xsrc, M: Cardinal;
C: TColor32;
DstLine: PColor32Array;
ScaleFactor,lx, fe: TFloat;
FSrcTop,I,J,ly,
sc, sr, cx, cy: integer;
Y_256: TFixed;
BlendMemEx: TBlendMemEx;
begin
{ rangechecking and rect intersection done by caller }
SrcW := SrcRect.Right - SrcRect.Left;
SrcH := SrcRect.Bottom - SrcRect.Top;
DstW := DstRect.Right - DstRect.Left;
DstH := DstRect.Bottom - DstRect.Top;
DstClipW := DstClip.Right - DstClip.Left;
DstClipH := DstClip.Bottom - DstClip.Top;
BlendMemEx := BLEND_MEM_EX[Src.CombineMode];
if (DstW > SrcW)or(DstH > SrcH) then begin
if (SrcW < 2) or (SrcH < 2) then
Resample(Dst, DstRect, DstClip, Src, SrcRect, Kernel, CombineOp,
CombineCallBack)
else
StretchHorzStretchVertLinear(Dst, DstRect, DstClip, Src, SrcRect, CombineOp,
CombineCallBack);
end
else
begin //Full Scaledown, ignores Fulledge - cannot be integrated into this resampling method
OffSrc := Src.Width * 4;
ScaleFactor:= SrcW / DstW;
cx := Trunc( (DstClip.Left - DstRect.Left) * ScaleFactor);
r2 := Trunc(ScaleFactor);
sr := Trunc( $10000 * ScaleFactor );
ScaleFactor:= SrcH / DstH;
cy := Trunc( (DstClip.Top - DstRect.Top) * ScaleFactor);
c2 := Trunc(ScaleFactor);
sc := Trunc( $10000 * ScaleFactor );
DstLine := PColor32Array(Dst.PixelPtr[0, DstClip.Top]);
RowSrc := Cardinal(Src.PixelPtr[ SrcRect.Left + cx, SrcRect.Top + cy ]);
xs := r2;
c1 := 0;
Dec(DstClip.Left, 2);
Inc(DstClipW);
Inc(DstClipH);
for J := 2 to DstClipH do
begin
dy := c2 - c1;
c1 := c2;
c2 := J * sc shr 16;
r1 := 0;
r2 := xs;
xsrc := RowSrc;
case CombineOp of
dmOpaque:
for I := 2 to DstClipW do
begin
dx := r2 - r1; r1 := r2;
r2 := I * sr shr 16;
DstLine[DstClip.Left + I] := BlockAverage(dx, dy, xsrc, OffSrc);
xsrc := xsrc + dx shl 2;
end;
dmBlend:
for I := 2 to DstClipW do
begin
dx := r2 - r1; r1 := r2;
r2 := I * sr shr 16;
BlendMemEx(BlockAverage(dx, dy, xsrc, OffSrc), DstLine[DstClip.Left + I], Src.MasterAlpha);
xsrc := xsrc + dx shl 2;
end;
dmTransparent:
for I := 2 to DstClipW do
begin
dx := r2 - r1; r1 := r2;
r2 := I * sr shr 16;
C := BlockAverage(dx, dy, xsrc, OffSrc);
if C <> Src.OuterColor then DstLine[DstClip.Left + I] := C;
xsrc := xsrc + dx shl 2;
end;
dmCustom:
for I := 2 to DstClipW do
begin
dx := r2 - r1; r1 := r2;
r2 := I * sr shr 16;
CombineCallBack(BlockAverage(dx, dy, xsrc, OffSrc), DstLine[DstClip.Left + I], Src.MasterAlpha);
xsrc := xsrc + dx shl 2;
end;
end;
Inc(DstLine, Dst.Width);
Inc(RowSrc, OffSrc * dy);
end;
end;
EMMS;
end;
{ Special interpolators (for sfLinear and sfDraft) }
function M_LinearInterpolator(PWX_256, PWY_256: Cardinal; C11, C21: PColor32): TColor32;
asm
db $0F,$6F,$09 /// MOVQ MM1,[ECX]
db $0F,$6F,$D1 /// MOVQ MM2,MM1
MOV ECX,C21
db $0F,$6F,$19 /// MOVQ MM3,[ECX]
db $0F,$73,$D1,$20 /// PSRLQ MM1,32
db $0F,$6F,$E3 /// MOVQ MM4,MM3
db $0F,$73,$D3,$20 /// PSRLQ MM3,32
db $0F,$6E,$E8 /// MOVD MM5,EAX
db $0F,$62,$ED /// PUNPCKLDQ MM5,MM5
db $0F,$EF,$C0 /// PXOR MM0, MM0
db $0F,$60,$C8 /// PUNPCKLBW MM1,MM0
db $0F,$60,$D0 /// PUNPCKLBW MM2,MM0
db $0F,$F9,$D1 /// PSUBW MM2,MM1
db $0F,$D5,$D5 /// PMULLW MM2,MM5
db $0F,$71,$F1,$08 /// PSLLW MM1,8
db $0F,$FD,$D1 /// PADDW MM2,MM1
db $0F,$71,$D2,$08 /// PSRLW MM2,8
db $0F,$60,$D8 /// PUNPCKLBW MM3,MM0
db $0F,$60,$E0 /// PUNPCKLBW MM4,MM0
db $0F,$F9,$E3 /// PSUBW MM4,MM3
db $0F,$71,$F3,$08 /// PSLLW MM3,8
db $0F,$D5,$E5 /// PMULLW MM4,MM5
db $0F,$FD,$E3 /// PADDW MM4,MM3
db $0F,$71,$D4,$08 /// PSRLW MM4,8
db $0F,$6E,$EA /// MOVD MM5,EDX
db $0F,$62,$ED /// PUNPCKLDQ MM5,MM5
db $0F,$F9,$D4 /// PSUBW MM2,MM4
db $0F,$D5,$D5 /// PMULLW MM2,MM5
db $0F,$71,$F4,$08 /// PSLLW MM4,8
db $0F,$FD,$D4 /// PADDW MM2,MM4
db $0F,$71,$D2,$08 /// PSRLW MM2,8
db $0F,$67,$D0 /// PACKUSWB MM2,MM0
db $0F,$7E,$D0 /// MOVD EAX,MM2
end;
function _Linea
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -