Delphi png到bmp转换(保持透明度)

Delphi png到bmp转换(保持透明度),delphi,delphi-xe5,Delphi,Delphi Xe5,我使用delphi XE-5,从JSON文件加载按钮信息,以便在TMS ADVToolBar控件上创建按钮。每个按钮为50X35,png格式,透明 我获取每个url,使用idHTTP组件将其检索到流中,然后将其加载到png中。然后我把它画到一个透明的BMP上。然而,我认为这不是正确的方法。无论如何,bmp会被添加到TImageList中,并使用索引将其分配给按钮。图像显示在按钮上,但没有透明度 请参见下面的我的代码: imgUrl:= //code to get img url from JS

我使用delphi XE-5,从JSON文件加载按钮信息,以便在TMS ADVToolBar控件上创建按钮。每个按钮为50X35,png格式,透明

我获取每个url,使用idHTTP组件将其检索到流中,然后将其加载到png中。然后我把它画到一个透明的BMP上。然而,我认为这不是正确的方法。无论如何,bmp会被添加到TImageList中,并使用索引将其分配给按钮。图像显示在按钮上,但没有透明度

请参见下面的我的代码:

 imgUrl:= //code to get img url from JSON file;

 MS := TMemoryStream.Create;
 png := TPngImage.Create;
 png.Transparent:= True;
 try
  idHTTP1.get(imgUrl,MS);
  Ms.Seek(0,soFromBeginning);
  png.LoadFromStream(MS);
  bmp:= TBitmap.Create;
  bmp.Transparent:= True;
  bmp.Width:= 50;
  bmp.Height:= 50;
  png.Draw(bmp.Canvas, Rect(7, 7, png.Width, png.Height));
  ImageList1.Add(bmp, nil);
  AdvGlowBtn.Images:= ImageList1;
  AdvGlowBtn.Layout:= blGlyphTop;
  AdvGlowBtn.WordWrap:= False;
  AdvGlowBtn.AutoSize:= True;

  AdvGlowBtn.ImageIndex:= ImageList1.Count-1;

  bmp.Free;
 finally
 FreeAndNil(png);
 FreeAndNil(MS);
 end;

TBitmap
类使用Windows自己的库来操作位图。根据您的Windows版本,底层操作系统库不支持32位BMP,尽管库头文件声明了
BITMAPQUAD
struct

对于较新版本的Windows(Vista及以上afaik),字段
BITMAPQUAD.reserved
用于存储alpha通道。对于旧版本,此字段必须保持为零(0x00)

如果您使用的是“最新”版本的Windows,我看到的唯一可能的解释是,
TBitmap
类没有更新以支持alpha通道


使用类
TPNGImage
不应该成为问题,而应该在使用前将其转换为BMP,除非您有一些更具体的需求。

首先您必须启用运行时主题(项目管理器),否则您的图像将没有透明度

这是将PNG图像加载到
ImageList1

bmp := TBitmap.Create;
try
  // everything done before to bmp has no effect
  bmp.Assign( png );
  // if for some reason the loaded image is smaller
  // set the size to avoid the invalid image size error
  bmp.Width := ImageList1.Width;
  bmp.Height := ImageList1.Height;

  AdvGlowBtn.Images:= ImageList1;
  ...
  // now add the Bitmap to the ImageList
  AdvGlowBtn.ImageIndex := ImageList1.Add( bmp, nil );
finally
  bmp.Free;
end;

我有一个Delphi5中的老项目,我有时仍在使用它。 这是我使用png对象的解决方案

procedure ImageList2Alpha(const ImageList: TImageList);
const
  Mask: array[Boolean] of Longint = (0, ILC_MASK);
var
  TempList: TImageList;
begin
  if Assigned(ImageList) then
  begin
    TempList := TImageList.Create(nil);
    try
      TempList.Assign(ImageList);
      with ImageList do
      begin
        Handle := ImageList_Create(Width, Height, ILC_COLOR32 or Mask[Masked], 0, AllocBy);
        if not HandleAllocated then
          raise EInvalidOperation.Create(SInvalidImageList);
      end;
      Imagelist.AddImages(TempList);
    finally
      FreeAndNil(TempList);
    end;
  end;
end;

procedure LoadPngToBmp(var Dest: TBitmap; AFilename: TFilename);
type 
  TRGB32 = packed record 
    B, G, R, A : Byte;
  end; 
  PRGBArray32 = ^TRGBArray32; 
  TRGBArray32 = array[0..0] of TRGB32;
type
  TRG24 = packed record
    rgbtBlue, rgbtGreen, rgbtRed : Byte;
  end;
  PRGBArray24 = ^TPRGBArray24;
  TPRGBArray24 = array[0..0] of TRG24;
type
  TByteArray = Array[Word] of Byte;
  PByteArray = ^TByteArray;
  TPByteArray = array[0..0] of TByteArray;
var
  BMP : TBitmap;
  PNG: TPNGObject;
  x, y: Integer; 
  BmpRow: PRGBArray32;
  PngRow : PRGBArray24;
  AlphaRow: PByteArray;
begin

  Bmp := TBitmap.Create;
  PNG := TPNGObject.Create;

  try

    if AFilename <> '' then
    begin

      PNG.LoadFromFile(AFilename);
      BMP.PixelFormat := pf32bit;
      BMP.Height := PNG.Height;
      BMP.Width := PNG.Width;

      if ( PNG.TransparencyMode = ptmPartial ) then
      begin

        for Y := 0 to BMP.Height-1 do
        begin

          BmpRow := PRGBArray32(BMP.ScanLine[Y]);
          PngRow := PRGBArray24(PNG.ScanLine[Y]);
          AlphaRow := PByteArray(PNG.AlphaScanline[Y]);

          for X := 0 to BMP.Width - 1 do
          begin
            with BmpRow[X] do
            begin
              with PngRow[X] do
              begin
                R := rgbtRed; G := rgbtGreen; B := rgbtBlue;
              end;
              A := Byte(AlphaRow[X]);
            end;
          end;

        end;

      end else
      begin

        for Y := 0 to BMP.Height-1 do
        begin

          BmpRow := PRGBArray32(BMP.ScanLine[Y]);
          PngRow := PRGBArray24(PNG.ScanLine[Y]);

          for X := 0 to BMP.Width - 1 do
          begin
            with BmpRow[X] do
            begin
              with PngRow[X] do
              begin
                R := rgbtRed; G := rgbtGreen; B := rgbtBlue;
              end;
              A := 255;
            end;
          end;

        end;

      end;

      Dest.Assign(BMP);

    end;

  finally
    Bmp.Free;
    PNG.Free;
  end;
end;
过程ImageList2Alpha(常量ImageList:TImageList);
常数
掩码:Longint=(0,ILC_掩码)的数组[布尔值];
变量
圣殿骑士:提摩日骑士;
开始
如果已分配(图像列表),则
开始
templast:=TImageList.Create(nil);
尝试
圣堂武士分配(图像列表);
用ImageList做什么
开始
句柄:=ImageList_Create(宽度、高度、ILC_颜色32或掩码[Masked],0,AllocBy);
如果未手动分配,则
引发EINValidoOperation.Create(SinValidImage列表);
结束;
Imagelist.AddImages(圣殿骑士);
最后
FreeAndNil(圣殿骑士);
结束;
结束;
结束;
过程装入pngtobmp(var Dest:TBitmap;AFilename:TFilename);
类型
TRGB32=压缩记录
B、 G,R,A:字节;
结束;
PRGBArray32=^TRGBArray32;
TRGBArray32=TRGB32的数组[0..0];
类型
TRG24=打包记录
rgbtBlue、rgbtGreen、rgbtRed:字节;
结束;
PRGBArray24=^TPRBarray24;
TrpgBarray24=TRG24的数组[0..0];
类型
TByteArray=字节的数组[字];
PByteArray=^TByteArray;
TPByteArray=TByteArray的数组[0..0];
变量
BMP:TBitmap;
PNG:TPNGObject;
x、 y:整数;
BMP船头:PRGBArray32;
PngRow:PRGBArray24;
AlphaRow:PByte阵列;
开始
Bmp:=TBitmap.Create;
PNG:=TPNGObject.Create;
尝试
如果文件名为“”,则
开始
LoadFromFile(AFilename);
BMP.PixelFormat:=pf32位;
BMP.Height:=PNG.Height;
BMP.Width:=PNG.Width;
如果(PNG.TransparencyMode=ptmPartial),则
开始
对于Y:=0到BMP.Height-1 do
开始
BmpRow:=PRGBArray32(BMP.ScanLine[Y]);
PngRow:=PRGBArray24(PNG.ScanLine[Y]);
AlphaRow:=PByteArray(PNG.AlphaScanline[Y]);
对于X:=0到BMP.Width-1 do
开始
用BmpRow[X]do
开始
使用PngRow[X]do
开始
R:=rgbtRed;G:=rgbtGreen;B:=rgbtBlue;
结束;
A:=字节(字母行[X]);
结束;
结束;
结束;
结束其他
开始
对于Y:=0到BMP.Height-1 do
开始
BmpRow:=PRGBArray32(BMP.ScanLine[Y]);
PngRow:=PRGBArray24(PNG.ScanLine[Y]);
对于X:=0到BMP.Width-1 do
开始
用BmpRow[X]do
开始
使用PngRow[X]do
开始
R:=rgbtRed;G:=rgbtGreen;B:=rgbtBlue;
结束;
A:=255;
结束;
结束;
结束;
结束;
目的地分配(BMP);
结束;
最后
Bmp.Free;
巴布亚新几内亚免费;
结束;
结束;
在表单(FormCreate)的OnCreate上调用ImageList2Alpha(YourImageList),ImageList将准备好存储位图32并保持透明度

调用LoadPngToBmp过程将PNG转换为位图32,然后将其存储在ImageList中。

如下所示:

ABitmap.SetSize(png.Width, png.Height);
png.AssignTo(ABitmap);

您大概不希望
透明。您可能想要一个32bpp的位图。为什么不直接使用PNG而不是将其转换为BMP?请尝试GraphicEx或Vampyre Imaging。。。但最重要的是使用PNGdirectly@Arioch,没有第三方也一样简单。。。但是直接添加PNGs是最好的选择。@TLama-这是真的吗?TImageList的字形大小必须是成比例的,不是吗。(例如50X50)在这种情况下,来自互联网的图像是50X35。我得到无效的图像大小错误。我很确定XP支持位图中的alpha。而不是win2k。更具体的需求在最初的帖子中列出。如何将50X35 png放入ImageList并保持其透明度,以便我可以将其放置在button@LuvRAD文档声明支持它,但正如您所注意到的,无法将
TPNGImage
直接添加到
TImageList
中。我觉得缺乏文件令人不安。这很可能是一个很好的解决方案,但对我不起作用,因为我没有提到我的png图像有各种大小(最大的是50X35)。对不起,我只能回答问题。现在您知道了如何在不失去透明度的情况下将PNG转换为位图。如果你有其他问题,那么你应该问另一个问题。这很有效。:)及