How to draw a translucent image on a form?
Asked Answered
H

3

6

I want to a draw a translucent image on a Delphi form, but for some reason it is not working.

Here is the original PNG (border is semi transparent):
Transparent border

I load the image in a TTntImage object:

Image1.Transparent := True;
Form1.Color := clWhite;
Form1.TransparentColor := True;
Form1.TransparentColorValue := clWhite;

TImage

The application:
Application


The image isn't translucent. I am working with a BMP image that contains the alpha channel. Am I missing something?

Hooknosed answered 11/5, 2011 at 13:2 Comment(0)
B
12

I found a solution that will let you draw a BMP image with an alpha channel onto a form using only the Windows API:

const
  AC_SRC_OVER = 0;
  AC_SRC_ALPHA = 1;

type
  BLENDFUNCTION = packed record
    BlendOp,
    BlendFlags,
    SourceConstantAlpha,
    AlphaFormat: byte;
  end;

function WinAlphaBlend(hdcDest: HDC; xoriginDest, yoriginDest, wDest, hDest: integer;
  hdcSrc: HDC; xoriginSrc, yoriginSrc, wSrc, hSrc: integer; ftn: BLENDFUNCTION): LongBool;
  stdcall; external 'Msimg32.dll' name 'AlphaBlend';

procedure TForm4.FormClick(Sender: TObject);
var
  hbm: HBITMAP;
  bm: BITMAP;
  bf: BLENDFUNCTION;
  dc: HDC;
begin
  hbm := LoadImage(0,
    'C:\Users\Andreas Rejbrand\Skrivbord\RatingCtrl.bmp',
    IMAGE_BITMAP,
    0,
    0,
    LR_LOADFROMFILE);
  if hbm = 0 then
    RaiseLastOSError;
  try
    if GetObject(hbm, sizeof(bm), @bm) = 0 then RaiseLastOSError;
    dc := CreateCompatibleDC(0);
    if dc = 0 then RaiseLastOSError;
    try
      if SelectObject(dc, hbm) = 0 then RaiseLastOSError;
      bf.BlendOp := AC_SRC_OVER;
      bf.BlendFlags := 0;
      bf.SourceConstantAlpha := 255;
      bf.AlphaFormat := AC_SRC_ALPHA;
      if not WinAlphaBlend(Canvas.Handle,
        10,
        10,
        bm.bmWidth,
        bm.bmHeight,
        dc,
        0,
        0,
        bm.bmWidth,
        bm.bmHeight,
        bf) then RaiseLastOSError;
    finally
      DeleteDC(dc);
    end;
  finally
    DeleteObject(hbm);
  end;
end;

Using The GIMP, I converted the PNG image

found here to a 32-bit RGBA bitmap, found here, and the result is very good:

Benyamin answered 11/5, 2011 at 13:48 Comment(3)
Nice! BTW, your code works with the regular gdi function declaration, i.e. windows.AlphaBlend(), no need to declare the constants, the record and the function..Augustusaugy
@Sertac: I am very well aware of that, but I am not sure if AlphaBlend is declared in the Windows.pas that ships with the old Delphi 7, the Delphi version of the OP. In addition, the declaration of AlphaBlend in Windows.pas in Delphi 2009 (my Delphi version) is very 'ugly': function AlphaBlend(DC: HDC; p2, p3, p4, p5: Integer; DC6: HDC; p7, p8, p9, p10: Integer; p11: TBlendFunction): BOOL; stdcall; But I guess I should have written a footnote about this.Benyamin
The AlphaBlend needs premultiplied alpha – See https://mcmap.net/q/1232593/-how-to-draw-a-png-transparently-on-a-tmetafilecanvas/850848#10044325Darnell
B
1

The TransparentColorValue approach cannot possibly work, because this only works with images in which a single colour represents full transparency. [In addition, you are toying with the form's transparent colour instead of image's transparent colour!] The above PNG image is supposed to have an alpha channel, so it's not like every pixel is either shown or transparent -- instead, each pixel has an opacity between 0 and 1 (0.37, for instance). That is, in addition to the R, G, and B components of each pixel, there is an 'alpha' component A.

The above image appears to be corrupt, however. A 'correct' PNG is shown below:


(source: rejbrand.se)

You can try to blend the above one onto different backgrounds, and you will find that the shadow blends nicely.

So, if one has a 'correct' PNG, how to draw it onto a form? Well, that is going to be very difficult in your case, since Delphi 7 does not support PNG images. It only supports BMP images, and these normally do not have alpha channels.

Benyamin answered 11/5, 2011 at 13:11 Comment(10)
windows bitmaps often have alpha channelsGendarmerie
@David: Yeah, but I am not sure if the Delphi 7 TImage can handle those. Can it?Benyamin
what do you mean by often David? Very few tools support .BMP files with alpha channels, so how often, do you suppose, that a stored windows .BMP has one? I would say close to 0.0001% of them have them. Except maybe on your computer.Sovereignty
@andreas no I doubt it very much. Delphi's TBitmap has been very tardy with alpha support.Gendarmerie
I can save this image as BMP but the image will be black. :(Hooknosed
@warren who said anything about files? How do you think 32bpp xp icons are represented inside your computer?Gendarmerie
@Robrok: The one titled 'Form4' above? Then you are probably using a very bad image file format converter. Try Paint. But still, BMP and alpha channels do not go together very well, so I would probably not use BMP if I were you.Benyamin
BMP or PNG, what ever. I am learning and i want to paint transparent image on a form.Hooknosed
I like alpha skins but they not free. And older versions are bad.Hooknosed
@David: The OP said something about files. This is a site where we answer the questions the user asked. Or we try to.Sovereignty
G
1

Why not try do draw your png onto new image with regular bmp. Draw what you want onto image 2 and redraw /or assign/ all to your image 1 when finish. Must works...

Gyrfalcon answered 16/11, 2012 at 13:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.