You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Delphi 11.3中程序化反转TImageCollection图像(保留透明度)

程序化修改TImageCollection图标颜色(适配深色主题/多颜色需求)

针对Delphi 11.3中TImageCollection+TVirtualImageList的图标颜色适配问题,无需维护多套图像资源,可通过直接操作图像像素或动态绘制的方式实现颜色转换,同时保留透明度。

一、批量转换图像颜色(预生成变体)

适合需要长期保留多色版本的场景,直接修改或新增TImageCollection中的图像条目。

核心函数实现

1. 反转颜色(黑→白,适配深色背景)

procedure ReverseImageColor(const SrcBitmap, DestBitmap: TBitmap);
var
  X, Y: Integer;
  SrcPixel, DestPixel: PRGBQuad;
  SrcScanline, DestScanline: PByte;
begin
  DestBitmap.SetSize(SrcBitmap.Width, SrcBitmap.Height);
  DestBitmap.PixelFormat := pf32bit; // 强制32位带Alpha通道

  for Y := 0 to SrcBitmap.Height - 1 do
  begin
    SrcScanline := SrcBitmap.ScanLine[Y];
    DestScanline := DestBitmap.ScanLine[Y];
    for X := 0 to SrcBitmap.Width - 1 do
    begin
      SrcPixel := PRGBQuad(SrcScanline + X * SizeOf(TRGBQuad));
      DestPixel := PRGBQuad(DestScanline + X * SizeOf(TRGBQuad));
      
      // 保留Alpha通道,反转RGB分量
      DestPixel^.rgbBlue := 255 - SrcPixel^.rgbBlue;
      DestPixel^.rgbGreen := 255 - SrcPixel^.rgbGreen;
      DestPixel^.rgbRed := 255 - SrcPixel^.rgbRed;
      DestPixel^.rgbReserved := SrcPixel^.rgbReserved; // 继承原透明度
    end;
  end;
end;

2. 替换指定颜色(如黑→红)

procedure ReplaceImageColor(const SrcBitmap, DestBitmap: TBitmap; OldColor, NewColor: TColor);
var
  X, Y: Integer;
  SrcPixel, DestPixel: PRGBQuad;
  SrcScanline, DestScanline: PByte;
  OldRGB, NewRGB: TRGBQuad;
begin
  DestBitmap.SetSize(SrcBitmap.Width, SrcBitmap.Height);
  DestBitmap.PixelFormat := pf32bit;

  // 将TColor转换为RGBQuad格式
  ColorToRGBQuad(OldColor, OldRGB);
  ColorToRGBQuad(NewColor, NewRGB);

  for Y := 0 to SrcBitmap.Height - 1 do
  begin
    SrcScanline := SrcBitmap.ScanLine[Y];
    DestScanline := DestBitmap.ScanLine[Y];
    for X := 0 to SrcBitmap.Width - 1 do
    begin
      SrcPixel := PRGBQuad(SrcScanline + X * SizeOf(TRGBQuad));
      DestPixel := PRGBQuad(DestScanline + X * SizeOf(TRGBQuad));
      
      // 匹配目标颜色则替换,否则保留原像素
      if (SrcPixel^.rgbRed = OldRGB.rgbRed) and
         (SrcPixel^.rgbGreen = OldRGB.rgbGreen) and
         (SrcPixel^.rgbBlue = OldRGB.rgbBlue) then
      begin
        DestPixel^.rgbRed := NewRGB.rgbRed;
        DestPixel^.rgbGreen := NewRGB.rgbGreen;
        DestPixel^.rgbBlue := NewRGB.rgbBlue;
      end
      else
        DestPixel^ := SrcPixel^;
      
      DestPixel^.rgbReserved := SrcPixel^.rgbReserved; // 保留透明度
    end;
  end;
end;

// 辅助函数:TColor转TRGBQuad
procedure ColorToRGBQuad(Color: TColor; out RGBQuad: TRGBQuad);
var
  RGB: TColorRGB;
begin
  RGB := ColorToRGB(Color);
  RGBQuad.rgbRed := GetRValue(RGB);
  RGBQuad.rgbGreen := GetGValue(RGB);
  RGBQuad.rgbBlue := GetBValue(RGB);
  RGBQuad.rgbReserved := 255;
end;

批量处理TImageCollection

遍历所有图像,生成对应颜色变体并添加到集合中:

type
  TImageColorMode = (icmReverse, icmRed);

procedure ProcessImageCollection(ImageCollection: TImageCollection; Mode: TImageColorMode);
var
  I: Integer;
  SrcBmp, DestBmp: TBitmap;
  Item: TImageCollectionItem;
  Suffix: string;
begin
  SrcBmp := TBitmap.Create;
  DestBmp := TBitmap.Create;
  try
    case Mode of
      icmReverse: Suffix := '_white';
      icmRed: Suffix := '_red';
    end;

    for I := 0 to ImageCollection.Images.Count - 1 do
    begin
      Item := ImageCollection.Images[I];
      Item.Bitmap.AssignTo(SrcBmp);

      case Mode of
        icmReverse: ReverseImageColor(SrcBmp, DestBmp);
        icmRed: ReplaceImageColor(SrcBmp, DestBmp, clBlack, clRed);
      end;

      // 新增颜色变体条目
      with ImageCollection.Images.Add do
      begin
        Name := Item.Name + Suffix;
        Bitmap.Assign(DestBmp);
        Width := Item.Width;
        Height := Item.Height;
      end;
    end;
  finally
    SrcBmp.Free;
    DestBmp.Free;
  end;
end;

调用示例:

// 生成白色变体(适配深色主题)
ProcessImageCollection(ImageCollection1, icmReverse);
// 生成红色变体
ProcessImageCollection(ImageCollection1, icmRed);

二、动态绘制时修改颜色(按需转换)

适合需要频繁切换主题/颜色的场景,无需修改原ImageCollection,在TVirtualImageList绘制时实时转换:

procedure TMainForm.VirtualImageList1DrawImage(Sender: TCustomVirtualImageList;
  const AImage: TVirtualImage; ACanvas: TCanvas; const ARect: TRect;
  AOpacity: Byte; AState: TVirtualImageState);
var
  Bmp: TBitmap;
  TempBmp: TBitmap;
begin
  Bmp := TBitmap.Create;
  TempBmp := TBitmap.Create;
  try
    // 从ImageCollection获取原图像
    ImageCollection1.GetBitmap(AImage.Name, Bmp);
    TempBmp.SetSize(Bmp.Width, Bmp.Height);
    TempBmp.PixelFormat := pf32bit;

    // 根据当前主题判断是否反转颜色
    if TOSThemeManager.Current.IsDarkMode then
      ReverseImageColor(Bmp, TempBmp)
    else
      TempBmp.Assign(Bmp);

    // 绘制到目标画布
    ACanvas.Draw(ARect.Left, ARect.Top, TempBmp);
  finally
    Bmp.Free;
    TempBmp.Free;
  end;
end;

注意事项

  • 确保所有图像为32位带Alpha通道格式,否则透明度会丢失;若原图像格式不符,可在处理前先转换为pf32bit。
  • 批量处理时,建议通过命名后缀区分不同颜色变体,方便在VirtualImageList中指定调用。
  • 动态绘制方式更节省内存,但会增加少量绘制开销,适合主题切换频繁的场景。

内容的提问来源于stack exchange,提问作者Alister

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 00:45:18