Results 1 to 9 of 9

Thread: c32bppDIB: MakeOpaque does not work as expected

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2017
    Posts
    760

    Question c32bppDIB: MakeOpaque does not work as expected

    I'n using an image class named "pcMemDC". The variable is named "m_cMemDC".
    It holds an image with transparent pixels.
    I want to remove the transparency and make the transparent pixels white and save this opaque image as a PNG.

    To do that, I use a LaVolpe's great c32bppDIB class, named "m_c32DIBBackground".

    Code:
     With m_c32DIBBackground
            .ManageOwnDC = True
            .InitializeDIB m_cMemDC.Width, m_cMemDC.Height 'I initialize it with the size of the source file
            .Alpha = AlphaNone 'I don't want alpha
            .CreateWhiteCanvas 'I create a white canvas
            .MakeOpaque 'And again make sure it is opaque
     
            m_cMemDC.Draw .hdc 'Now I draw the alpha image to the white opaque canvas.
    
            .SaveToFile_PNG "d:\test1.png", False 'And save it out
    
        End With
    However, the resulting image has a black background instead of white.

    I don't see where it goes wrong.

    I even already suspected the problem in the other class, but I don't know:

    Its "Draw" sub looks like this:

    Code:
    Public Sub Draw( _
          ByVal uDstDc As Long, _
          Optional ByVal xSrc As Long = 0, Optional ByVal ySrc As Long = 0, _
          Optional ByVal WidthSrc As Long = 0, Optional ByVal HeightSrc As Long = 0, _
          Optional ByVal xDst As Long = 0, Optional ByVal yDst As Long = 0 _
       )
       If WidthSrc <= 0 Then WidthSrc = m_lWidth
       If HeightSrc <= 0 Then HeightSrc = m_lHeight
       
        Dim lROP&
        If Not m_bNoMirror Then
            lROP = vbSrcCopy
        Else
            lROP = (vbSrcCopy Or NOMIRRORBITMAP)
        End If
        
        BitBlt uDstDc, xDst, yDst, WidthSrc, HeightSrc, m_hDC, xSrc, ySrc, lROP
       
    End Sub
    What am I doing wrong?

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

    Re: c32bppDIB: MakeOpaque does not work as expected

    Check the ".MakeOpaque" method, it's likely the problem is in there. You could also use "GetDIBits" to get an array of pixels from the bitmap, then change the alpha byte to 255 (white) and write the array back with "SetDIBits".

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

    Re: c32bppDIB: MakeOpaque does not work as expected

    Quote Originally Posted by tmighty2 View Post

    Code:
    Public Sub Draw( _
          ByVal uDstDc As Long, _
          Optional ByVal xSrc As Long = 0, Optional ByVal ySrc As Long = 0, _
          Optional ByVal WidthSrc As Long = 0, Optional ByVal HeightSrc As Long = 0, _
          Optional ByVal xDst As Long = 0, Optional ByVal yDst As Long = 0 _
       )
       If WidthSrc <= 0 Then WidthSrc = m_lWidth
       If HeightSrc <= 0 Then HeightSrc = m_lHeight
       
        Dim lROP&
        If Not m_bNoMirror Then
            lROP = vbSrcCopy
        Else
            lROP = (vbSrcCopy Or NOMIRRORBITMAP)
        End If
        
        BitBlt uDstDc, xDst, yDst, WidthSrc, HeightSrc, m_hDC, xSrc, ySrc, lROP
       
    End Sub
    What am I doing wrong?
    The above BitBlt-based Draw-method is not "Alpha-capable".
    It neither respects a (potentially existing) AlphaChannel of "the Source-DIB" -
    nor do you have a guarantee, that it leaves the AlphaChannel-Bytes of "the Destination-DIB" intact.

    "GDI-wise",... only the AlphaBlend-GDI-API can handle that.
    (in case the Source is a 32Bit-DIB with a proper Alpha-channel).

    I'm also not quite sure, what you goal is...

    Why would you want to write out something into a *.png, which priorily had "nice Alpha-Infos in it" -
    (which are lost, after rendering this resource onto a solid, white Background).

    FWIW, here's some code which requires an RC6-reference in your Project,
    which shows how the task can be done with ease (although the comments raise the same question)...
    Code:
    Private Sub Form_Load()
      'let's load an alpha-resource-surface - and also create a drawing-context on it in one line
      With Cairo.ImageList.AddIconFromResourceFile("", "shell32", 167).CreateContext
        
        'write out the just loaded Alpha-resource as a PNG with Alpha-channel
        .Surface.WriteContentToPngFile "c:\temp\AlphaIcon.png"
        
        'now we draw "a white UnderLay" on the just loaded resource-alpha-bytes of this surface(-context)
        .Operator = CAIRO_OPERATOR_DEST_ATOP '...by telling the "Cairo-Blender" to switch what's "Destination and Source"
        .Paint 1, Cairo.CreateSolidPatternLng(vbWhite) 'so that .Paint will now draw white underneath the already loaded Alpha-Bytes
        
        'Ok, now we can visualize the result of the above "alpha-on-white"-operation (which all happened on this single-Pixel-surface)
        Set Me.Picture = .Surface.Picture
        
        'although the surface has now lost all its alpha-channel-info ... but we put it out as a PNG anyways
        .Surface.WriteContentToPngFile "c:\temp\AlphaIcon_OnWhite.png"
      End With
    End Sub
    HTH

    Olaf

  4. #4

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

    Re: c32bppDIB: MakeOpaque does not work as expected

    You MemDC.Draw method should be extended to accept ROP as a parameter so that you can use vbSrcPaint to OR blit source into all *black* target (not white) and *after* this call MakeOpaque (not before blitting).

    Keep in mind that Raymond Chen’s technique for manipulating alpha channel is dubious for values other than 255 because 32-bit DIB are expected to be in precomputed alpha state i.e. for a pixel w/ alpha = 123 all the color components (R, G and B) cannot be more than 123 but blatantly OR blitting alpha values does *not* precompute color components so you might end up w/ invalid colors unless alpha being set is 255 which does not need precomputing so cannot render invalid colors per se.

  6. #6
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,454

    Re: c32bppDIB: MakeOpaque does not work as expected

    Quote Originally Posted by The trick View Post
    BitBlt/StretchBlt (and others which use raster operations) works with alpha channel according to the raster operation, so you can copy your alpha channel/set it/remove etc. using GDI functions.
    That's interesting and might work (in the meantime, on newer Win-OSes only?) - but I was referring
    to the Draw-method as posted (which had vbSrcCopy as the "hardwired" RasterOp-constant).

    Also a "true PerPixel-AlphaBlending" via GDI (when the Src-DIB needs to be 32bpp - and contains Alpha-pre-multiplied-RGB-data),
    is easiest (and fastest) to accomplish with the already mentioned AlphaBlend-API.

    Trying to simulate the same render-output as "true PerPixel-AlphaBlending" -
    via multiple BitBlt-calls (using different Raster-Op-Consts) -
    is "adventurous" at best and I'd not recommend it.

    Olaf

  7. #7

  8. #8
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,797

    Re: c32bppDIB: MakeOpaque does not work as expected

    Quote Originally Posted by Schmidt View Post
    That's interesting and might work (in the meantime, on newer Win-OSes only?) - but I was referring
    to the Draw-method as posted (which had vbSrcCopy as the "hardwired" RasterOp-constant).

    Also a "true PerPixel-AlphaBlending" via GDI (when the Src-DIB needs to be 32bpp - and contains Alpha-pre-multiplied-RGB-data),
    is easiest (and fastest) to accomplish with the already mentioned AlphaBlend-API.

    Trying to simulate the same render-output as "true PerPixel-AlphaBlending" -
    via multiple BitBlt-calls (using different Raster-Op-Consts) -
    is "adventurous" at best and I'd not recommend it.

    Olaf
    I meant some GDI functions just process the alpha channel according to a raster operation. I didn't talk about blending. It works as least since WinXP.

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

    Re: c32bppDIB: MakeOpaque does not work as expected

    Here's some work I did to "see" an alpha channel with a standard PictureBox (not using GDI+).

    Not sure if that helps or not though. EMF files can be a bit funky.

    EDIT: Actually, I did use the GDI+ to read the PNG file.
    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.

Tags for this Thread

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