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

时间:2014-01-27 15:16:16

标签: delphi delphi-xe5

我正在使用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;

4 个答案:

答案 0 :(得分:3)

首先,您必须启用 运行时主题(项目经理),否则您的图片将无透明度

这是将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;

答案 1 :(得分:2)

我在Delphi 5中有一个旧项目,有时候我还在使用它。 这是我使用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;

在Form(FormCreate)的OnCreate上调用ImageList2Alpha(YourImageList),ImageList将准备存储您的Bitmaps32以保持透明度。

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

答案 2 :(得分:1)

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

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

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

使用班级TPNGImage不应成为问题,而不是在使用之前将其转换为BMP,除非您有更具体的需求。

答案 3 :(得分:1)

使用它:

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