📄 gr32_resamplers.pas
字号:
public
function GetSampleInt(X, Y: Integer): TColor32; override;
function GetSampleFixed(X, Y: TFixed): TColor32; override;
function GetSampleFloat(X, Y: TFloat): TColor32; override;
end;
{ TSuperSampler }
TSamplingRange = 1..MaxInt;
TSuperSampler = class(TNestedSampler)
private
FSamplingY: TSamplingRange;
FSamplingX: TSamplingRange;
FDistanceX: TFixed;
FDistanceY: TFixed;
FOffsetX: TFixed;
FOffsetY: TFixed;
FScale: TFixed;
procedure SetSamplingX(const Value: TSamplingRange);
procedure SetSamplingY(const Value: TSamplingRange);
public
constructor Create(Sampler: TCustomSampler); override;
function GetSampleFixed(X, Y: TFixed): TColor32; override;
published
property SamplingX: TSamplingRange read FSamplingX write SetSamplingX;
property SamplingY: TSamplingRange read FSamplingY write SetSamplingY;
end;
{ TAdaptiveSuperSampler }
TRecurseProc = function(X, Y, W: TFixed; const C1, C2: TColor32): TColor32 of object;
TAdaptiveSuperSampler = class(TNestedSampler)
private
FMinOffset: TFixed;
FLevel: Integer;
FTolerance: Integer;
procedure SetLevel(const Value: Integer);
function DoRecurse(X, Y, Offset: TFixed; const A, B, C, D, E: TColor32): TColor32;
function QuadrantColor(const C1, C2: TColor32; X, Y, Offset: TFixed;
Proc: TRecurseProc): TColor32;
function RecurseAC(X, Y, Offset: TFixed; const A, C: TColor32): TColor32;
function RecurseBD(X, Y, Offset: TFixed; const B, D: TColor32): TColor32;
protected
function CompareColors(C1, C2: TColor32): Boolean; virtual;
public
constructor Create(Sampler: TCustomSampler); override;
function GetSampleFixed(X, Y: TFixed): TColor32; override;
published
property Level: Integer read FLevel write SetLevel;
property Tolerance: Integer read FTolerance write FTolerance;
end;
{ TPatternSampler }
TFloatSamplePattern = array of array of TArrayOfFloatPoint;
TFixedSamplePattern = array of array of TArrayOfFixedPoint;
TPatternSampler = class(TNestedSampler)
private
FPattern: TFixedSamplePattern;
FPatternWidth: Integer;
FPatternHeight: Integer;
procedure SetPattern(const Value: TFixedSamplePattern);
public
destructor Destroy; override;
function GetSampleFixed(X, Y: TFixed): TColor32; override;
property Pattern: TFixedSamplePattern read FPattern write SetPattern;
end;
{ Auxiliary record used in accumulation routines }
PBufferEntry = ^TBufferEntry;
TBufferEntry = record
B, G, R, A: Integer;
end;
{ TKernelSampler }
TKernelSampler = class(TNestedSampler)
private
FKernel: TIntegerMap;
FStartEntry: TBufferEntry;
FCenterX: Integer;
FCenterY: Integer;
protected
procedure UpdateBuffer(var Buffer: TBufferEntry; Color: TColor32;
Weight: Integer); virtual; abstract;
function ConvertBuffer(var Buffer: TBufferEntry): TColor32; virtual;
public
constructor Create(ASampler: TCustomSampler); override;
destructor Destroy; override;
function GetSampleInt(X, Y: Integer): TColor32; override;
function GetSampleFixed(X, Y: TFixed): TColor32; override;
published
property Kernel: TIntegerMap read FKernel write FKernel;
property CenterX: Integer read FCenterX write FCenterX;
property CenterY: Integer read FCenterY write FCenterY;
end;
{ TConvolver }
TConvolver = class(TKernelSampler)
protected
procedure UpdateBuffer(var Buffer: TBufferEntry; Color: TColor32;
Weight: Integer); override;
end;
{ TSelectiveConvolver }
TSelectiveConvolver = class(TConvolver)
private
FRefColor: TColor32;
FDelta: Integer;
FWeightSum: TBufferEntry;
protected
procedure UpdateBuffer(var Buffer: TBufferEntry; Color: TColor32;
Weight: Integer); override;
function ConvertBuffer(var Buffer: TBufferEntry): TColor32; override;
public
constructor Create(ASampler: TCustomSampler); override;
function GetSampleInt(X, Y: Integer): TColor32; override;
function GetSampleFixed(X, Y: TFixed): TColor32; override;
published
property Delta: Integer read FDelta write FDelta;
end;
{ TMorphologicalSampler }
TMorphologicalSampler = class(TKernelSampler)
protected
function ConvertBuffer(var Buffer: TBufferEntry): TColor32; override;
end;
{ TDilater }
TDilater = class(TMorphologicalSampler)
protected
procedure UpdateBuffer(var Buffer: TBufferEntry; Color: TColor32;
Weight: Integer); override;
end;
{ TEroder }
TEroder = class(TMorphologicalSampler)
protected
procedure UpdateBuffer(var Buffer: TBufferEntry; Color: TColor32;
Weight: Integer); override;
public
constructor Create(ASampler: TCustomSampler); override;
end;
{ TExpander }
TExpander = class(TKernelSampler)
protected
procedure UpdateBuffer(var Buffer: TBufferEntry; Color: TColor32;
Weight: Integer); override;
end;
{ TContracter }
TContracter = class(TExpander)
private
FMaxWeight: TColor32;
protected
procedure UpdateBuffer(var Buffer: TBufferEntry; Color: TColor32;
Weight: Integer); override;
public
procedure PrepareSampling; override;
function GetSampleInt(X, Y: Integer): TColor32; override;
function GetSampleFixed(X, Y: TFixed): TColor32; override;
end;
function CreateJitteredPattern(TileWidth, TileHeight, SamplesX, SamplesY: Integer): TFixedSamplePattern;
{ Convolution and morphological routines }
procedure Convolve(Src, Dst: TBitmap32; Kernel: TIntegerMap; CenterX, CenterY: Integer);
procedure Dilate(Src, Dst: TBitmap32; Kernel: TIntegerMap; CenterX, CenterY: Integer);
procedure Erode(Src, Dst: TBitmap32; Kernel: TIntegerMap; CenterX, CenterY: Integer);
procedure Expand(Src, Dst: TBitmap32; Kernel: TIntegerMap; CenterX, CenterY: Integer);
procedure Contract(Src, Dst: TBitmap32; Kernel: TIntegerMap; CenterX, CenterY: Integer);
{ Auxiliary routines for accumulating colors in a buffer }
procedure IncBuffer(var Buffer: TBufferEntry; Color: TColor32); {$IFDEF USEINLINING} inline; {$ENDIF}
procedure MultiplyBuffer(var Buffer: TBufferEntry; W: Integer); {$IFDEF USEINLINING} inline; {$ENDIF}
function BufferToColor32(Buffer: TBufferEntry; Shift: Integer): TColor32; {$IFDEF USEINLINING} inline; {$ENDIF}
procedure ShrBuffer(var Buffer: TBufferEntry; Shift: Integer); {$IFDEF USEINLINING} inline; {$ENDIF}
{ Registration routines }
procedure RegisterResampler(ResamplerClass: TCustomResamplerClass);
procedure RegisterKernel(KernelClass: TCustomKernelClass);
var
KernelList: TClassList;
ResamplerList: TClassList;
const
EMPTY_ENTRY: TBufferEntry = (B: 0; G: 0; R: 0; A: 0);
implementation
uses
GR32_LowLevel, GR32_System, GR32_Rasterizers, GR32_Math, Math;
var
BlockAverage: function (Dlx, Dly, RowSrc, OffSrc: Cardinal): TColor32;
LinearInterpolator: function(PWX_256, PWY_256: Cardinal; C11, C21: PColor32): TColor32;
const
SDstNil = 'Destination bitmap is nil';
SSrcNil = 'Source bitmap is nil';
SSrcInvalid = 'Source rectangle is invalid';
SSamplerNil = 'Nested sampler is nil';
type
TTransformationAccess = class(TTransformation);
TBitmap32Access = class(TBitmap32);
TCustomResamplerAccess = class(TCustomResampler);
TPointRec = record
Pos: Integer;
Weight: Cardinal;
end;
TCluster = array of TPointRec;
TMappingTable = array of TCluster;
type
TKernelSamplerClass = class of TKernelSampler;
{ Auxiliary rasterization routine for kernel-based samplers }
procedure RasterizeKernelSampler(Src, Dst: TBitmap32; Kernel: TIntegerMap;
CenterX, CenterY: Integer; SamplerClass: TKernelSamplerClass);
var
Sampler: TKernelSampler;
Rasterizer: TRasterizer;
begin
Rasterizer := DefaultRasterizerClass.Create;
try
Dst.SetSizeFrom(Src);
Sampler := SamplerClass.Create(Src.Resampler);
Sampler.Kernel := Kernel;
try
Rasterizer.Sampler := Sampler;
Rasterizer.Rasterize(Dst);
finally
Sampler.Free;
end;
finally
Rasterizer.Free;
end;
end;
procedure Convolve(Src, Dst: TBitmap32; Kernel: TIntegerMap; CenterX, CenterY: Integer);
begin
RasterizeKernelSampler(Src, Dst, Kernel, CenterX, CenterY, TConvolver);
end;
procedure Dilate(Src, Dst: TBitmap32; Kernel: TIntegerMap; CenterX, CenterY: Integer);
begin
RasterizeKernelSampler(Src, Dst, Kernel, CenterX, CenterY, TDilater);
end;
procedure Erode(Src, Dst: TBitmap32; Kernel: TIntegerMap; CenterX, CenterY: Integer);
begin
RasterizeKernelSampler(Src, Dst, Kernel, CenterX, CenterY, TEroder);
end;
procedure Expand(Src, Dst: TBitmap32; Kernel: TIntegerMap; CenterX, CenterY: Integer);
begin
RasterizeKernelSampler(Src, Dst, Kernel, CenterX, CenterY, TExpander);
end;
procedure Contract(Src, Dst: TBitmap32; Kernel: TIntegerMap; CenterX, CenterY: Integer);
begin
RasterizeKernelSampler(Src, Dst, Kernel, CenterX, CenterY, TContracter);
end;
{ Auxiliary routines }
procedure IncBuffer(var Buffer: TBufferEntry; Color: TColor32);
begin
with TColor32Entry(Color) do
begin
Inc(Buffer.B, B);
Inc(Buffer.G, G);
Inc(Buffer.R, R);
Inc(Buffer.A, A);
end;
end;
procedure MultiplyBuffer(var Buffer: TBufferEntry; W: Integer);
begin
Buffer.B := Buffer.B * W;
Buffer.G := Buffer.G * W;
Buffer.R := Buffer.R * W;
Buffer.A := Buffer.A * W;
end;
procedure ShrBuffer(var Buffer: TBufferEntry; Shift: Integer);
begin
Buffer.B := Buffer.B shr Shift;
Buffer.G := Buffer.G shr Shift;
Buffer.R := Buffer.R shr Shift;
Buffer.A := Buffer.A shr Shift;
end;
function BufferToColor32(Buffer: TBufferEntry; Shift: Integer): TColor32;
begin
with TColor32Entry(Result) do
begin
B := Buffer.B shr Shift;
G := Buffer.G shr Shift;
R := Buffer.R shr Shift;
A := Buffer.A shr Shift;
end;
end;
procedure CheckBitmaps(Dst, Src: TBitmap32); {$IFDEF USEINLINING}inline;{$ENDIF}
begin
if not Assigned(Dst) then raise EBitmapException.Create(SDstNil);
if not Assigned(Src) then raise EBitmapException.Create(SSrcNil);
end;
function CheckSrcRect(Src: TBitmap32; const SrcRect: TRect): Boolean;
begin
Result := False;
if IsRectEmpty(SrcRect) then Exit;
if (SrcRect.Left < 0) or (SrcRect.Right > Src.Width) or
(SrcRect.Top < 0) or (SrcRect.Bottom > Src.Height) then
raise ESrcInvalidException.Create(SSrcInvalid);
Result := True;
end;
procedure BlendBlock(
Dst: TBitmap32; DstRect: TRect;
Src: TBitmap32; SrcX, SrcY: Integer;
CombineOp: TDrawMode; CombineCallBack: TPixelCombineEvent);
var
SrcP, DstP: PColor32;
SP, DP: PColor32;
MC: TColor32;
W, I, DstY: Integer;
BlendLine: TBlendLine;
BlendLineEx: TBlendLineEx;
begin
{ Internal routine }
W := DstRect.Right - DstRect.Left;
SrcP := Src.PixelPtr[SrcX, SrcY];
DstP := Dst.PixelPtr[DstRect.Left, DstRect.Top];
case CombineOp of
dmOpaque:
begin
for DstY := DstRect.Top to DstRect.Bottom - 1 do
begin
//Move(SrcP^, DstP^, W shl 2); // for FastCode
MoveLongWord(SrcP^, DstP^, W);
Inc(SrcP, Src.Width);
Inc(DstP, Dst.Width);
end;
end;
dmBlend:
if Src.MasterAlpha >= 255 then
begin
BlendLine := BLEND_LINE[Src.CombineMode];
for DstY := DstRect.Top to DstRect.Bottom - 1 do
begin
BlendLine(SrcP, DstP, W);
Inc(SrcP, Src.Width);
Inc(DstP, Dst.Width);
end
end
else
begin
BlendLineEx := BLEND_LINE_EX[Src.CombineMode];
for DstY := DstRect.Top to DstRect.Bottom - 1 do
begin
BlendLineEx(SrcP, DstP, W, Src.MasterAlpha);
Inc(SrcP, Src.Width);
Inc(DstP, Dst.Width);
end
end;
dmTransparent:
begin
MC := Src.OuterColor;
for DstY := DstRect.Top to DstRect.Bottom - 1 do
begin
SP := SrcP;
DP := DstP;
{ TODO: Write an optimized routine for fast masked transfers. }
for I := 0 to W - 1 do
begin
if MC <> SP^ then DP^ := SP^;
Inc(SP); Inc(DP);
end;
Inc(SrcP, Src.Width);
Inc(DstP, Dst.Width);
end;
end;
else // dmCustom:
begin
for DstY := DstRect.Top to DstRect.Bottom - 1 do
begin
SP := SrcP;
DP := DstP;
for I := 0 to W - 1 do
begin
CombineCallBack(SP^, DP^, Src.MasterAlpha);
Inc(SP); Inc(DP);
end;
Inc(SrcP, Src.Width);
Inc(DstP, Dst.Width);
end;
end;
end;
end;
procedure BlockTransfer(
Dst: TBitmap32; DstX: Integer; DstY: Integer; DstClip: TRect;
Src: TBitmap32; SrcRect: TRect;
CombineOp: TDrawMode; CombineCallBack: TPixelCombineEvent);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -