Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to preserve the PNGImage mask when loaded from resource using Delphi XE

I am upgrading my code to Delphi XE (from Delphi 7) and am trying to eliminate all unnecessary libraries. I've used PNGComponents for ages but it is time to move on and use the native TImageList and TPNGImage.

Part of my code loads an image list at runtime from linked in resources. My working PNGComponents code for this is:

function CreateAndLoadImageList( ASize : integer ) : TPngImageList;
var
  PngObject : TPngObject;
  I : integer;
begin
  Result := TPngImageList.Create( nil );

  Result.BeginUpdate;
  try

    Result.Width := ASize;
    Result.Height := ASize;

    PngObject := TPngObject.create;
    try

      For I := 0 to Length( ArtImageNames ) -1 do
        begin
        PngObject.LoadFromResourceName( hInstance, Format( 'AImg%d_%d', [ASize, I]));

        Result.PngImages.Add( False).PngImage := PngObject;
        end;

    finally
      PngObject.Free;
    end;


  finally
    Result.EndUpdate;
  end;

end;

Using an answer in this question I am now trying the code below which shows the images but with black backgrounds, presumably because the mask is lost. I guess I need a mask bitmap to pass to ImageList_Add where the '0' is but I'm poor on this stuff. Does anyone know how I might get this working?

function CreateAndLoadImageList( ASize : integer ) : TImageList;
var
  PngImage : TPngImage;
  bmp : TBitmap;
  I : integer;
begin

  Result := TImageList.Create( nil );
  Result.Masked := False;
  Result.DrawingStyle := dsTransparent;

  Result.BeginUpdate;
  try

    Result.Width := ASize;
    Result.Height := ASize;
    Result.Masked := False;

    PngImage := TPngImage.create;
    try

      For I := 0 to Length( ArtImageNames ) -1 do
        begin
        PngImage.LoadFromResourceName( hInstance, Format( 'AImg%d_%d', [ASize, I]));


        bmp:=TBitmap.Create;
        PngImage.AssignTo(bmp);

        bmp.AlphaFormat:=afIgnored;

        ImageList_Add( Result.Handle, bmp.Handle, 0);
        Bmp.Free;

        end;
    finally
      PngImage.Free;
    end;


  finally
    Result.EndUpdate;
  end;

end;
like image 679
Brian Frost Avatar asked Nov 04 '22 22:11

Brian Frost


1 Answers

PNG images do partial transparency using alpha channels. They do not use masks. I imagine that your problem is that you are not retaining the alpha in your image list.

  • You should set your image list's ColorDepth to cd32Bit.
  • I would expect the bitmap's properties to be set correctly when you assign your PNG image to it so remove the line which sets AlphaFormat.

As an aside it is intended that you use Assign rather than AssignTo. AssignTo is an internal method that enables a mild form of double dispatch for TPersistent.

like image 149
David Heffernan Avatar answered Nov 09 '22 10:11

David Heffernan