从TImageList保存透明(alpha通道)PNG

时间:2018-10-13 16:04:06

标签: delphi png c++builder imagelist timagelist

我有一个TImageList,其中包含透明图标(32位,带有alpha通道)。我想要做的是将基于图像索引的单个图标另存为PNG文件,同时保留Alpha通道的透明度。使用RAD Studio 2010,使其具有TPngImage支持,不需要第三方库。使用此处的方法Add a png image to a imagelist in runtime using Delphi XE-将图像从PNG“ sprite”图像加载到TImageList中,因此在加载时会保留透明度。现在,我需要单独保存它们,换句话说,就是从已经加载到TImageList中的精灵图像中提取单个图像。

到目前为止,我的代码:

int imageindex = 123;
boost::scoped_ptr<TPngImage>         png(new TPngImage);
boost::scoped_ptr<Graphics::TBitmap> bmp(new Graphics::TBitmap);

MyImageList->GetBitmap(imageindex, bmp.get()); // Using GetBitmap to copy TImageList image into separate TBitmap

png->Assign(bmp.get()); // Assign that bitmap to TPngImage
png->SaveToFile("C:\\filename.png");

以上方法有效,但它以白色背景保存(保存后不保留透明性)。我可能错过了一个简单的步骤,但无法弄清楚。

Delphi代码也很受欢迎,应该不难翻译。

1 个答案:

答案 0 :(得分:2)

是的,您可以从添加了(JSONArray)obj.get("useCases")的PNG图像中获取。下面的代码允许您执行此操作!
首先,将TImageList添加到您的PngImage子句中。

uses

看图片。它描述了如果我们设置或不设置以下代码行,将会发生什么:

procedure LoadPNGFromImageList(AImageList: TCustomImageList; AIndex: Integer; var ADestPNG: TPngImage);
const
  PixelsQuad = MaxInt div SizeOf(TRGBQuad) - 1;
type
  TRGBAArray = Array [0..PixelsQuad - 1] of TRGBQuad;
  PRGBAArray = ^TRGBAArray;
var
  ContentBmp: TBitmap;
  RowInOut: PRGBAArray;
  RowAlpha: PByteArray;
  X: Integer;
  Y: Integer;
begin
  if not Assigned(AImageList) or (AIndex < 0) or
     (AIndex > AImageList.Count - 1) or not Assigned(ADestPNG)
  then
    Exit;

  ContentBmp := TBitmap.Create;
  try
    ContentBmp.SetSize(ADestPNG.Width, ADestPNG.Height);
    ContentBmp.PixelFormat := pf32bit;

    // Allocate zero alpha-channel
    for Y:=0 to ContentBmp.Height - 1 do
      begin
        RowInOut := ContentBmp.ScanLine[Y];
        for X:=0 to ContentBmp.Width - 1 do
          RowInOut[X].rgbReserved := 0;
      end;
    ContentBmp.AlphaFormat := afDefined;

    // Copy image
    AImageList.Draw(ContentBmp.Canvas, 0, 0, AIndex, true);

    // Now ContentBmp has premultiplied alpha value, but it will
    // make bitmap too dark after converting it to PNG. Setting
    // AlphaFormat property to afIgnored helps to unpremultiply
    // alpha value of each pixel in bitmap.
    ContentBmp.AlphaFormat := afIgnored;

    // Copy graphical data and alpha-channel values
    ADestPNG.Assign(ContentBmp);
    ADestPNG.CreateAlpha;
    for Y:=0 to ContentBmp.Height - 1 do
      begin
        RowInOut := ContentBmp.ScanLine[Y];
        RowAlpha := ADestPNG.AlphaScanline[Y];
        for X:=0 to ContentBmp.Width - 1 do
          RowAlpha[X] := RowInOut[X].rgbReserved;
      end;
  finally
    ContentBmp.Free;
  end;
end;

enter image description here
图1是设置ContentBmp.AlphaFormat := afIgnored; 的结果,第二个图是 not 设置afIgnored的结果,允许使用先前设置的afIgnored

原始图像是名为图1的图像

在应用程序中使用上面的代码:

afDefined
相关问题