2 Star 1 Fork 0

wyrover/FlatStyle

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
FlatWatet.pas 6.32 KB
一键复制 编辑 原始数据 按行查看 历史
wyrover 提交于 2015-06-17 17:38 . + Init FlatStyle
unit FlatWatet;
interface
{$I FlatStyle.inc}
uses
Windows, SysUtils, Graphics, Math;
const
csDefDamping = 20;
RAND_MAX = $7FFF;
type
PIntArray = ^TIntArray;
TIntArray = array[0..65535] of Integer;
PPIntArray = ^TPIntArray;
TPIntArray = array[0..65535] of PIntArray;
PRGBArray = ^TRGBArray;
TRGBArray = array[0..65535] of TRGBTriple;
PPRGBArray = ^TPRGBArray;
TPRGBArray = array[0..65535] of PRGBArray;
TWaterDamping = 1..99;
TDefineWatet = class(TObject)
private
FWaterWidth: Integer;
FWaterHeight: Integer;
FWaterBuff1: Pointer;
FWaterBuff2: Pointer;
FScanLine1: PPIntArray;
FScanLine2: PPIntArray;
FScanLineSrc: PPRGBArray;
FDamping: TWaterDamping;
protected
procedure CalcWater;
procedure SetDamping(Value: TWaterDamping);
procedure ClearWater;
public
constructor Create;
destructor Destroy; override;
procedure SetSize(Bitmap: TBitmap);
procedure Render(Src, Dst: TBitmap);
procedure Blob(x, y: Integer; ARadius, AHeight: Integer);
property Damping: TWaterDamping read FDamping write SetDamping;
end;
implementation
{ TWater }
procedure TDefineWatet.Blob(x, y, ARadius, AHeight: Integer);
var
Rquad: Integer;
cx, cy, cyq: Integer;
WaterLeft, WaterTop, WaterRight, WaterBottom: Integer;
begin
if (x < 0) or (x > FWaterWidth - 1) then
x := 1 + ARadius + Random(RAND_MAX) mod (FWaterWidth - 2 * ARadius - 1);
if (y < 0) or (y > FWaterHeight - 1) then
y := 1 + ARadius + Random(RAND_MAX) mod (FWaterHeight - 2 * ARadius - 1);
WaterLeft := -Min(x, ARadius);
WaterRight := Min(FWaterWidth - 1 - x, ARadius);
WaterTop := -Min(y, ARadius);
WaterBottom := Min(FWaterHeight - 1 - y, ARadius);
Rquad := ARadius * ARadius;
for cy := WaterTop to WaterBottom do
begin
cyq := cy * cy;
for cx := WaterLeft to WaterRight do
begin
if (cx * cx + cyq <= Rquad) then
begin
Inc(FScanLine1[cy + y][cx + x], AHeight);
end;
end;
end;
end;
procedure TDefineWatet.CalcWater;
var
x, y, xl, xr: Integer;
NewH: Integer;
P, P1, P2, P3: PIntArray;
PT: Pointer;
Rate: Integer;
begin
Rate := (100 - FDamping) * 256 div 100;
for y := 0 to FWaterHeight - 1 do
begin
P := FScanLine2[y];
P1 := FScanLine1[Max(y - 1, 0)];
P2 := FScanLine1[y];
P3 := FScanLine1[Min(y + 1, FWaterHeight - 1)];
for x := 0 to FWaterWidth - 1 do
begin
xl := Max(x - 1, 0);
xr := Min(x + 1, FWaterWidth - 1);
NewH := (P1[xl] + P1[x] + P1[xr] + P2[xl] + P2[xr] + P3[xl] + P3[x] + P3[xr]) div 4 - P[x];
P[x] := NewH * Rate div 256;
end;
end;
PT := FWaterBuff1;
FWaterBuff1 := FWaterBuff2;
FWaterBuff2 := PT;
PT := FScanLine1;
FScanLine1 := FScanLine2;
FScanLine2 := PT;
end;
procedure TDefineWatet.ClearWater;
begin
if FWaterBuff1 <> nil then
ZeroMemory(FWaterBuff1, (FWaterWidth * FWaterHeight) * SizeOf(Integer));
if FWaterBuff2 <> nil then
ZeroMemory(FWaterBuff2, (FWaterWidth * FWaterHeight) * SizeOf(Integer));
end;
constructor TDefineWatet.Create;
begin
inherited;
FDamping := csDefDamping;
end;
destructor TDefineWatet.Destroy;
begin
if FWaterBuff1 <> nil then
FreeMem(FWaterBuff1);
if FWaterBuff2 <> nil then
FreeMem(FWaterBuff2);
if FScanLine1 <> nil then
FreeMem(FScanLine1);
if FScanLine2 <> nil then
FreeMem(FScanLine2);
if FScanLineSrc <> nil then
FreeMem(FScanLineSrc);
inherited Destroy;
end;
procedure TDefineWatet.Render(Src, Dst: TBitmap);
var
dx, dy: Integer;
i, c, x, y: Integer;
P1, P2, P3: PIntArray;
PSrc, PDst: PRGBArray;
PSrcDot, PDstDot: PRGBTriple;
BytesPerLine1, BytesPerLine2: Integer;
begin
CalcWater;
Src.PixelFormat := pf24bit;
Dst.PixelFormat := pf24bit;
FScanLineSrc[0] := Src.ScanLine[0];
BytesPerLine1 := Integer(Src.ScanLine[1]) - Integer(FScanLineSrc[0]);
for i := 1 to FWaterHeight - 1 do
FScanLineSrc[i] := PRGBArray(Integer(FScanLineSrc[i - 1]) + BytesPerLine1);
PDst := Dst.ScanLine[0];
BytesPerLine2 := Integer(Dst.ScanLine[1]) - Integer(PDst);
for y := 0 to FWaterHeight - 1 do
begin
PSrc := FScanLineSrc[y];
P1 := FScanLine1[Max(y - 1, 0)];
P2 := FScanLine1[y];
P3 := FScanLine1[Min(y + 1, FWaterHeight - 1)];
for x := 0 to FWaterWidth - 1 do
begin
dx := P2[Max(x - 1, 0)] - P2[Min(x + 1, FWaterWidth - 1)];
dy := P1[x] - P3[x];
if (x + dx >= 0) and (x + dx < FWaterWidth) and (y + dy >= 0) and
(y + dy < FWaterHeight) then
begin
PSrcDot := @FScanLineSrc[y + dy][x + dx];
PDstDot := @PDst[x];
c := PSrcDot.rgbtBlue - dx;
if c < 0 then
PDstDot.rgbtBlue := 0
else if c > 255 then
PDstDot.rgbtBlue := 255
else
PDstDot.rgbtBlue := c;
c := PSrcDot.rgbtGreen - dx;
if c < 0 then
PDstDot.rgbtGreen := 0
else if c > 255 then
PDstDot.rgbtGreen := 255
else
PDstDot.rgbtGreen := c;
c := PSrcDot.rgbtRed - dx;
if c < 0 then
PDstDot.rgbtRed := 0
else if c > 255 then
PDstDot.rgbtRed := 255
else
PDstDot.rgbtRed := c;
end
else
begin
PDst[x] := PSrc[x];
end;
end;
PDst := PRGBArray(Integer(PDst) + BytesPerLine2);
end;
end;
procedure TDefineWatet.SetDamping(Value: TWaterDamping);
begin
if (Value >= Low(TWaterDamping)) and (Value <= High(TWaterDamping)) then
FDamping := Value;
end;
procedure TDefineWatet.SetSize;
var
i: Integer;
begin
FWaterWidth := Bitmap.Width;
FWaterHeight := Bitmap.Height;
if (FWaterWidth <= 0) or (FWaterHeight <= 0) then
begin
FWaterWidth := 0;
FWaterHeight := 0;
end;
ReallocMem(FWaterBuff1, FWaterWidth * FWaterHeight * SizeOf(Integer));
ReallocMem(FWaterBuff2, FWaterWidth * FWaterHeight * SizeOf(Integer));
ReallocMem(FScanLine1, FWaterHeight * SizeOf(PIntArray));
ReallocMem(FScanLine2, FWaterHeight * SizeOf(PIntArray));
ReallocMem(FScanLineSrc, FWaterHeight * SizeOf(PRGBArray));
ClearWater;
if (FWaterHeight > 0)and(FWaterWidth > 0) then
begin
FScanLine1[0] := FWaterBuff1;
FScanLine2[0] := FWaterBuff2;
for i := 1 to FWaterHeight - 1 do
begin
FScanLine1[i] := @FScanLine1[i - 1][FWaterWidth];
FScanLine2[i] := @FScanLine2[i - 1][FWaterWidth];
end;
end;
end;
end.
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Pascal
1
https://gitee.com/wyrover/FlatStyle.git
git@gitee.com:wyrover/FlatStyle.git
wyrover
FlatStyle
FlatStyle
master

搜索帮助