简体   繁体   中英

Saving transparent (alpha channel) PNG from TImageList

I have a TImageList which contains transparent icons (32bit, with alpha channel). What I want to do is to save individual icons based on image index as PNG file(s), while preserving alpha channel transparency. Using RAD Studio 2010 so it has TPngImage support, no need for third party libraries. Images are loaded into TImageList from PNG "sprite" image using the method here - Add a png image to a imagelist in runtime using Delphi XE - so the transparency is preserved upon loading. Now I need to save them out individually, in other words, extract individual images from sprite images which is already loaded into TImageList.

My code so far:

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");

The above works but it saves with the white background (transparency is not preserved after saving). I am probably missing a simple step but can't figure it out.

Delphi code is also welcome, shouldn't be hard to translate.

Yes, you can obtain PNG-image from TImageList where it was added. Code below allows you to do this!
Firstly, add PngImage to your uses clause.

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;

Look at the picture. It is depicts what will happen if we set or not set such line of code:

ContentBmp.AlphaFormat := afIgnored;

在此处输入图片说明
Figure 1 is a result of setting afIgnored and the second one figure is a result of not setting afIgnored , allowing to use previously set afDefined .

Original image is an image named Figure 1

Using of code above in application:

procedure TForm1.aButton1Click(Sender: TObject);
var
  DestPNG: TPngImage;
begin
  DestPNG := TPNGImage.Create;
  try
    // Initialize PNG
    DestPNG.CreateBlank(COLOR_RGBALPHA, 8, 60, 60);

    // Obtain PNG from image list
    LoadPNGFromImageList(ImageList1, 0, DestPNG);

    // Output PNG onto Canvas
    DestPNG.Draw(Canvas, Rect(0, 0, 60, 60));
    DestPNG.SaveToFile('C:\MyPNGIcon.png');
  finally
    DestPNG.Free;
  end;
end;  

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM