Create an HBitmap with transparency Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Create an HBitmap with transparency

17 May 2020, 23:32

dxgi is pretty good if not for having to port so much ugly com code
its easier to just write a dll wrapper instead
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Create an HBitmap with transparency

18 May 2020, 01:00

malcev wrote: forgot about legacy technologies and OS
If I tell my customers “forget about legacy OS”, they will answer “forget about money”. :lol:
Another interesting example:

Code: Select all

width := 40
height := width*7

Gui, -DPIScale
Gui, Margin, 0, 0
for k, v in [0xFF0000, 0xFFA500, 0xFFFF00, 0x66FF00, 0xBFFF, 0x80, 0x800080, 0xFF0000] {
   Loop 2
      Gui, Add, Pic, % "BackgroundTrans y0 x" . width*(k - A_Index), % "HBITMAP:" . CreateColoredBitmapEx(width, height, v, A_Index - 1)
}
Gui, Show, % "w" . width*7
Return

GuiClose() {
   ExitApp
}

CreateColoredBitmapEx(width, height, color, gradient := false) {
   hBitmap := CreateDIBSection(width, -height,, pBits)
   Loop % height {
      i := A_Index - 1
      Loop % width
         NumPut(gradient ? (color & 0xFFFFFF)|(255/width*A_Index)<<24 : color, pBits + (width*i + A_Index - 1)*4, "UInt")
   }
   Return hBitmap
}

CreateDIBSection(w, h, bpp := 32, ByRef ppvBits := 0)
{
   hdc := DllCall("GetDC", "Ptr", 0, "Ptr")
   VarSetCapacity(bi, 40, 0)
   NumPut( 40, bi,  0, "UInt")
   NumPut(  w, bi,  4, "UInt")
   NumPut(  h, bi,  8, "UInt")
   NumPut(  1, bi, 12, "UShort")
   NumPut(  0, bi, 16, "UInt")
   NumPut(bpp, bi, 14, "UShort")
   hbm := DllCall("CreateDIBSection", "Ptr", hdc, "Ptr", &bi, "UInt", 0, "PtrP", ppvBits, "Ptr", 0, "UInt", 0, "Ptr")
   DllCall("ReleaseDC", "Ptr", 0, "Ptr", hdc)
   return hbm
}
Last edited by teadrinker on 18 May 2020, 05:40, edited 1 time in total.
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Create an HBitmap with transparency

18 May 2020, 04:35

If I tell my customers “forget about legacy OS”, they will answer “forget about money”.
Then You can use Direct2D.
serzh82saratov
Posts: 137
Joined: 01 Jul 2017, 03:04

Re: Create an HBitmap with transparency

18 May 2020, 16:56

malcev wrote:
17 May 2020, 21:03
Transparency with pure GDI
С AlphaBlend на AutoHotkey не встречал рабочих примеров, только обсуждения что что то не получается.
malcev wrote:
17 May 2020, 21:03
serzh82saratov, if You need speed You have to forgot about legacy technologies and OS and use DirectComposition with Direct3D 11 and DXGI like in this example::
dxgi по моему очень сложен в освоении тем более на AutoHotkey, а нормальная обёртка тем более в виде Dll маловероятно что будет сделана.
На Windows 10 конечно очень удобно и просто использовать LayeredChild, но с поддержкой Windows 7 это будет 2 разных кода.
serzh82saratov
Posts: 137
Joined: 01 Jul 2017, 03:04

Re: Create an HBitmap with transparency

18 May 2020, 18:55

Я также искал, но не вижу что можно просто запустить и увидеть результат.
gregster
Posts: 8916
Joined: 30 Sep 2013, 06:48

Re: Create an HBitmap with transparency

18 May 2020, 19:36

Hi @serzh82saratov : Just a friendly reminder to use english in this part of the forum :wave:.
Thank you!
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Create an HBitmap with transparency

18 May 2020, 19:48

An AlphaBlend example. Here we create a DC with opaque green, that is overlapped with a DC with a blue color containing a gradient alpha channel.

Code: Select all

#NoEnv
SetBatchLines, -1

hBitmap := DrawGradient(0x66FF00, 0xBFFF, 300, 300, "v")
Gui, Margin, 0, 0
Gui, Add, Pic,, HBITMAP:%hBitmap%
Gui, Show
Return

GuiClose() {
   ExitApp
}

DrawGradient(colorRGB_1, colorRGB_2, width, height, direction) {
   Loop 2 {
      k := A_Index
      hBitmap%k% := CreateDIBSection(width, height,, pBits%k%)
      Loop % height {
         i := A_Index - 1
         Loop % width {
            if (k = 1)
               color := colorRGB_1 | 0xFF000000
            else {
               alpha := 255/(direction = "h" ? width/A_Index : height/(i + 1))
               r := (colorRGB_2 >> 16)*alpha/0xFF << 16
               g := ((colorRGB_2 >> 8) & 0xFF)*alpha/0xFF << 8
               b := (colorRGB_2 & 0xFF)*alpha/0xFF
               color := (alpha << 24) | r | g | b
            } 
            NumPut(color, pBits%k% + (width*i + A_Index - 1)*4, "UInt")
         }
      }
      hDC%k% := DllCall("CreateCompatibleDC", "Ptr", 0, "Ptr")
      obj%k% := DllCall("SelectObject", "Ptr", hDC%k%, "Ptr", hBitmap%k%)
   }
   DllCall("GdiAlphaBlend", "Ptr", hDC1, "Int", 0, "Int", 0, "Int", width, "Int", height
                          , "Ptr", hDC2, "Int", 0, "Int", 0, "Int", width, "Int", height
                          , "UInt", 255 << 16 | 1 << 24)
   Loop 2 {
      DllCall("SelectObject", "Ptr", hDC%A_Index%, "Ptr", obj%A_Index%)
      DllCall("DeleteDC", "Ptr", hDC%A_Index%)
   }
   DllCall("DeleteObject", "Ptr", hBitmap2)
   Return hBitmap1
}

CreateDIBSection(w, h, bpp := 32, ByRef ppvBits := 0)
{
   hdc := DllCall("GetDC", "Ptr", 0, "Ptr")
   VarSetCapacity(bi, 40, 0)
   NumPut( 40, bi,  0, "UInt")
   NumPut(  w, bi,  4, "UInt")
   NumPut(  h, bi,  8, "UInt")
   NumPut(  1, bi, 12, "UShort")
   NumPut(  0, bi, 16, "UInt")
   NumPut(bpp, bi, 14, "UShort")
   hbm := DllCall("CreateDIBSection", "Ptr", hdc, "Ptr", &bi, "UInt", 0, "PtrP", ppvBits, "Ptr", 0, "UInt", 0, "Ptr")
   DllCall("ReleaseDC", "Ptr", 0, "Ptr", hdc)
   return hbm
}
I would say it is not too convenient method since we have to pre-multiply the color channels.
serzh82saratov
Posts: 137
Joined: 01 Jul 2017, 03:04

Re: Create an HBitmap with transparency

19 May 2020, 06:47

I would say that this is a very expensive method, 10 such small pictures will be created for a very long time.
serzh82saratov
Posts: 137
Joined: 01 Jul 2017, 03:04

Re: Create an HBitmap with transparency

19 May 2020, 06:47

gregster wrote:
18 May 2020, 19:36
Hi @serzh82saratov : Just a friendly reminder to use english in this part of the forum :wave:.
Thank you!
Well, I did not know what this rule was.
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Create an HBitmap with transparency

19 May 2020, 07:34

Optimized a bit:

Code: Select all

#NoEnv
SetBatchLines, -1

hBitmap := DrawGradient(0x66FF00, 0xBFFF, 300, 300, "v")
Gui, Margin, 0, 0
Gui, Add, Pic,, HBITMAP:%hBitmap%
Gui, Show
Return

GuiClose() {
   ExitApp
}

DrawGradient(colorRGB_1, colorRGB_2, width, height, direction) {
   colorRGB_1 |= 0xFF000000
   r := colorRGB_2 >> 16
   g := (colorRGB_2 >> 8) & 0xFF
   b := colorRGB_2 & 0xFF
   Loop 2 {
      k := A_Index
      hBitmap%k% := CreateDIBSection(width, height,, pBits%k%)
      Loop % height {
         i := A_Index
         Loop % width {
            if (k = 1)
               color := colorRGB_1
            else {
               alpha := 255/(direction = "h" ? width/A_Index : height/i)
               factor := alpha/0xFF
               color := alpha << 24 | r*factor << 16 | g*factor << 8 | b*factor
            } 
            NumPut(color, pBits%k% + (width*(i - 1) + A_Index - 1)*4, "UInt")
         }
      }
      hDC%k% := DllCall("CreateCompatibleDC", "Ptr", 0, "Ptr")
      obj%k% := DllCall("SelectObject", "Ptr", hDC%k%, "Ptr", hBitmap%k%)
   }
   DllCall("GdiAlphaBlend", "Ptr", hDC1, "Int", 0, "Int", 0, "Int", width, "Int", height
                          , "Ptr", hDC2, "Int", 0, "Int", 0, "Int", width, "Int", height
                          , "UInt", 255 << 16 | 1 << 24)
   Loop 2 {
      DllCall("SelectObject", "Ptr", hDC%A_Index%, "Ptr", obj%A_Index%)
      DllCall("DeleteDC", "Ptr", hDC%A_Index%)
   }
   DllCall("DeleteObject", "Ptr", hBitmap2)
   Return hBitmap1
}

CreateDIBSection(w, h, bpp := 32, ByRef ppvBits := 0)
{
   hdc := DllCall("GetDC", "Ptr", 0, "Ptr")
   VarSetCapacity(bi, 40, 0)
   NumPut( 40, bi,  0, "UInt")
   NumPut(  w, bi,  4, "UInt")
   NumPut(  h, bi,  8, "UInt")
   NumPut(  1, bi, 12, "UShort")
   NumPut(  0, bi, 16, "UInt")
   NumPut(bpp, bi, 14, "UShort")
   hbm := DllCall("CreateDIBSection", "Ptr", hdc, "Ptr", &bi, "UInt", 0, "PtrP", ppvBits, "Ptr", 0, "UInt", 0, "Ptr")
   DllCall("ReleaseDC", "Ptr", 0, "Ptr", hdc)
   return hbm
}
iseahound
Posts: 1434
Joined: 13 Aug 2016, 21:04
Contact:

Re: Create an HBitmap with transparency

20 May 2020, 12:07

teadrinker wrote:
12 May 2020, 14:05
Perhaps you want something like this:

Code: Select all

colorWithoutTransparency := 0xC0C0C0
colorWithTransparency := 0x55F000FF
width := 200
height := 200

Gui, Color, FAD886
Gui, Margin, 0, 0
Gui, Add, Pic,, % "HBITMAP:" . CreateColoredBitmap(width, height, colorWithoutTransparency)
Gui, Add, Pic, x100 y100 BackgroundTrans, % "HBITMAP:" . CreateColoredBitmap(width, height, colorWithTransparency)
Gui, Show

CreateColoredBitmap(width, height, color) {
   hBitmap := CreateDIBSection(width, -height,, pBits)
   Loop % height {
      i := A_Index - 1
      Loop % width
         NumPut(color, pBits + width*4*i + (A_Index - 1)*4, "UInt")
   }
   Return hBitmap
}

CreateDIBSection(w, h, bpp := 32, ByRef ppvBits := 0)
{
   hdc := DllCall("GetDC", "Ptr", 0, "Ptr")
   VarSetCapacity(bi, 40, 0)
   NumPut( 40, bi,  0, "UInt")
   NumPut(  w, bi,  4, "UInt")
   NumPut(  h, bi,  8, "UInt")
   NumPut(  1, bi, 12, "UShort")
   NumPut(  0, bi, 16, "UInt")
   NumPut(bpp, bi, 14, "UShort")
   hbm := DllCall("CreateDIBSection", "Ptr", hdc, "Ptr", &bi, "UInt", 0, "PtrP", ppvBits, "Ptr", 0, "UInt", 0, "Ptr")
   DllCall("ReleaseDC", "Ptr", 0, "Ptr", hdc)
   return hbm
}
Edited (2 times)
Use RtlMoveMemory and two unnested loops. One loop to create the width, and a second loop to copy the first over the height. NumPut is too slow.

Also your color value should take a ARGB value and premultiply it to get pARGB. [alpha, alpha*red, alpha*green, alpha*blue]
teadrinker
Posts: 4309
Joined: 29 Mar 2015, 09:41
Contact:

Re: Create an HBitmap with transparency

20 May 2020, 12:26

iseahound wrote: Use RtlMoveMemory and two unnested loops. One loop to create the width, and a second loop to copy the first over the height. NumPut is too slow.
I've already guessed about it. But this method works only if there ara identical lines in the bitmap.
iseahound wrote: Also your color value should take a ARGB value and premultiply it to get pARGB. [alpha, alpha*red, alpha*green, alpha*blue]
Not sure I understand what you mean. Why is it needed in this case?

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Rohwedder and 143 guests