Transparent PNG alpha channel window

Just starting out? Need help? Post your questions and find answers here.
OgreVorbis
User
User
Posts: 77
Joined: Thu Jan 16, 2020 10:47 pm

Transparent PNG alpha channel window

Post by OgreVorbis »

I've found many posts regarding this by searching, but none of them seem to do what I'm looking for.
Currently, I'm using SetLayeredWindowAttributes with LWA_COLORKEY. This only allows me to have a certain color be fully transparent. What I want to do is display a PNG with an alpha channel in a boarderless window and have the alpha parts be partially transparent. In simpler terms, I want to display a transparent PNG exactly as it should look. There are no controls on the form other than an image gadget currently.
There's also the LWA_ALPHA option, but apparently that just makes the whole window partially transparent. My goal is something like the program called Rainmeter.

Side question: If I'm able to achieve this, does drawing on the alpha PNG with 2D drawing functions void the alpha channel? Cause I want to draw extra stuff on top of the PNG programmatically. The extra stuff does not need to be transparent though.
My blog/software site: http://dosaidsoft.com/
BarryG
Addict
Addict
Posts: 3292
Joined: Thu Apr 18, 2019 8:17 am

Re: Transparent PNG alpha channel window

Post by BarryG »

What do you mean? I display transparent PNGs with its alpha channel transparent all the time. Is that what you mean? You still need #LWA_COLORKEY to make the window transparent, but the color used for that doesn't have to match the alpha channel of the PNG. Just load the PNG and show it on the transparent window, like this:

Code: Select all

UsePNGImageDecoder()
LoadImage(0,"My_Transparent_PNG_Image.png")

OpenWindow(0,200,65,400,300,"test",#PB_Window_BorderLess)
StickyWindow(0,1)

hWnd=WindowID(0)
SetWindowColor(0,#Blue) ; Color used by #LWA_COLORKEY below (not the PNG's alpha channel).
SetWindowLongPtr_(hWnd,#GWL_EXSTYLE,GetWindowLongPtr_(hWnd,#GWL_EXSTYLE)|#WS_EX_LAYERED)
SetLayeredWindowAttributes_(hWnd,#Blue,0,#LWA_COLORKEY)

ImageGadget(0,10,10,0,0,ImageID(0))

Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
OgreVorbis
User
User
Posts: 77
Joined: Thu Jan 16, 2020 10:47 pm

Re: Transparent PNG alpha channel window

Post by OgreVorbis »

BarryG wrote: Sat Mar 05, 2022 5:36 am What do you mean? I display transparent PNGs with its alpha channel transparent all the time. Is that what you mean? You still need #LWA_COLORKEY to make the window transparent, but the color used for that doesn't have to match the alpha channel of the PNG. Just load the PNG and show it on the transparent window, like this:
I tried that with one of my PNGs and it doesn't work. It's only fully transparent or not transparent. As I said, it needs to be partially transparent. Could you please upload the PNG you used for the test because it's not working for me. Maybe there is something wrong with my PNG file. It's made with paint.net and displays proper transparency in other image programs.
My blog/software site: http://dosaidsoft.com/
BarryG
Addict
Addict
Posts: 3292
Joined: Thu Apr 18, 2019 8:17 am

Re: Transparent PNG alpha channel window

Post by BarryG »

I don't know if uploading it somewhere will re-encode the PNG, so I put it in a zip file here:

https://drive.google.com/file/d/1kYhEIw ... sp=sharing

Run it with my test code above, and this is how it appears on my desktop:

Image
OgreVorbis
User
User
Posts: 77
Joined: Thu Jan 16, 2020 10:47 pm

Re: Transparent PNG alpha channel window

Post by OgreVorbis »

BarryG wrote: Sat Mar 05, 2022 7:44 am
Run it with my test code above, and this is how it appears on my desktop:
You must not understand the question. What you are showing me has already been done.
The problem is it doesn't work with PARTIAL transparency. Open that image in paint.net or equivalent software and apply a transparency level of 128 for example, you will see it is NOT transparent.
My blog/software site: http://dosaidsoft.com/
BarryG
Addict
Addict
Posts: 3292
Joined: Thu Apr 18, 2019 8:17 am

Re: Transparent PNG alpha channel window

Post by BarryG »

OgreVorbis wrote: Sat Mar 05, 2022 7:57 amYou must not understand the question.
Sorry!
User avatar
chi
Addict
Addict
Posts: 1028
Joined: Sat May 05, 2007 5:31 pm
Location: Linz, Austria

Re: Transparent PNG alpha channel window

Post by chi »

Search for "UpdateLayeredWindow"
Et cetera is my worst enemy
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8425
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Transparent PNG alpha channel window

Post by netmaestro »

Try this out:

Code: Select all

; Requires PB 5.10 or newer

Declare PreMultiply(image)

CreateImage(0,64,64,32,#PB_Image_Transparent)
StartVectorDrawing(ImageVectorOutput(0))
AddPathBox(0,0,64,64)
VectorSourceColor(RGBA(255,0,0,128))
FillPath()
AddPathBox(16,16,32,32)
VectorSourceColor(RGBA(0,0,255,255))
FillPath()
StopVectorDrawing()

;PreMultiply(0) ; Only use this if the image is brought in with UsePngImageDecoder()

OpenWindow(0,0,0,ImageWidth(0),ImageHeight(0),"",#PB_Window_BorderLess|#PB_Window_ScreenCentered)
SetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE, GetWindowLongPtr_(WindowID(0), #GWL_EXSTYLE)|#WS_EX_LAYERED|#WS_EX_TOOLWINDOW)

hDC = StartDrawing(ImageOutput(0)) 
  With sz.SIZE
    \cx = ImageWidth(0)
    \cy = ImageHeight(0)
  EndWith
  With BlendMode.BLENDFUNCTION 
    \SourceConstantAlpha = 255 
    \AlphaFormat = 1
  EndWith
  UpdateLayeredWindow_(WindowID(0),0,0,@sz,hDC,@ContextOffset.POINT,0,@BlendMode,2)
StopDrawing() 

Repeat
  ev=WaitWindowEvent()
  Select ev
    Case #WM_LBUTTONDOWN
      SendMessage_(WindowID(0), #WM_NCLBUTTONDOWN, #HTCAPTION, 0)
    Case #PB_Event_RightClick
      CloseWindow(0)
      End
    EndSelect
Until ev = #PB_Event_CloseWindow

Procedure PreMultiply(image)
  StartDrawing(ImageOutput(image))
    DrawingMode(#PB_2DDrawing_AllChannels)
    For j=0 To ImageHeight(image)-1
      For i=0 To ImageWidth(image)-1
        color = Point(i,j)
        Plot(i,j, RGBA(Red(color)   & $FF * Alpha(color) & $FF / $FF,
                       Green(color) & $FF * Alpha(color) & $FF / $FF,
                       Blue(color)  & $FF * Alpha(color) & $FF / $FF,
                       Alpha(color)))
      Next
    Next
  StopDrawing()
EndProcedure
BERESHEIT
punak
User
User
Posts: 63
Joined: Tue Sep 07, 2021 12:08 pm

Re: Transparent PNG alpha channel window

Post by punak »

@netmaestro : thanks for your codes, I think these codes have the potential to make aero glass windows. :D now i want to create a frosted glass window. what changes should be made to the code for this purpose?

like this :
Image

i use this image:
https://www.pngkit.com/view/u2t4r5y3e6u ... ffect-png/

and this codes

Code: Select all

Enumeration 
  #GlassWin
  #ControlsWin
  #AeroGlassImg
  #CalendarGadget
EndEnumeration

Declare PreMultiply(image)
Define ev, hdc, sz.SIZE, BlendMode.BLENDFUNCTION, ContextOffset.POINT

UsePNGImageDecoder()
LoadImage(#AeroGlassImg,"a.png")

Procedure ControlsWinCB()
  ResizeWindow(#ControlsWin,WindowX(#GlassWin), WindowY(#GlassWin), WindowWidth(#GlassWin), WindowHeight(#GlassWin))
EndProcedure

PreMultiply(#AeroGlassImg) 

OpenWindow(#GlassWin,0,0,ImageWidth(#AeroGlassImg),ImageHeight(#AeroGlassImg),"",#PB_Window_BorderLess|#PB_Window_ScreenCentered)
SetWindowLongPtr_(WindowID(#GlassWin), #GWL_EXSTYLE, GetWindowLongPtr_(WindowID(#GlassWin), #GWL_EXSTYLE)|#WS_EX_LAYERED|#WS_EX_TOOLWINDOW)
StickyWindow(#GlassWin, #True) 


hDC = StartDrawing(ImageOutput(#AeroGlassImg)) 
With sz
  \cx = ImageWidth(#AeroGlassImg)
  \cy = ImageHeight(#AeroGlassImg)
EndWith
With BlendMode 
  \SourceConstantAlpha = 255 
  \AlphaFormat = 1
EndWith

UpdateLayeredWindow_(WindowID(#GlassWin),0,0,@sz,hDC,@ContextOffset,0,@BlendMode,2)
StopDrawing()

OpenWindow(#ControlsWin, WindowX(#GlassWin), WindowY(#GlassWin), WindowWidth(#GlassWin), WindowHeight(#GlassWin), "", #PB_Window_BorderLess|#PB_Window_Invisible,WindowID(#GlassWin))
SetWindowColor(#ControlsWin, #Green)
SetWindowLong_(WindowID(#ControlsWin), #GWL_EXSTYLE, #WS_EX_LAYERED|#WS_EX_TOPMOST)
SetLayeredWindowAttributes_(WindowID(#ControlsWin), #Green, 255, #LWA_COLORKEY) 

CalendarGadget(#CalendarGadget,100,100,250,200)
HideWindow(#ControlsWin, #False) 

BindEvent(#PB_Event_MoveWindow,@ControlsWinCB())
SetActiveWindow(#GlassWin)  

Repeat
  ev=WaitWindowEvent()
  Select ev
    Case #WM_LBUTTONDOWN
      SendMessage_(WindowID(#GlassWin), #WM_NCLBUTTONDOWN, #HTCAPTION, 0)
    Case #PB_Event_RightClick
      CloseWindow(#ControlsWin)
      CloseWindow(#GlassWin)
      End
  EndSelect
Until ev = #PB_Event_CloseWindow

Procedure PreMultiply(image)
  StartDrawing(ImageOutput(image))
  DrawingMode(#PB_2DDrawing_AllChannels)
  For j=0 To ImageHeight(image)-1
    For i=0 To ImageWidth(image)-1
      color = Point(i,j)
      Plot(i,j, RGBA(Red(color)   & $FF * Alpha(color) & $FF / $FF,
                     Green(color) & $FF * Alpha(color) & $FF / $FF,
                     Blue(color)  & $FF * Alpha(color) & $FF / $FF,
                     Alpha(color)))
    Next
  Next
  StopDrawing()
EndProcedure
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8425
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Transparent PNG alpha channel window

Post by netmaestro »

I am working on a demo code for you, should be ready sometime in the next day or so. In the meantime, here's the basic method in a nutshell:

1. Create a transparent image of the desired dimensions
2. Draw a white box to it with an alpha value of around 140 (or whatever looks good to you). A slight tint might be desirable, up to you.
3. Decide where on the screen you want your frosted glass
4. Take a screenshot of this rectangle
5. Apply a gaussian blur to the screenshot
6. Create an output image same size
7. Draw the blurred image on it
8. Draw the alpha image on it
9. Render the output image to the screen

The result will be a rectangle with a frosted glass appearance, with contents under the glass looking somewhat blurry. If you draw a bathroom or something this could go over top of it in case anyone goes in there. Anyway look for some demo code in the next day or two.

As I am almost criminally lazy I'm going to wait until Keya isn't looking and steal his blur code from:

https://www.purebasic.fr/english/viewtopic.php?p=577063

Because he did an excellent job and I'm tired of reinventing wheels.
BERESHEIT
punak
User
User
Posts: 63
Joined: Tue Sep 07, 2021 12:08 pm

Re: Transparent PNG alpha channel window

Post by punak »

@netmaestro : thank you for your effort, I can't wait... :D
acreis
Enthusiast
Enthusiast
Posts: 182
Joined: Fri Jun 01, 2012 12:20 am

Re: Transparent PNG alpha channel window

Post by acreis »

Me too
BarryG
Addict
Addict
Posts: 3292
Joined: Thu Apr 18, 2019 8:17 am

Re: Transparent PNG alpha channel window

Post by BarryG »

+1
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8425
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Transparent PNG alpha channel window

Post by netmaestro »

I'm still fighting to achieve this. I've been on it all weekend with only limited success. There are two basic problems: 1) How to achieve faster performance for the blur and 2) How to grab a screenshot beneath my own window without including my window in it. Microsoft made a perfect solution in Vista with the DwmEnableBlurBehindWindow function (dwmapi.dll) and screenshots of it working look excellent. But while the API runs successfully it no longer blurs the area behind the window starting with Windows 8 because they changed the way windows are drawn. If anyone is able to assist with either of these two issues, your input would be very welcome. I'm not giving up on this.
BERESHEIT
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8425
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Transparent PNG alpha channel window

Post by netmaestro »

Okay I have a couple of ideas. On the blur speed, I've submitted Keya's blur code to wilbert, if he can't speed it up no one can. On screenshotting the area under my window without including my window I can remove the whole client area using SetWindowRgn_() and my client area bits can't interfere with anything if they aren't there. Starting to look hopeful now.
BERESHEIT
Post Reply