所有特效基於同一模式:
TImage 載入原始圖片作為緩衝區TBitmap 作為動態合成目標Canvas.CopyRect 將來源畫布矩形區域複製到目標畫布對應區域Form.Canvas.Draw 顯示,形成動畫原理:逐行從源圖頂部複製到目標圖底部,視覺上圖片從下方推入。
procedure TForm1.BtnPullUpClick(Sender: TObject);
var
Bmp: TBitmap; I, H, W: Integer;
begin
Bmp := TBitmap.Create;
try
Bmp.Width := Image1.Width; Bmp.Height := Image1.Height;
H := Image1.Height; W := Image1.Width;
for I := 0 to H do
begin
Bmp.Canvas.CopyRect(Rect(0, H-I, W, H),
Image1.Canvas, Rect(0, 0, W, I));
Canvas.Draw(120, 100, Bmp);
Application.ProcessMessages; // 讓 UI 更新
end;
finally Bmp.Free; end;
end;
下拉、左拉、右拉同理調整 Rect 參數。
原理:奇數掃描線從上往下、偶數掃描線從下往上同步複製,雙向匯聚。
procedure TForm1.BtnVInterlaceClick(Sender: TObject);
var
Bmp: TBitmap; I, J, H, W: Integer;
begin
Bmp := TBitmap.Create;
try
Bmp.SetSize(Image1.Width, Image1.Height);
H := Image1.Height; W := Image1.Width;
I := 0;
while I <= H do
begin
J := I;
while J > 0 do
begin
// 奇數線:從下往上
Bmp.Canvas.CopyRect(Rect(0, J-1, W, J),
Image1.Canvas, Rect(0, H-I+J-1, W, H-I+J));
// 偶數線:從上往下
Bmp.Canvas.CopyRect(Rect(0, H-J, W, H-J+1),
Image1.Canvas, Rect(0, I-J, W, I-J+1));
Dec(J, 2);
end;
Canvas.Draw(120, 100, Bmp);
Application.ProcessMessages;
Inc(I, 2);
end;
finally Bmp.Free; end;
end;
原理:同垂直交錯,改為左右兩側向中間匯聚。
procedure TForm1.BtnHInterlaceClick(Sender: TObject);
var
Bmp: TBitmap; I, J, H, W: Integer;
begin
Bmp := TBitmap.Create;
try
Bmp.SetSize(Image1.Width, Image1.Height);
H := Image1.Height; W := Image1.Width;
I := 0;
while I <= W do
begin
J := I;
while J > 0 do
begin
Bmp.Canvas.CopyRect(Rect(J-1, 0, J, H),
Image1.Canvas, Rect(W-I+J-1, 0, W-I+J, H));
Bmp.Canvas.CopyRect(Rect(W-J, 0, W-J+1, H),
Image1.Canvas, Rect(I-J, 0, I-J+1, H));
Dec(J, 2);
end;
Canvas.Draw(120, 100, Bmp);
Application.ProcessMessages;
Inc(I, 2);
end;
finally Bmp.Free; end;
end;
原理:從底部向上,每一條掃描線依序「掃過」畫面頂端到當前位置,留下軌跡。
procedure TForm1.BtnRainClick(Sender: TObject);
var
Bmp: TBitmap; I, J, H, W: Integer;
begin
Bmp := TBitmap.Create;
try
Bmp.SetSize(Image1.Width, Image1.Height);
H := Image1.Height; W := Image1.Width;
for I := H downto 1 do
for J := 1 to I do
begin
Bmp.Canvas.CopyRect(Rect(0, J-1, W, J),
Image1.Canvas, Rect(0, I-1, W, I));
Canvas.Draw(120, 100, Bmp);
Application.ProcessMessages;
end;
finally Bmp.Free; end;
end;
原理:將圖片分 N 組(預設 16 組),每組內部逐行依序顯示,組與組平行推進。
procedure TForm1.BtnBlindClick(Sender: TObject);
var
Bmp: TBitmap; I, J, H, W, Groups, RowsPerGroup: Integer;
begin
Bmp := TBitmap.Create;
try
Bmp.SetSize(Image1.Width, Image1.Height);
H := Image1.Height; W := Image1.Width;
Groups := 16;
RowsPerGroup := H div Groups;
for I := 0 to RowsPerGroup do
for J := 0 to Groups - 1 do
begin
Bmp.Canvas.CopyRect(Rect(0, RowsPerGroup*J+I-1, W, RowsPerGroup*J+I),
Image1.Canvas, Rect(0, RowsPerGroup*J+I-1, W, RowsPerGroup*J+I));
Canvas.Draw(120, 100, Bmp);
Application.ProcessMessages;
end;
finally Bmp.Free; end;
end;
原理:每次複製一塊矩形區塊(預設高 10 像素),而非單行。
procedure TForm1.BtnBlockClick(Sender: TObject);
var
Bmp: TBitmap; I, J, H, W, BlockH: Integer;
begin
Bmp := TBitmap.Create;
try
Bmp.SetSize(Image1.Width, Image1.Height);
H := Image1.Height; W := Image1.Width;
BlockH := 10;
I := H;
while I > 0 do
begin
for J := BlockH to I do
begin
Bmp.Canvas.CopyRect(Rect(0, J-BlockH, W, J),
Image1.Canvas, Rect(0, I-BlockH, W, I));
Canvas.Draw(120, 100, Bmp);
Application.ProcessMessages;
end;
Dec(I, BlockH);
end;
finally Bmp.Free; end;
end;
TBitmap 合成完畢後一次 BitBlt 到螢幕,減少閃爍TTimer 或執行緒,避免阻塞主執行緒try..finally Bmp.Free 確保記憶體不洩漏原文驗證環境:Delphi 3.0、Pentium 100MHz 相容機,效果流暢。現代硬體可支援更高解析度與幀率。
TRegex 支援的完整元字符、量詞、斷言與 Unicode 分類
Delphi 2005 ASP.NET 開發環境搭建避坑實錄:從 IIS 到 Cassini 的血淚歷程
WinAPI 鉤子回調:HardwareProc 詳細解析
致 Delphi 與 C++Builder 社群的一封公開信:Borland RAD 團隊的承諾與願景
Delphi 2009 容器類簡介(二):TList 存儲記錄指標完整測試代碼