首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

GDI+ 進階 (100):TGPImage 顏色替換——ColorMap + ImageAttributes 實戰

     編輯:Delphi

目標

使用 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.

關鍵技術細節

1. TColorMap 使用 ARGB 32 位整數

  • ColorRefToARGB(TColor):將 Delphi TColor (BBGGRR) 轉 GDI+ ARGB (AARRGGBB)。
  • ARGBToColorRef(ARGB):反向轉換。
  • Alpha 通道默認 255 (不透明),若需半透明替換手動構造 MakeColor(Alpha, R, G, B)。

2. DrawImage 多參數重載:必須傳 ImageAttributes


Gr.DrawImage(Img, DestRect, SrcX, SrcY, SrcW, SrcH, UnitPixel, ImgAttr);
// 只有帶 ImageAttributes 參數的重載才會應用 ColorMap

3. 替換表可包含多組映射


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); // 一次性替換三種顏色

4. ClearRemapTable 瞬間恢復

不需重新載入圖片,屬於繪製時屬性,清除後下次 DrawImage 顯示原始像素。

應用場景

  1. 主題換膚:UI 圖標單色替換,無需準備多套素材。
  2. 圖片去水印/紅眼修正:針對性替換特定顏色區域。
  3. 色盲模式模擬:紅綠色盲顏色映射表。
  4. 打印墨水優化:將深色背景替換為白色節省墨粉。

總結

GDI+ 顏色替換核心:**TColorMap 定義新舊 ARGB 映射 → TGPImageAttributes.SetRemapTable 應用 → DrawImage(..., ImgAttr) 繪製時生效 → ClearRemapTable 撤銷**。無需修改像素數據,繪製管道級處理,性能極高,支援動態交互式替換。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved