使用 TGPImageAttributes.SetRemapTable 配合 TColorMap 陣列,實現圖片中指定顏色的動態替換(如將紅色換為藍色),並支援撤銷恢復原圖。
| 類型 | 作用 |
|---|---|
TColorMap | 記錄 oldColor、newColor (ARGB 32位) |
TGPImageAttributes | 攜帶重映射表、色彩矩陣、閾值等繪圖屬性 |
SetRemapTable(Count, PColorMap) | 設置顏色替換表 |
ClearRemapTable | 清除替換表,恢復原色 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
btnPick: TButton; // 實際用滑鼠點擊拾取,這裡用 ColorDialog 模擬
btnReplace: TButton;
btnReset: TButton;
ColorDialog1: TColorDialog;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure btnReplaceClick(Sender: TObject);
procedure btnResetClick(Sender: TObject);
private
FOldColor, FNewColor: TColor;
FHasPick: Boolean;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses GDIPOBJ, GDIPAPI;
var
GImg: TGPImage;
ImgAttr: TGPImageAttributes;
ColorMap: array[0..0] of TColorMap; // 單顏色替換
procedure TForm1.FormCreate(Sender: TObject);
begin
GImg := TGPImage.Create('c:\temp\test.png'); // 需預先準備測試圖
ClientWidth := GImg.GetWidth + 20;
ClientHeight := GImg.GetHeight + 60;
ImgAttr := TGPImageAttributes.Create;
ColorMap[0].oldColor := 0;
ColorMap[0].newColor := 0;
btnPick.Caption := '拾取顏色 (點擊圖片)';
btnReplace.Caption := '替換為新顏色';
btnReset.Caption := '恢復原圖';
btnReplace.Enabled := False;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
GImg.Free;
ImgAttr.Free;
end;
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
C: TColor;
begin
if (X < 10) or (X >= 10 + GImg.GetWidth) or (Y < 10) or (Y >= 10 + GImg.GetHeight) then Exit;
// 從屏幕座標轉圖片座標並 GetPixel (簡化演示)
C := GetPixel(Canvas.Handle, X, Y);
FOldColor := C;
ColorMap[0].oldColor := ColorRefToARGB(C);
btnPick.Caption := Format('已拾取: $%.6x', [C]);
btnReplace.Enabled := True;
end;
procedure TForm1.FormPaint(Sender: TObject);
var
Gr: TGPGraphics;
begin
Gr := TGPGraphics.Create(Canvas.Handle);
try
Gr.DrawImage(GImg,
MakeRect(10, 10, GImg.GetWidth, GImg.GetHeight), // 目標矩形
0, 0, GImg.GetWidth, GImg.GetHeight, UnitPixel, // 源矩形
ImgAttr); // 關鍵:傳入 ImageAttributes
finally
Gr.Free;
end;
end;
procedure TForm1.btnReplaceClick(Sender: TObject);
begin
if ColorDialog1.Execute then
begin
FNewColor := ColorDialog1.Color;
ColorMap[0].newColor := ColorRefToARGB(FNewColor);
ImgAttr.SetRemapTable(1, @ColorMap); // 應用替換表
btnReplace.Caption := Format('已替換為: $%.6x', [FNewColor]);
Invalidate;
end;
end;
procedure TForm1.btnResetClick(Sender: TObject);
begin
ImgAttr.ClearRemapTable; // 清除替換
btnPick.Caption := '拾取顏色 (點擊圖片)';
btnReplace.Caption := '替換為新顏色';
btnReplace.Enabled := False;
Invalidate;
end;
end.
TColorMap 使用 ARGB 32 位整數ColorRefToARGB(TColor):將 Delphi TColor (BBGGRR) 轉 GDI+ ARGB (AARRGGBB)。ARGBToColorRef(ARGB):反向轉換。MakeColor(Alpha, R, G, B)。DrawImage 多參數重載:必須傳 ImageAttributes
Gr.DrawImage(Img, DestRect, SrcX, SrcY, SrcW, SrcH, UnitPixel, ImgAttr);
// 只有帶 ImageAttributes 參數的重載才會應用 ColorMap
var Map: array[0..2] of TColorMap;
Map[0] := (oldColor: RedARGB; newColor: BlueARGB);
Map[1] := (oldColor: GreenARGB; newColor: YellowARGB);
Map[2] := (oldColor: BlackARGB; newColor: WhiteARGB);
ImgAttr.SetRemapTable(3, @Map); // 一次性替換三種顏色
ClearRemapTable 瞬間恢復不需重新載入圖片,屬於繪製時屬性,清除後下次 DrawImage 顯示原始像素。
GDI+ 顏色替換核心:**TColorMap 定義新舊 ARGB 映射 → TGPImageAttributes.SetRemapTable 應用 → DrawImage(..., ImgAttr) 繪製時生效 → ClearRemapTable 撤銷**。無需修改像素數據,繪製管道級處理,性能極高,支援動態交互式替換。