IsAlphaBitmap(hBM) : Returns true if a GDI Bitmap is alpha transparent

Post your working scripts, libraries and tools
User avatar
SKAN
Posts: 820
Joined: 29 Sep 2013, 16:58

IsAlphaBitmap(hBM) : Returns true if a GDI Bitmap is alpha transparent

11 Sep 2020, 16:47

The function:
 

Code: Select all

IsAlphaBitmap(sBM) {                                        ; v0.95 by SKAN on D39C/D39O @ tiny.cc/t80920
Local
  VarSetCapacity(BITMAP, 32, 0)
  Res := DllCall("GetObject", "Ptr",sBM, "Int",A_PtrSize=8? 32:24, "Ptr",&BITMAP)
  Bpp := NumGet(BITMAP,18,"UShort")
  If (Res=0|| Bpp<32)
    Return 0

  W := NumGet(BITMAP,04,"UInt"), Plane := NumGet(BITMAP,16,"UShort"),  WBytes := NumGet(BITMAP,12,"UInt")
  H := NumGet(BITMAP,08,"UInt"), Bytes := WBytes*H,                    HalfSz := Bytes/2
  VarSetCapacity(BITMAPINFO, 40, 0), pBits:=0
  NumPut(Bpp,NumPut(Plane,NumPut(0-H,NumPut(W,NumPut(40,BITMAPINFO,"Int"),"Int"),"Int"),"Short"),"Short")
  tBM := DllCall("CreateDIBSection"
               , "Ptr",0, "Ptr",&BITMAPINFO, "Int",0, "PtrP",pBits, "Ptr",0, "Int", 0, "Ptr")
  tDC := DllCall("CreateCompatibleDC", "Ptr",0, "Ptr"),  DllCall("SaveDC", "Ptr",tDC)
  sDC := DllCall("CreateCompatibleDC", "Ptr",0, "Ptr"),  DllCall("SaveDC", "Ptr",sDC)
  DllCall("SelectObject", "Ptr",tDC, "Ptr",tBM)
  DllCall("SelectObject", "Ptr",sDC, "Ptr",sBM)
  DllCall("GdiAlphaBlend", "Ptr",tDC, "Int",0, "Int",0, "Int",W, "Int",H
                         , "Ptr",sDC, "Int",0, "Int",0, "Int",W, "Int",H, "Int",0x01FF0000)
  DllCall("RestoreDC", "Ptr",sDC, "Int",-1),             DllCall("DeleteDC", "Ptr",sDC)
  DllCall("RestoreDC", "Ptr",tDC, "Int",-1),             DllCall("DeleteDC", "Ptr",tDC)
  IsAplha := NumGet(pBits+0,"UInt") ? 1
          :  !(DllCall("ntdll\RtlCompareMemory", "Ptr",pBits, "Ptr",pBits+1, "Ptr",Bytes-1)=Bytes-1)
  DllCall("DeleteObject", "Ptr",tBM)
Return IsAplha
}
 
Thanks to @just me for all the help.
 
 
Old post moved here
iseahound
Posts: 614
Joined: 13 Aug 2016, 21:04
GitHub: iseahound

Re: IsAlphaBitmap() : Returns true if hBitmap is alpha transparent

11 Sep 2020, 18:45

Thanks for this function! I was stumped that Windows didn't have a solution to checking the alpha channel of a bitmap for transparency. However, I doubt that there is any faster method than going through every pixel BBGGRRAA | 0xFF and checking if it is equal to 255. Did you benchmark it?
User avatar
SKAN
Posts: 820
Joined: 29 Sep 2013, 16:58

Re: IsAlphaBitmap() : Returns true if hBitmap is alpha transparent

11 Sep 2020, 19:41

iseahound wrote:However, I doubt that there is any faster method than going through every pixel BBGGRRAA | 0xFF and checking if it is equal to 255.
Yes. It should be faster for a hBitmap that has a DIB section.. but what about DDB? Probably, I would have to use CopyImage() to convert it to DIB,
in which case, IsAlphaBitmap() is a better option.
iseahound wrote:Did you benchmark it?
On my old/slow machine it takes about 28ms for a full HD image (1920x1080).. only if it has alpha.. otherwise 15ms.
Anybody can test. Create and load a large 24bpp BMP with LoadPicture() with GDI+ in options. Guaranteed alpha.
Without GDI+, definitely non-alpha.

:) :thumbup:
Helgef
Posts: 4462
Joined: 17 Jul 2016, 01:02
Contact:

Re: IsAlphaBitmap() : Returns true if hBitmap is alpha transparent

12 Sep 2020, 06:09

The function can fail in case of interruptions. You can use critical to ensure no other thread destroy the gui before the function returns. Or use a unique gui for each call.

Cheers.
User avatar
SKAN
Posts: 820
Joined: 29 Sep 2013, 16:58

IsAlphaBitmap() : Code updated.

14 Sep 2020, 06:29

Helgef wrote: The function can fail in case of interruptions. You can use critical to ensure no other thread destroy the gui before the function returns. Or use a unique gui for each call.
Cheers.
 

Clarification: Helgef was commenting on the following (previous) version.

Code: Select all

IsAlphaBitmap(hBM) {                    ; by SKAN on D39C/D39C
Local                                   ; @ https://www.autohotkey.com/boards/viewtopic.php?&t=80920
  If (DllCall("GetObjectType", "Ptr",hBM) != 7) ; OBJ_BITMAP
     Return
  Gui, __IsAlphaBitmap:New
  Gui, __IsAlphaBitmap:Add, Picture, w0 h0 hWndhWnd 0x4E ; SS_REALSIZECONTROL|SS_BITMAP
  hBM1 := DllCall("SendMessage", "Ptr",hWnd, "Int",0x172, "Ptr",0, "Ptr",hBM, "UPtr") ; STM_SETIMAGE
  hBM2 := DllCall("SendMessage", "Ptr",hWnd, "Int",0x172, "Ptr",0, "Ptr",0x0, "UPtr") ; STM_SETIMAGE
  Gui, __IsAlphaBitmap:Destroy
Return (hBM2!=hBM) ? DllCall("DeleteObject", "Ptr",hBM2) : 0
}
 
Thanks @Helgef :thumbup: :)
The function was setting default GUI, and so, I have resorted to CreateWindowEx() in current version.

 
Code updated.
User avatar
SKAN
Posts: 820
Joined: 29 Sep 2013, 16:58

Re: IsAlphaBitmap(hBM) : Returns true if a GDI Bitmap is alpha transparent

21 Sep 2020, 19:37

Backup of previous post : IsAlphaBitmap() v0.50
just me
Posts: 7305
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: IsAlphaBitmap(hBM) : Returns true if a GDI Bitmap is alpha transparent

22 Sep 2020, 08:00

Hi SKAN,

if I run your latest version with the PixelData4 example from CreateDDB() the bitmap is not classified as alpha. Is this intended?

Code: Select all

#NoEnv
PixelData4 := "
( LTrim Join|
  00FFFFFF|FF000000|00FFFFFF|FF000000|00FFFFFF|FF000000|00FFFFFF|FF000000
  FF000000|00FFFFFF|FF000000|00FFFFFF|FF000000|00FFFFFF|FF000000|00FFFFFF
  00FFFFFF|FF000000|00FFFFFF|FF000000|00FFFFFF|FF000000|00FFFFFF|FF000000
  FF000000|00FFFFFF|FF000000|00FFFFFF|FF000000|00FFFFFF|FF000000|00FFFFFF
  00FFFFFF|FF000000|00FFFFFF|FF000000|00FFFFFF|FF000000|00FFFFFF|FF000000
  FF000000|00FFFFFF|FF000000|00FFFFFF|FF000000|00FFFFFF|FF000000|00FFFFFF
  00FFFFFF|FF000000|00FFFFFF|FF000000|00FFFFFF|FF000000|00FFFFFF|FF000000
  FF000000|00FFFFFF|FF000000|00FFFFFF|FF000000|00FFFFFF|FF000000|00FFFFFF
)"
HBM := CreateDDB(PixelData4, 8, 8)
MsgBox, 0, IsAlphaBitmap, % IsAlphaBitmap(HBM)
Gui, Color, Silver
Gui, Add, Pic, w240 h240 +0x4E +Border hwndHPIC
GuiControl, , %HPIC%, *w0 *h0 HBITMAP:%hBM%
Gui, Show, , Alpha Test
Return
GuiClose:
ExitApp

CreateDDB(PixelData, W, H) {                                  ; v0.50 by SKAN on D39B/D39C
Local n:=VarSetCapacity(BMBITS, W*H*4),  pBMBITS:=&BMBITS     ;        @ tiny.cc/createddb
  Loop, Parse, PixelData, |, %A_Space%
    pBMBITS := NumPut("0x" . A_LoopField, pBMBITS+0, "Int")
Return DllCall("CreateBitmap", "Int",W, "Int",H, "Int",1, "Int",32, "Ptr",&BMBITS, "UPtr")
}

IsAlphaBitmap(sBM) {                              ; v0.90 by SKAN on D39C/D39L @ tiny.cc/t80920
Local
  sDC := DllCall("CreateCompatibleDC", "Ptr",0, "Ptr")
, DllCall("SaveDC", "Ptr",sDC)
, DllCall("SelectObject", "Ptr",sDC, "Ptr",sBM, "Ptr")
, tDC := DllCall("CreateCompatibleDC", "Ptr",0, "Ptr")
  While ( (I:=A_Index)<3 )
     DllCall("SaveDC", "Ptr",tDC)
  ,  tBM%I% := DllCall("CreateBitmap", "Int",1, "Int",1, "Int",1, "Int",32, "PtrP",I, "Ptr")
  ,  DllCall("SelectObject", "Ptr",tDC, "Ptr",tBM%I%, "Ptr")
  ,  DllCall("GdiAlphaBlend", "Ptr",tDC, "Int",0, "Int",0, "Int",1, "Int",1, "Ptr",sDC, "Int",0
                                       , "Int",0, "Int",1, "Int",1, "Int",0x01FF0000)
  ,  Color%A_Index% := DllCall("GetPixel", "Ptr",tDC, "Int",0, "Int",0, "UInt")
  ,  DllCall("RestoreDC", "Ptr",tDC, "Int",-1)
  ,  DllCall("DeleteObject", "Ptr",tBM%I%)
  DllCall("RestoreDC", "Ptr",sDC, "Int",-1)
, DllCall("DeleteDC","Ptr",sDC)
, DllCall("DeleteDC","Ptr",tDC)
Return !(Color1=0x010000 && Color2=0x020000)
}
User avatar
SKAN
Posts: 820
Joined: 29 Sep 2013, 16:58

Re: IsAlphaBitmap(hBM) : Returns true if a GDI Bitmap is alpha transparent

22 Sep 2020, 08:57

just me wrote: if I run your latest version with the PixelData4 example from CreateDBB() the bitmap is not classified as alpha. Is this intended?
:( :( :(

Obviously the first pixel doesn't have Alpha set.
I badly needed this for converting hBitmap to pBitmap :(
Guess, I'll have to check all the bits.. I think I know a way to do that without loop.

Thank you very much for the feedback :) :thumbup:
just me
Posts: 7305
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: IsAlphaBitmap(hBM) : Returns true if a GDI Bitmap is alpha transparent

23 Sep 2020, 10:19

Very good! :thumbup:
BTW: Shouldn't the DIB be deleted?
User avatar
SKAN
Posts: 820
Joined: 29 Sep 2013, 16:58

GdiPlus_CreateBitmapFromHBITMAP()

23 Sep 2020, 15:27

just me wrote: Very good! :thumbup:
BTW: Shouldn't the DIB be deleted?
Thanks, fixed. :oops: :thumbup:.
 
Temporarily posting here GdiPlus_CreateBitmapFromHBITMAP() which is the base for IsAlphaBitmap()
This function will detect and convert GDI alpha bitmap to GDIPlus bitmap with alpha transparency.

Code: Select all

GdiPlus_CreateBitmapFromHBITMAP(sBM, hPal:=0) { ; By SKAN on D39K/D39L  @ tiny.cc/gdiplus
Local
  VarSetCapacity(BITMAP, 32, 0)
  If !DllCall("GetObject", "Ptr",sBM, "Int",A_PtrSize=8? 32:24, "Ptr",&BITMAP)
    Return 0

  W := NumGet(BITMAP, 04, "UInt"),   Planes := NumGet(BITMAP, 16, "UShort"),   Stride := NumGet(BITMAP, 12, "UInt")
  H := NumGet(BITMAP, 08, "UInt"),   Bpp    := NumGet(BITMAP, 18, "UShort"),   Bytes  := Stride * H

  If (Bpp<32)
  Return !DllCall("GdiPlus\GdipCreateBitmapFromHBITMAP", "Ptr",sBM, "Ptr",hPal, "PtrP",pBitmap:=0) ? pBitmap : 0

  VarSetCapacity(BITMAPINFO, 40, 0)
  NumPut(BPP, NumPut(Planes,NumPut(0-H,NumPut(W,NumPut(40,BITMAPINFO,"Int"),"Int"),"Int"),"Short"),"Short")
  tBM := DllCall("CreateDIBSection", "Ptr",0, "Ptr",&BITMAPINFO, "Int",0, "PtrP",pBits:=0, "Ptr",0, "Int", 0, "Ptr")

  tDC := DllCall("CreateCompatibleDC", "Ptr",0, "Ptr"),  DllCall("SaveDC", "Ptr",tDC),  DllCall("SelectObject", "Ptr",tDC, "Ptr",tBM)
  sDC := DllCall("CreateCompatibleDC", "Ptr",0, "Ptr"),  DllCall("SaveDC", "Ptr",sDC),  DllCall("SelectObject", "Ptr",sDC, "Ptr",sBM)

  DllCall("GdiAlphaBlend", "Ptr",tDC, "Int",0, "Int",0, "Int",W, "Int",H, "Ptr",sDC, "Int",0, "Int",0, "Int",W, "Int",H, "Int",A:=0x01FF0000)
  If !( Numget(pBits+0,"UInt") || DllCall("ntdll\RtlCompareMemory", "Ptr",pBits, "Ptr",pBits+1, "Ptr",.Bytes-1)=Bytes-1 )
  DllCall("GdiAlphaBlend", "Ptr",tDC, "Int",0, "Int",0, "Int",W, "Int",H, "Ptr",sDC, "Int",0, "Int",0, "Int",W, "Int",H, "Int",A:=0x00FF0000)

  DllCall("RestoreDC", "Ptr",sDC, "Int",-1),  DllCall("DeleteDC", "Ptr",sDC)
  DllCall("RestoreDC", "Ptr",tDC, "Int",-1),  DllCall("DeleteDC", "Ptr",tDC)

  VarSetCapacity(BITMAPDATA, 40, 0), NumPut(Stride, BITMAPDATA, 8, "Int")
  PixelFormat32bppPARGB:=925707, PixelFormat32bppRGB:=139273, PixelFormat := (A=0x01FF0000 ? PixelFormat32bppPARGB : PixelFormat32bppRGB)

  DllCall("GdiPlus\GdipCreateBitmapFromScan0", "Int",W, "Int",H, "Int",0, "Int",PixelFormat, "Ptr",0, "PtrP",pBitmap:=0)
  DllCall("GdiPlus\GdipBitmapLockBits", "Ptr",pBitmap, "Ptr",0, "Int",0x1, "Int",PixelFormat, "Ptr",&BITMAPDATA)
  DllCall("RtlMoveMemory","Ptr",NumGet(BITMAPDATA, 16, "Ptr"), "Ptr",pBits, "Ptr",Bytes)
  DllCall("GdiPlus\GdipBitmapUnlockBits", "Ptr",pBitmap, "Ptr",&BITMAPDATA)
  DllCall("DeleteObject", "Ptr",tBM)
Return pBitmap
}

Return to “Scripts and Functions”

Who is online

Users browsing this forum: thebat and 20 guests