Results 1 to 24 of 24

Thread: [RESOLVED] BitBlt from png with transparency

  1. #1

    Thread Starter
    Lively Member
    Join Date
    May 2022
    Location
    App.Path
    Posts
    66

    Resolved [RESOLVED] BitBlt from png with transparency

    Hello all!

    I am trying to load a from a PNG on disk and then have it ready to BitBlt whenever wherever with transparency support. First thing I tried is AlphaBlendImage but can't get it to work. I tried various other solutions but few worked, and ones that did were not what I wanted. I am about to go crazy!
    Basically, I need to get PNG into a DC, so I can BitBlt with it. Preferably without anti-aliasing or blurring, the PNG is either 16x16 or 32x32. Does anyone know how or can help show how to do this?

    Thanks in advance.

    No, Shaggy Hiker, I am not stealing your signature.

  2. #2
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,871

    Re: BitBlt from png with transparency

    theres multiple ways.
    it all depends on the needs.

    easy and little code u have:
    - DrawIconEx/CreateIconFromResourceEx that can load a PNG and render it, very little code.
    - u have WIA that is quite easy to use. do a forum search for it.

    a bit more involved u have
    - GDI+ that can both load and render. no need for any DC to store the image, as it has its own container.
    - GDI32 (together with GDI+ to load), so its basically two steps. one to load and one to store and render.

    and more involved:
    - Direct2d/WIC to load and render.

    so everything u can find in vbforums. theres multiple threads about any of the methods.
    just do a search and u will find plenty.
    since your question was GDI32 u will need to first LOAD, and that require GDI+ or WIC or another solution.
    and its important u load it and convert it into 32bit and after that u convert it into a gdi bitmap (dc) and use GdiAlphaBlend to render.

    theres plenty of threads for GDI32 and how to load a PNG with transparency

  3. #3
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,416

    Re: BitBlt from png with transparency

    Since it wasn't mentioned above - here's what it looks like, when using the RC6-CairoWrapper:
    Code:
    Private Declare Function GdiAlphaBlend& Lib "gdi32" (ByVal hDC&, ByVal x&, ByVal y&, ByVal dx&, ByVal dy&, ByVal hdcSrc&, ByVal srcx&, ByVal srcy&, ByVal SrcdX&, ByVal SrcdY&, ByVal lBlendFunction&)
    
    Private Sub Form_Load()
      Cairo.ImageList.AddImage "MyPngKey1", "c:\temp\test.png" 'load and buffer the resource
      Caption = "Click Me"
    End Sub
    
    Private Sub Form_Click()
      AlphaRenderFromResourceTo Me.hDC, 10, 10, "MyPngKey1"
    End Sub
    
    Sub AlphaRenderFromResourceTo(ByVal hDC As Long, x, y, ImgKey As String)
      Dim Src As cCairoSurface: Set Src = Cairo.ImageList(ImgKey)
      With Cairo.CreateWin32Surface(Src.Width, Src.Height)
          .CreateContext.RenderSurfaceContent Src, 0, 0
          GdiAlphaBlend hDC, x, y, .Width, .Height, .GetDC, 0, 0, .Width, .Height, 2 ^ 24 + &HFF0000
      End With
    End Sub
    Olaf

  4. #4

    Thread Starter
    Lively Member
    Join Date
    May 2022
    Location
    App.Path
    Posts
    66

    Re: BitBlt from png with transparency

    Quote Originally Posted by baka View Post
    easy and little code u have:
    - DrawIconEx/CreateIconFromResourceEx that can load a PNG and render it, very little code.
    How would I do this? As far as I can tell it is only for icon resources?

    No, Shaggy Hiker, I am not stealing your signature.

  5. #5
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,871

    Re: BitBlt from png with transparency

    if u do a search u find the answer

    u can use CreateIconFromResourceEx to take a bytearray

    hIcon = CreateIconFromResourceEx(bytes(0), UBound(bytes) + 1, 1, &H30000, width, height, 0)

    so basically u load a png into a byte array and create a hicon that way
    the same u can do from resource as well

    after that just place it

    DrawIconEx Me.Hdc, 0, 0, hIcon, width, height, 0, 0, 3

  6. #6

    Thread Starter
    Lively Member
    Join Date
    May 2022
    Location
    App.Path
    Posts
    66

    Re: BitBlt from png with transparency

    Hello baka. I cannot get it to work. CreateIconFromResourceEx just returns 0. GetLastError also returns 0.
    I think my problem is similiar to this thread? https://www.vbforums.com/showthread....Ex-not-working

    Here I have posted my code:

    VB Code:
    1. 'Form path to read from
    2.         sPath = App.Path & "\textures\grid.png"
    3.        
    4.         'Get data into array
    5.         nFile = FreeFile
    6.         Open sPath For Binary Access Read As #nFile
    7.         If LOF(nFile) > 0 Then
    8.             ReDim PNG(0 To LOF(nFile) - 1)
    9.             Get nFile, , PNG
    10.         Else
    11.             Close #nFile
    12.             Kill sPath
    13.             MsgBox "Texture grid.png missing or empty.", vbOKOnly, "Texture Missing"
    14.             Exit Sub
    15.         End If
    16.         Close #nFile
    17.        
    18.         'Create icon
    19.         'hGridIcon always 0
    20.         hGridIcon = CreateIconFromResourceEx(PNG(0), UBound(PNG) + 1, 1, &H30000, 16, 16, 0)

    No, Shaggy Hiker, I am not stealing your signature.

  7. #7
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,871

    Re: BitBlt from png with transparency

    need to use the correct API declaration.
    and of course u need to use autoredraw=true

    Code:
    Private Declare Function CreateIconFromResourceEx Lib "user32" (ByRef presbits As Byte, ByVal dwResSize As Long, ByVal fIcon As Long, ByVal dwVer As Long, ByVal cxDesired As Long, ByVal cyDesired As Long, ByVal Flags As Long) As Long
    Private Declare Function DrawIconEx Lib "user32" (ByVal Hdc As Long, ByVal xLeft As Long, ByVal yTop As Long, ByVal hIcon As Long, ByVal cxWidth As Long, ByVal cyWidth As Long, ByVal istepIfAniCur As Long, ByVal hbrFlickerFreeDraw As Long, ByVal diFlags As Long) As Long
    Private Declare Function DestroyIcon Lib "user32.dll" (ByVal hIcon As Long) As Long
    
    Private Sub Form_Load()
        Dim Data() As Byte
        Dim hIcon As Long
        Dim Width As Long
        Dim Height As Long
        
        Open "C:\pictures\picture.png" For Binary As #1
            ReDim Data(1 To LOF(1))
            Get #1, , Data
        Close #1
        
        ' Get Dimension from PNG-Header (Assuming its a correct PNG
        Width = Data(17) * 16777216 + Data(18) * 65536 + Data(19) * 256 + Data(20)
        Height = Data(21) * 16777216 + Data(22) * 65536 + Data(23) * 256 + Data(24)
    
        Me.AutoRedraw = True
        hIcon = CreateIconFromResourceEx(Data(1), UBound(Data), 1, &H30000, Width, Height, 0)
        DrawIconEx Me.Hdc, 0, 0, hIcon, Width, Height, 0, 0, 3
        DestroyIcon hIcon
    End Sub
    Last edited by baka; Oct 12th, 2024 at 06:39 AM.

  8. #8

    Thread Starter
    Lively Member
    Join Date
    May 2022
    Location
    App.Path
    Posts
    66

    Re: BitBlt from png with transparency

    Hello baka, I put your code in a new form and it does not work. (hIcon still 0)
    I have seen some sites mention that support for PNGs in CreateIconFromResourceEx was added in Vista. Will it not work with previous versions?

    Edit: Just tried on Windows 7 and still did not work.
    Last edited by OrangeBlaze; Oct 12th, 2024 at 11:47 AM.

    No, Shaggy Hiker, I am not stealing your signature.

  9. #9
    PowerPoster
    Join Date
    Jan 2020
    Posts
    4,480

    Re: BitBlt from png with transparency

    DrawIconEx, this will also cause the picture to be not smooth and blurred when it is zoomed out.

  10. #10
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,871

    Re: BitBlt from png with transparency

    are you messing with me? Im quite tired of this sh*t.
    not sure what u are doing but the problem its u. u are doing something wrong.

    and if u expect this to work in windows 95/98 of course it will not.
    this was introduced with windows 2000 (so it works in xp/vista) u can not expect us to help u with ancient compatibility.
    and U need to add that in your OP if u require such things. Im out, can't help people like u.

  11. #11
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,545

    Re: BitBlt from png with transparency

    Quote Originally Posted by OrangeBlaze View Post
    Hello baka, I put your code in a new form and it does not work. (hIcon still 0)
    I have seen some sites mention that support for PNGs in CreateIconFromResourceEx was added in Vista. Will it not work with previous versions?

    Edit: Just tried on Windows 7 and still did not work.
    Btw, baka's sample code works beautifully here on Win11.

    So you are targeting XP or Win9x? Which one it is?

    AlphaBlend API works on XP so does GDI+ for decoding the PNG. Your best bet would be to decode the PNG to a 32-bit alpha transparent DIB (precomputed alpha, so called PARGB pixels) and then AlphaBlend from it into your DC.

    You have to use AlphaBlend. You cannot use BitBlt and expect transparency, no idea where your confusion about this API comes from.

    cheers,
    </wqw>

  12. #12
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,871

    Re: BitBlt from png with transparency

    not sure what u try to do.
    but this works in windows 7-11 (I know as I have windows 7 and 10 installed) probably xp-vista as well (but can't say 100% since I don't have those anymore)

    the problem is u.
    so instead of saying nothing work, show what u are doing. YOUR CODE.
    Im sure theres something wrong with that. maybe that PNG is not a PNG at all. who knows.

  13. #13
    PowerPoster VanGoghGaming's Avatar
    Join Date
    Jan 2020
    Location
    Eve Online - Mining, Missions & Market Trading!
    Posts
    2,119

    Lightbulb Re: BitBlt from png with transparency

    MSDN does mention that: "Since Windows Vista RT_ICON icon or RT_CURSOR cursor resource may contain PNG-compressed image data."

    Just tested this code on Windows 10 and it works correctly (the PNG is drawn on the form):

    Code:
    Private Declare Function CreateIconFromResourceEx Lib "user32" (presbits As Any, ByVal dwResSize As Long, ByVal fIcon As Long, ByVal dwVer As Long, ByVal cxDesired As Long, ByVal cyDesired As Long, ByVal Flags As Long) As Long
    Private Declare Function DrawIconEx Lib "user32" (ByVal hDC As Long, ByVal xLeft As Long, ByVal yTop As Long, ByVal hIcon As Long, ByVal cxWidth As Long, ByVal cyWidth As Long, ByVal istepIfAniCur As Long, ByVal hbrFlickerFreeDraw As Long, ByVal diFlags As Long) As Long
    Private Declare Function DestroyIcon Lib "user32" (ByVal hIcon As Long) As Long
    
    Private Sub Form_Load()
    Dim hIcon As Long, baData() As Byte
        AutoRedraw = True
        With New WIA.ImageFile
            .LoadFile "Picture.png"
            baData = .FileData.BinaryData
            hIcon = CreateIconFromResourceEx(baData(0), .FileData.Count, 1, &H30000, .Width, .Height, 0)
            If hIcon Then
                DrawIconEx hDC, 0, 0, hIcon, .Width, .Height, 0, 0, 3
                DestroyIcon hIcon
            End If
        End With
    End Sub

  14. #14
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,545

    Re: BitBlt from png with transparency

    This works on XP using GDI+

    Code:
    Option Explicit
    
    Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
    Private Declare Function GdiplusStartup Lib "gdiplus" (hToken As Long, pInputBuf As Any, Optional ByVal pOutputBuf As Long = 0) As Long
    Private Declare Function GdipLoadImageFromFile Lib "gdiplus" (ByVal sFileName As Long, mImage As Long) As Long
    Private Declare Function GdipGetImageDimension Lib "gdiplus" (ByVal hImage As Long, nWidth As Single, nHeight As Single) As Long   '
    Private Declare Function GdipDisposeImage Lib "gdiplus" (ByVal hImage As Long) As Long
    Private Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hDC As Long, hGraphics As Long) As Long
    Private Declare Function GdipDeleteGraphics Lib "gdiplus" (ByVal hGraphics As Long) As Long
    Private Declare Function GdipDrawImageRectRect Lib "gdiplus" (ByVal hGraphics As Long, ByVal hImage As Long, ByVal dstX As Single, ByVal dstY As Single, ByVal dstWidth As Single, ByVal dstHeight As Single, ByVal srcX As Single, ByVal srcY As Single, ByVal srcWidth As Single, ByVal srcHeight As Single, Optional ByVal srcUnit As Long = 2, Optional ByVal hImageAttributes As Long, Optional ByVal pfnCallback As Long, Optional ByVal lCallbackData As Long) As Long
    
    Private Sub Form_Load()
        AutoRedraw = True
        DrawImage App.Path & "\garden.png", hDC
    End Sub
    
    Private Sub DrawImage(sFileName As String, ByVal hDC As Long, Optional ByVal lX As Long, Optional ByVal lY As Long)
        Dim aInput(0 To 3)  As Long
        Dim hBitmap         As Long
        Dim sngWidth        As Single
        Dim sngHeight       As Single
        Dim hGraphics       As Long
        
        If GetModuleHandle("gdiplus") = 0 Then
            aInput(0) = 1
            Call GdiplusStartup(0, aInput(0))
        End If
        Call GdipLoadImageFromFile(StrPtr(sFileName), hBitmap)
        Call GdipGetImageDimension(hBitmap, sngWidth, sngHeight)
        Call GdipCreateFromHDC(hDC, hGraphics)
        Call GdipDrawImageRectRect(hGraphics, hBitmap, lX, lY, sngWidth, sngHeight, 0, 0, sngWidth, sngHeight)
        Call GdipDisposeImage(hBitmap)
        Call GdipDeleteGraphics(hGraphics)
    End Sub
    cheers,
    </wqw>

  15. #15
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,602

    Re: BitBlt from png with transparency

    I've been down this road of messing with PNGs with alpha using VB6.

    Here, this might help you: https://www.vbforums.com/showthread....)-Editing-Tool
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  16. #16

    Thread Starter
    Lively Member
    Join Date
    May 2022
    Location
    App.Path
    Posts
    66

    Re: BitBlt from png with transparency

    Hello all! baka was fed up with me, and no-one else had responded so throughout the entire day I looked for a solution. Just came back here to post it and mark resolved and I see all this. Thank you everyone for your help, I will look into which one of these works best for me. Right now I just got LaVolpe's PNG rendering code working, which is very similiar to wqweto's example, but with much more stuff I don't need.

    For right now, my solution is this:
    https://www.vbforums.com/showthread....pdated-16Feb09
    However I will probably end up using wqweto's code as it is very similiar and this already works like a charm (I expected nothing less from LaVolpe)

    No, Shaggy Hiker, I am not stealing your signature.

  17. #17

    Thread Starter
    Lively Member
    Join Date
    May 2022
    Location
    App.Path
    Posts
    66

    Re: BitBlt from png with transparency

    Hello again. I got wqweto's solution working perfectly except for one thing. If I don't run any GDI+ code, after I end the program, when the IDE loses focus it crashes. Very annoying. This might be another thread but just posting here for now. It seems like if GdiPlusStartup was ever called, this issue occurs. If it was never called, no issue. But obviously I need GdiPlusStartup.

    No, Shaggy Hiker, I am not stealing your signature.

  18. #18
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,871

    Re: BitBlt from png with transparency

    if u use GDI+ u need to initialize it and also close it. especially if u use an older OS (that u should have mentioned)

    wqweto code, just edit this part:
    Code:
    If GetModuleHandle("gdiplus") = 0 Then
            aInput(0) = 1
            Call GdiplusStartup(0, aInput(0))
        End If
    with

    Code:
    If mToken = 0 Then
       aInput(0) = 1
       GdiplusStartup mToken, aInput(0)
    End If
    where mToken is a global variable

    and when u done using GDI+ (usually in the termination-procedure, before your application ends)
    you add:

    Code:
    GdiplusShutdown mToken
    or if u just want to use it one time add it at the end of the function.

  19. #19

    Thread Starter
    Lively Member
    Join Date
    May 2022
    Location
    App.Path
    Posts
    66

    Resolved Re: BitBlt from png with transparency

    Thank you baka, wqweto, and everyone else! It now works! Here is my final code:


    Code:
    Private Declare Function GdiplusStartup Lib "gdiplus" (hToken As Long, pInputBuf As Any, Optional ByVal pOutputBuf As Long = 0) As Long
    Private Declare Function GdiplusShutdown Lib "gdiplus" (ByVal token As Long) As Long
    Private Declare Function GdipLoadImageFromFile Lib "gdiplus" (ByVal sFileName As Long, mImage As Long) As Long
    Private Declare Function GdipGetImageDimension Lib "gdiplus" (ByVal hImage As Long, nWidth As Single, nHeight As Single) As Long   '
    Private Declare Function GdipDisposeImage Lib "gdiplus" (ByVal hImage As Long) As Long
    Private Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hDC As Long, hGraphics As Long) As Long
    Private Declare Function GdipDeleteGraphics Lib "gdiplus" (ByVal hGraphics As Long) As Long
    Private Declare Function GdipDrawImageRectRect Lib "gdiplus" (ByVal hGraphics As Long, ByVal hImage As Long, ByVal dstX As Single, ByVal dstY As Single, ByVal dstWidth As Single, ByVal dstHeight As Single, ByVal srcX As Single, ByVal srcY As Single, ByVal srcWidth As Single, ByVal srcHeight As Single, Optional ByVal srcUnit As Long = 2, Optional ByVal hImageAttributes As Long, Optional ByVal pfnCallback As Long, Optional ByVal lCallbackData As Long) As Long
    
    Dim hBitmap As Long
    Dim hGraphics As Long
    Dim GDItoken As Long
    
    Public Sub InitGDI()
        
        Dim aInput(0 To 3) As Long
        
        aInput(0) = 1
        If GDItoken = 0 Then Call GdiplusStartup(GDItoken, aInput(0))
        
    End Sub
    Public Sub DisposeGDI()
        
        Call GdipDeleteGraphics(hGraphics)
        Call GdiplusShutdown(GDItoken)
        
    End Sub
    
    Public Sub DrawPNG(ByVal hDC As Long, sFile As String, X As Single, Y As Single, Width As Single, Height As Single)
        
        Dim sngWidth        As Single
        Dim sngHeight       As Single
            
        'Dispose of old handle if exist
        If hBitmap <> 0 Then Call GdipDisposeImage(hBitmap)
        'Make handle to draw from
        Call GdipLoadImageFromFile(StrPtr(sFile), hBitmap)
        
        'Get dimensions
        Call GdipGetImageDimension(hBitmap, sngWidth, sngHeight)
        
        'Create hGraphics
        Call GdipCreateFromHDC(hDC, hGraphics)
        
        'Draw
        Call GdipDrawImageRectRect(hGraphics, hBitmap, X, Y, Width, Height, 0, 0, sngWidth, sngHeight)
        
    End Sub

    No, Shaggy Hiker, I am not stealing your signature.

  20. #20
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,545

    Re: BitBlt from png with transparency

    Btw, my original sample above did not use GdiplusShutdown and did not AV on exit.

    The way you have "reimplemented" the snippet is outright dangerous and besides it's leaking hGraphics on each call.

    You have to cleanup hBitmap and hGraphics inside DrawPNG but it's up to you to (unnecessary) call GdiplusShutdown through (unnecessary) InitGDI and DisposeGDI whenever you see fit.

    (Loading and unloading GDIPLUS.DLL is like loading and unloading GDI32.DLL -- no one should be even thinking about doing it in their app)

    cheers,
    </wqw>

  21. #21
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,871

    Re: [RESOLVED] BitBlt from png with transparency

    no u need to shut it down or it will crash the application.
    hgraphic u delete when u are not rendering anymore.
    and u delete the himage (bitmap) when not needed anymore.
    theres no right or wrong WHEN u do it. but it should be done before termination.

    maybe u dont need to do it in windows 10+ but in older OS u NEED to shut it down.

  22. #22
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,545

    Re: [RESOLVED] BitBlt from png with transparency

    > hgraphic u delete when u are not rendering anymore.

    You do realize OP is calling Call GdipCreateFromHDC(hDC, hGraphics) on each call to DrawPNG and leaking it into oblivion.

    > maybe u dont need to do it in windows 10+ but in older OS u NEED to shut it down.

    No, you don't need to shut GDI+ on any OS *if* you don't leak handles.

    Now I'll bow out of this discussion but don't run here asking why your GDI+ app is crashing on exit.

    cheers,
    </wqw>

  23. #23
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,871

    Re: [RESOLVED] BitBlt from png with transparency

    OMG I have worked with GAMES for decades. I KNOW how to handle GDI+
    as I have been working with that A LOT before Direct2D. if u didn't shut it down it would crash the application.
    not sure how u use it. but u invalidate +10 years of experience saying that.
    if u keep calling GdiplusStartup without never calling GdiplusShutdown eventually it will stop working and u get a crash.
    the same with almost anything that has initialization. that is why its important with the termination.
    I get issues with sounds if I get a few crashes in IDE. eventually the sound stop working. sometimes a IDE restart can help, but sometimes I need to restart windows.
    if u dont understand this theres something really wrong with how u code.
    of course if u have a compiled .exe, windows can do it FOR YOU. but its lazy to let the OS do it. especially older OS and u don't know how they operate.

    the same with your "suggestion" how to terminate bitmaps in some threads. this ugly trend TO NOT release something is dangerous.
    following your suggestion creates eventually out of memory errors and can crash the entire OS. sure u can do it many times, as everything seems to work. until it doesn't.

    LEARN TO TERMINATE. *facepalm*

  24. #24
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,545

    Re: [RESOLVED] BitBlt from png with transparency

    I would have addressed all your questions but I already bowed out of this unproductive discussion (no one likes to be shouted at in CAPSLOCK) so you can assume you are right on everything you said.

    cheers,
    </wqw>

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width