Сохранение прозрачного (альфа-канала) PNG из TImageList - PullRequest
0 голосов
/ 13 октября 2018

У меня есть TImageList, который содержит прозрачные значки (32 бита, с альфа-каналом).Я хочу сохранить отдельные значки на основе индекса изображения в виде файлов PNG, сохранив прозрачность альфа-канала.Использование RAD Studio 2010 с поддержкой TPngImage, не требует сторонних библиотек.Изображения загружаются в TImageList из PNG-изображения «sprite», используя метод, описанный здесь - Добавьте изображение png в список изображений во время выполнения, используя Delphi XE - чтобы при загрузке сохранялась прозрачность.Теперь мне нужно сохранить их по отдельности, другими словами, извлечь отдельные изображения из изображений спрайтов, которые уже загружены в 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 голосов
/ 15 октября 2018

Да, вы можете получить 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;

Посмотрите на картинку.Это показывает, что произойдет, если мы установим или не установим такую ​​строку кода:

ContentBmp.AlphaFormat := afIgnored;

enter image description here
Рисунок 1 является результатом установки afIgnored ивторая цифра является результатом , а не настройки afIgnored, позволяющей использовать ранее установленную afDefined.

Исходное изображение - это изображение с именем Figure 1

Использование приведенного выше кода в приложении:

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;  
...