Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Alpha-blended glyphs for TBitBtn and TSpeedButtons?


This question is not answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 6 - Last Post: Jun 19, 2015 2:25 AM Last Post By: Uwe Raabe
Carl Olsen

Posts: 124
Registered: 3/29/00
Alpha-blended glyphs for TBitBtn and TSpeedButtons?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 9, 2015 5:32 PM
I wish to improve the look of my application, so I'm converting all my glyphs from 4 bit per pixel, to (hopefully) 32 bit per pixel with alpha blend.

Unfortunately, it seems I can only use bitmaps as my glyphs, and only 24 bit at best. Is there some way in Delphi XE8 that I can do proper alpha blending? I would think a .png file would work great, but it won't let me use a PNG.

I need to do this for both TBitBtn and TSpeedButton.

Thanks!

Carl.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Alpha-blended glyphs for TBitBtn and TSpeedButtons?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 9, 2015 6:06 PM   in response to: Carl Olsen in response to: Carl Olsen
Carl wrote:

Unfortunately, it seems I can only use bitmaps as my glyphs, and
only 24 bit at best. Is there some way in Delphi XE8 that I can
do proper alpha blending? I would think a .png file would work
great, but it won't let me use a PNG.

Standard VCL components, including TBitBtn and TSpeedButton, do not support
PNG graphics, only BMP graphics (and not alpha-blended BMPs). There are
3rd party components that support PNG, though. For example, I use TPngImageList
and TPngBitBtn in several of my projects (TPngImageList can even be attached
to standard VCL components that support TCustomImageList). But those components
were made for earlier Delphi versions, I have no clue if they will work in
modern versions. You will have to look around.

--
Remy Lebeau (TeamB)
Uwe Raabe

Posts: 180
Registered: 10/20/00
Re: Alpha-blended glyphs for TBitBtn and TSpeedButtons?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 17, 2015 2:53 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:

But those components were made for
earlier Delphi versions, I have no clue if they will work in modern
versions. You will have to look around.

PngComponents for Delphi 2009 - XE8 are available from CodeCentral:
http://cc.embarcadero.com/Item/26127

--
Uwe Raabe
Embarcadero MVP
Uwe Raabe

Posts: 180
Registered: 10/20/00
Re: Alpha-blended glyphs for TBitBtn and TSpeedButtons?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 19, 2015 2:24 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:

But those components were made for
earlier Delphi versions, I have no clue if they will work in modern
versions. You will have to look around.

PngComponents for Delphi 2009 - XE8 are available from CodeCentral:
http://cc.embarcadero.com/Item/26127

--
Uwe Raabe
Embarcadero MVP
Uwe Raabe

Posts: 180
Registered: 10/20/00
Re: Alpha-blended glyphs for TBitBtn and TSpeedButtons?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 19, 2015 2:25 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:

But those components were made for
earlier Delphi versions, I have no clue if they will work in modern
versions. You will have to look around.

PngComponents for Delphi 2009 - XE8 are available from CodeCentral:
http://cc.embarcadero.com/Item/26127

--
Uwe Raabe
Embarcadero MVP
Angus Johnson

Posts: 32
Registered: 9/23/99
Re: Alpha-blended glyphs for TBitBtn and TSpeedButtons?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 10, 2015 8:18 AM   in response to: Carl Olsen in response to: Carl Olsen
On 10/06/2015 10:32 AM, Carl Olsen wrote:> I wish to improve the look of
my application, so I'm converting all my glyphs from 4 bit per pixel, to
(hopefully) 32 bit per pixel with alpha blend.

Unfortunately, it seems I can only use bitmaps as my glyphs, and only
24 bit at best. Is there some way in Delphi XE8 that I can do proper
alpha blending? I would think a .png file would work great, but it
won't let me use a PNG.

I need to do this for both TBitBtn and TSpeedButton.

It's not too hard to do alpha blending especially onto a monochrome
background like a button surface. You don't even need to use
Windows.AlphaBlend (which requires premultiplied alphas).

Here's some code that takes a 32bit bitmap resource, alpha blends it
with the button's color (clBtnFace) before assigning it to a
BitBtn.Glyph ...

{$R myBmp.res} //contains a bitmap image resource

type
PByteArray = ^TByteArray;
TByteArray = array [0 ..255] of Byte;

PColorEntry = ^TColorEntry;
TColorEntry = packed record
case Integer of
0: (B, G, R, A: Byte);
1: (ARGB: Cardinal);
end;

var
MulTable: array [Byte, Byte] of Byte;

function Blend(const F, B: Cardinal): Cardinal;
var
fg: TColorEntry ABSOLUTE F;
bg: TColorEntry ABSOLUTE B;
res: TColorEntry ABSOLUTE Result;
Fw, Bw: PByteArray;
begin
if fg.A = 0 then result := B
else if fg.A = $FF then result := F
else
begin
Fw := @MulTable[fg.A];
Bw := @MulTable[not fg.A];
Res.R := Fw[fg.R] + Bw[bg.R];
Res.G := Fw[fg.G] + Bw[bg.G];
Res.B := Fw[fg.B] + Bw[bg.B];
Res.A := 255;
end;
end;

procedure AddBkgndColor(alphaBmp: TBitmap; bkgndColor: Cardinal);
var
x,y: Integer;
c: PColorEntry;
cl: TColorEntry ABSOLUTE bkgndColor;
begin
alphaBmp.PixelFormat := pf32bit;
cl.A := 255;
for y := 0 to alphaBmp.Height -1 do
begin
c := alphaBmp.ScanLine[y];
for x := 0 to alphaBmp.Width -1 do
begin
c.ARGB := Blend(c.ARGB, cl.ARGB);
inc(c);
end;
end;
end;

function ColorToRGB32(c: TColor): Cardinal;
begin
result := Cardinal(ColorToRGB(c));
//and we also need to swap Red and Blue channels ...
result := (result and $FF00FF00) or
((result shr 16) and $FF) or ((result and $FF) shl 16);
end;

procedure TForm2.FormCreate(Sender: TObject);
var
bmp: TBitmap;
begin

//do it all here ...

bmp := TBitmap.Create;
try
bmp.LoadFromResourceID(hInstance, 1);
AddBkgndColor(bmp, ColorToRGB32(clBtnFace));
BitBtn1.Glyph.Assign(bmp);
finally
bmp.free;
end;
end;

{$R-}
procedure MakeMulTable;
var
I, J: Integer;
const
Div255 = 1 / 255;
begin
for I := 0 to 255 do MulTable[I, 0] := 0;
for I := 1 to 255 do
for J := 0 to 255 do
MulTable[I, J] := Round(I * J * Div255);
end;
{$R+}

initialization
MakeMulTable;

Angus Johnson

Posts: 32
Registered: 9/23/99
Re: Alpha-blended glyphs for TBitBtn and TSpeedButtons?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 10, 2015 8:37 AM   in response to: Carl Olsen in response to: Carl Olsen
On 10/06/2015 10:32 AM, Carl Olsen wrote:> I wish to improve the look of
my application, so I'm converting all my glyphs from 4 bit per pixel, to
(hopefully) 32 bit per pixel with alpha blend.

Unfortunately, it seems I can only use bitmaps as my glyphs, and only
24 bit at best. Is there some way in Delphi XE8 that I can do proper
alpha blending? I would think a .png file would work great, but it
won't let me use a PNG.

I need to do this for both TBitBtn and TSpeedButton.

It's not too hard to do alpha blending especially onto a monochrome
background like a button surface. You don't even need to use
Windows.AlphaBlend (which requires premultiplied alphas).

Here's some code that takes a 32bit bitmap resource, alpha blends it
with the button's color (clBtnFace) before assigning it to a
BitBtn.Glyph ...


{$R myBmp.res} //contains a bitmap image resource
 
type
   PByteArray = ^TByteArray;
   TByteArray = array [0 ..255] of Byte;
 
   PColorEntry = ^TColorEntry;
   TColorEntry = packed record
     case Integer of
       0: (B, G, R, A: Byte);
       1: (ARGB: Cardinal);
   end;
 
var
   MulTable: array [Byte, Byte] of Byte;
 
function Blend(const F, B: Cardinal): Cardinal;
var
   fg: TColorEntry ABSOLUTE F;
   bg: TColorEntry ABSOLUTE B;
   res: TColorEntry ABSOLUTE Result;
   Fw, Bw: PByteArray;
begin
   if fg.A = 0 then result := B
   else if fg.A = $FF then result := F
   else
   begin
     Fw := @MulTable[fg.A];
     Bw := @MulTable[not fg.A];
     Res.R := Fw[fg.R] + Bw[bg.R];
     Res.G := Fw[fg.G] + Bw[bg.G];
     Res.B := Fw[fg.B] + Bw[bg.B];
     Res.A := 255;
   end;
end;
 
procedure AddBkgndColor(alphaBmp: TBitmap; bkgndColor: Cardinal);
var
   x,y: Integer;
   c: PColorEntry;
   cl: TColorEntry ABSOLUTE bkgndColor;
begin
   alphaBmp.PixelFormat := pf32bit;
   cl.A := 255;
   for y := 0 to alphaBmp.Height -1 do
   begin
     c := alphaBmp.ScanLine[y];
     for x := 0 to alphaBmp.Width -1 do
     begin
       c.ARGB := Blend(c.ARGB, cl.ARGB);
       inc(c);
     end;
   end;
end;
 
function ColorToRGB32(c: TColor): Cardinal;
begin
   result := Cardinal(ColorToRGB(c));
   //and we also need to swap Red and Blue channels ...
   result := (result and $FF00FF00) or
     ((result shr 16) and $FF) or ((result and $FF) shl 16);
end;
 
procedure TForm2.FormCreate(Sender: TObject);
var
   bmp: TBitmap;
begin
 
   //do it all here ...
 
   bmp := TBitmap.Create;
   try
     bmp.LoadFromResourceID(hInstance, 1);
     AddBkgndColor(bmp, ColorToRGB32(clBtnFace));
     BitBtn1.Glyph.Assign(bmp);
   finally
     bmp.free;
   end;
end;
 
{$R-}
procedure MakeMulTable;
var
   I, J: Integer;
const
   Div255 = 1 / 255;
begin
   for I := 0 to 255 do MulTable[I, 0] := 0;
   for I := 1 to 255 do
     for J := 0 to 255 do
       MulTable[I, J] := Round(I * J * Div255);
end;
{$R+}
 
initialization
   MakeMulTable;
 
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02