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

DelphiX 透明色與 Alpha 透明度控制完整指南:TransparentColor、Transparent 屬性與 DrawAlpha 實戰

     編輯:Delphi

核心概念:雙層透明機制

DelphiX 的 TPictureCollectionItem 提供兩層獨立的透明控制機制:

  1. 透明色 (TransparentColor + Transparent := True):將指定顏色的像素視為完全透明 (Alpha=0),實現不規則形狀精靈、去除背景色
  2. 全域 Alpha (DrawAlpha 方法的 Alpha 參數 / Transparent 屬性配合 Draw):對整張圖片應用統一透明度係數 (0-255),實現淡入淡出、半透明疊加

兩者可疊加:FinalAlpha = PixelAlpha * GlobalAlpha / 255

屬性與方法速查表

屬性/方法類型說明預設值
TransparentBoolean啟用/禁用透明色功能True
TransparentColorTColor指定作為透明色的 RGB 值clBlack ($000000)
Draw(..., Alpha)方法參數Draw 方法不直接支援 Alpha,需用 DrawAlpha-
DrawAlpha(Dest, Rect, Pattern, Alpha)方法指定全域 Alpha (0-255) 繪製-
DrawRotateAlpha(..., Alpha)方法旋轉 + Alpha 混合-

完整範例:互動式透明控制演示

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DXDraws, StdCtrls, DXClass;

type
  TForm1 = class(TForm)
    DXDraw1: TDXDraw;
    DXImageList1: TDXImageList;
    CheckBox1: TCheckBox;
    TrackBar1: TTrackBar;
    lblAlpha: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure CheckBox1Click(Sender: TObject);
    procedure TrackBar1Change(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  PicItem: TPictureCollectionItem;

procedure TForm1.FormCreate(Sender: TObject);
const
  ImgPath1 = 'C:\Temp\Transparent.bmp';  // 白色背景測試圖
begin
  DXImageList1.DXDraw := DXDraw1;
  DXDraw1.Align := alClient;
  
  PicItem := TPictureCollectionItem(DXImageList1.Items.Add);
  PicItem.Picture.LoadFromFile(ImgPath1);
  
  // 關鍵:指定透明色為白色 (測試圖背景色)
  PicItem.TransparentColor := $FFFFFF;  // clWhite
  PicItem.Transparent := True;          // 預設即為 True
  
  // TrackBar 設定 Alpha 0-255
  TrackBar1.Min := 0;
  TrackBar1.Max := 255;
  TrackBar1.Position := 255;
  TrackBar1.Align := alBottom;
  TrackBar1.Height := 30;
  
  // CheckBox 控制透明色啟用/禁用
  CheckBox1.Caption := '啟用透明色 (白色背景透明)';
  CheckBox1.Checked := True;
  CheckBox1.Align := alTop;
  CheckBox1.Height := 30;
  
  lblAlpha.Align := alBottom;
  lblAlpha.Height := 25;
  lblAlpha.Alignment := taCenter;
  lblAlpha.Caption := 'Alpha: 255 (不透明)';
end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
  // 切換透明色功能
  PicItem.Transparent := CheckBox1.Checked;
  CheckBox1.Caption := IfThen(CheckBox1.Checked, 
    '啟用透明色 (白色背景透明)', 
    '禁用透明色 (白色背景顯示)');
  
  // 立即重繪
  TrackBar1Change(nil);
end;

procedure TForm1.TrackBar1Change(Sender: TObject);
var
  r: TRect;
begin
  // 計算置中矩形
  r := Rect(
    (DXDraw1.Width - PicItem.Width) div 2,
    (DXDraw1.Height - PicItem.Height) div 2,
    (DXDraw1.Width + PicItem.Width) div 2,
    (DXDraw1.Height + PicItem.Height) div 2
  );
  
  // 紅色背景以便觀察透明效果
  DXDraw1.Surface.Fill($FF0000);  // 紅色
  
  // 核心:DrawAlpha 指定全域透明度
  PicItem.DrawAlpha(DXDraw1.Surface, r, 0, TrackBar1.Position);
  
  DXDraw1.Flip;
  
  // 更新標籤
  lblAlpha.Caption := Format('Alpha: %d (%s)', 
    [TrackBar1.Position, 
     IfThen(TrackBar1.Position = 255, '不透明',
     IfThen(TrackBar1.Position = 0, '全透明', '半透明'))]);
end;

end.

DFM 定義

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'DelphiX 透明色與 Alpha 控制示例'
  ClientHeight = 400
  ClientWidth = 500
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object DXDraw1: TDXDraw
    Left = 0
    Top = 30
    Width = 500
    Height = 315
    Align = alClient
    AutoInitialize = True
    AutoSize = True
    Color = clBlack
    Display.FixedBitCount = False
    Display.FixedRatio = True
    Display.FixedSize = True
    Options = [doAllowReboot, doWaitVBlank, doCenter, do3D, doDirectX7Mode, doHardware, doSelectDriver]
    SurfaceHeight = 315
    SurfaceWidth = 500
    TabOrder = 0
    Traces = <>
  end
  object CheckBox1: TCheckBox
    Left = 0
    Top = 0
    Width = 500
    Height = 30
    Align = alTop
    Caption = 'CheckBox1'
    TabOrder = 1
    OnClick = CheckBox1Click
  end
  object TrackBar1: TTrackBar
    Left = 0
    Top = 345
    Width = 500
    Height = 30
    Align = alBottom
    Max = 255
    Min = 0
    Position = 255
    TabOrder = 2
    OnChange = TrackBar1Change
  end
  object lblAlpha: TLabel
    Left = 0
    Top = 375
    Width = 500
    Height = 25
    Align = alBottom
    Alignment = taCenter
    Caption = 'Alpha: 255'
    TabOrder = 3
  end
  object DXImageList1: TDXImageList
    Left = 40
    Top = 40
  end
end

透明色選擇最佳實踐

背景顏色TransparentColor 設定適用格式注意事項
純白clWhite / $FFFFFFBMP, JPG最常見,但圖片內容若含白色會誤透明
品紅/洋紅clFuchsia / $FF00FFBMP, PNG遊戲開發標準透明色,極少用於圖片內容
純黑clBlack / $000000BMP預設值,但深色內容易衝突
自定義任意 RGB所有需確保該色不出現在圖片有效內容中

進階技巧:透明色自動檢測

function DetectTransparentColor(Pic: TPicture; SampleCorners: Boolean = True): TColor;
var
  Bmp: TBitmap;
  Colors: array[0..3] of TColor;
  i: Integer;
  ColorCount: TDictionary;
  MostCommon: TColor;
  MaxCount: Integer;
begin
  Result := clNone;
  Bmp := TBitmap.Create;
  try
    Bmp.Assign(Pic.Graphic);
    Bmp.PixelFormat := pf24bit;  // 確保 24位
    
    ColorCount := TDictionary.Create;
    try
      if SampleCorners then
      begin
        // 採樣四個角落 (各 5x5 區域)
        Colors[0] := Bmp.Canvas.Pixels[0, 0];
        Colors[1] := Bmp.Canvas.Pixels[Bmp.Width-1, 0];
        Colors[2] := Bmp.Canvas.Pixels[0, Bmp.Height-1];
        Colors[3] := Bmp.Canvas.Pixels[Bmp.Width-1, Bmp.Height-1];
        
        // 統計最常見顏色
        for i := 0 to 3 do
        begin
          if ColorCount.ContainsKey(Colors[i]) then
            ColorCount[Colors[i]] := ColorCount[Colors[i]] + 1
          else
            ColorCount[Colors[i]] := 1;
        end;
        
        MaxCount := 0;
        for MostCommon in ColorCount.Keys do
        begin
          if ColorCount[MostCommon] > MaxCount then
          begin
            MaxCount := ColorCount[MostCommon];
            Result := MostCommon;
          end;
        end;
      end
      else
      begin
        // 全圖掃描 (較慢),取邊緣像素最多的顏色
        // ... 省略實現
      end;
    finally
      ColorCount.Free;
    end;
  finally
    Bmp.Free;
  end;
end;

// 使用範例
PicItem.TransparentColor := DetectTransparentColor(PicItem.Picture);
PicItem.Transparent := (PicItem.TransparentColor <> clNone);

Alpha 混合數學原理

// 每像素計算 (預乘 Alpha 模式)
Src:  (Rs, Gs, Bs, As)  // As = 0 (透明色) 或 255 (不透明) 或圖片原始 Alpha
Dst:  (Rd, Gd, Bd, Ad)  // 目標表面像素
GlobalAlpha: Ga (0-255, 來自 DrawAlpha 參數)

// 有效 Alpha
EffectiveAlpha = (As * Ga) div 255

// 混合公式
R = (Rs * EffectiveAlpha + Rd * (255 - EffectiveAlpha)) div 255
G = (Gs * EffectiveAlpha + Gd * (255 - EffectiveAlpha)) div 255
B = (Bs * EffectiveAlpha + Bd * (255 - EffectiveAlpha)) div 255

// 特例:
// - 透明色像素:As = 0 → EffectiveAlpha = 0 → 完全顯示背景
// - 不透明像素 + Ga=255:EffectiveAlpha = 255 → 完全覆蓋
// - 不透明像素 + Ga=128:EffectiveAlpha = 128 → 50% 混合

動畫應用:淡入淡出與交叉淡化

type
  TFadeMode = (fmFadeIn, fmFadeOut, fmCrossFade);

var
  FadeMode: TFadeMode = fmFadeIn;
  FadeAlpha: Integer = 0;
  FadeSpeed: Integer = 8; // 每幀變化量

procedure TForm1.DXTimer1Timer(Sender: TObject; LagCount: Integer);
var
  Delta: Integer;
begin
  DXDraw1.Surface.Fill(0);
  
  Delta := FadeSpeed * (LagCount + 1);
  
  case FadeMode of
    fmFadeIn:
    begin
      Inc(FadeAlpha, Delta);
      if FadeAlpha >= 255 then
      begin
        FadeAlpha := 255;
        FadeMode := fmFadeOut; // 自動切換淡出
      end;
    end;
    fmFadeOut:
    begin
      Dec(FadeAlpha, Delta);
      if FadeAlpha <= 0 then
      begin
        FadeAlpha := 0;
        FadeMode := fmFadeIn;
      end;
    end;
    fmCrossFade:
    begin
      // 交叉淡化需兩張圖片,Alpha 互補
      // Pic1: Alpha, Pic2: 255-Alpha
    end;
  end;
  
  PicItem.DrawAlpha(DXDraw1.Surface, CenterRect, 0, FadeAlpha);
  DXDraw1.Flip;
end;

常見問題排查

問題原因解決
透明色不生效,背景仍顯示TransparentColor 與圖片實際背景色不匹配用取色器確認確切 RGB 值;注意 JPG 壓縮導致邊緣非純色
圖片邊緣出現鋸齒/彩邊透明色邊緣像素非純色 (抗鋸齒產生半透明過渡)使用 PNG 真 Alpha 通道;或預乘 Alpha 處理;或手動清理邊緣
DrawAlpha 效果與預期不符未考慮透明色與 GlobalAlpha 疊加理解 FinalAlpha = PixelAlpha * GlobalAlpha / 255
Alpha=0 仍可見圖片輪廓背景未清除 (Surface.Fill)每幀開始呼叫 DXDraw1.Surface.Fill(背景色)
32位 PNG 載入後透明失效DelphiX 載入 PNG 可能不保留 Alpha 通道轉為 32位 BMP (含 Alpha) 或使用 TDXTextureImage 載入

效能優化建議

  • 靜態透明圖片:Alpha=255 時用 Draw 而非 DrawAlpha,省去混合運算
  • 大量相同 Alpha 精靈:批次繪製,減少狀態切換
  • 避免頻繁切換 Transparent:屬性變更可能觸發內部纹理重建
  • 使用 32位含 Alpha 圖片:免去透明色設定,邊緣品質更好,GPU 直接混合

總結

DelphiX 的透明控制採用透明色 (像素級二值遮罩)與全域 Alpha (整體透明度係數)雙層機制。透明色解決「不規則形狀/去背景」,Alpha 解決「淡入淡出/半透明疊加」。兩者可疊加使用,最終透明度為乘積關係。掌握 TransparentColor 選擇技巧、DrawAlpha 動畫應用、邊緣抗鋸齒處理,即可實現專業級的精靈透明效果。

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