Re: Unknown transparency mask color -- how to?
- From: "Mike D Sutton" <EDais@xxxxxxxx>
- Date: Fri, 1 Dec 2006 16:06:59 -0000
OK, I think I'm finally seeing the light at the end of the tunnel.
Current (bad) Method: "Blank out DC" using a FillRect of color XYZ. Use various tools (BitBlt, TextOut, Lines, etc...)
to put objects on that layer. TransparentBlt/ChromaBLT the layer with a transparency color of XYZ. Problems and issues
with this already described below. Your comments understood.
So far so good
New Proposed Method: Create a layer with an alpha channel of 0 across the board, and render my objects onto it (using
standard APIs as listed above). You said anything that GDI touches gives an Alpha of 100, correct??
I would be nice, but unfortunately it works the other way around - GDI doesn't understand about alpha channels and as
such always trashes them, so any pixel GDI touches will have an alpha value of 0. You can use this to your advantage
though by first filling the entire alpha channel with 0xFF then perform your drawing, and finally invert the alpha - Any
pixels GDI left untouched, and thus should be transparent, now have an alpha value of 0x0, and any pixels GDI drew will
now have an alpha of 0xFF as you require.
The problem here however comes when you mix AlphaBlend() with this alpha trick above since this API call is actually
part of MSImg32.dll, not GDI32.dll, and does actually understand alpha. If you need to mix GDI with alpha blending then
you need to be careful about how you layer your drawing - You can do as much GDI work on your buffer as you need to, but
as soon as you need to blend, sort out your existing alpha channel and then perform your blending. After that the GDI
alpha trick will no longer work since there is now meaningful data in the alpha channel, both from GDI and AlphaBlend().
If you do need to perform more GDI drawing over the top then you'll need to create another buffer, use the GDI alpha
trick and then AlphaBlend() that over your initial buffer. Phew, what a lot of hassle..
So a final alpha blend would only show the objects, lines, etc... that I've placed on it, correct?
Correct. Oh and one other thing while I think about it; Chroma/TransparentBlt() is actually incompatible with the alpha
trick due to the way it performs its masking. In that case you'd need to go through the buffer yourself, check for any
pixels of the transparent colour and fill those with 0x00000000 or write the high byte for all other pixels, something
like this:
'***
Dim Pixels() As Long
Dim X As Long, Y As Long
For Y = 0 To Height - 1
For X = 0 To Width - 1
If ((Pixels(X, Y) And &HFFFFFF) = TransparentColour) Then
Pixels(X, Y) = &H0 ' Transparent; kill it
Else ' Opaque; add in the full alpha channel
Pixels(X, Y) = Pixels(X, Y) Or &HFF000000
End If
Next X
Next Y
'***
If this is true, 2 questions
1.) What is the most optimum way to way to create a DC with height/width of lHeight and lWidth that has an alpha
channel of 0 across it.
A DC is just a container, but I'm guessing you mean a DC with a DIBSection within it with the given width and height.
In that case use CreateDIBSection() but change the declare to return lplpVoid/ppvBits (Depending on which declaration
you're going from) to be ByRef so you get the pointer to the data back, then use RtlFillMemory() to write the buffer:
'***
Private Declare Function CreateDIBSection Lib "GDI32.dll" ( _
ByVal hDC As Long, ByRef pBMI As BitmapInfo, ByVal iUsage As Long, _
ByRef ppvBits As Long, ByVal hSection As Long, ByVal dwOffset As Long) As Long
Private Declare Function RtlFillMemory Lib "Kernel32.dll" ( _
ByRef Destination As Any, ByVal Length As Long, ByVal Fill As Byte) As Long
Dim DataPtr As Long
hDIB = CreateDIBSection(hDC, ... , DataPtr, ... )
' Fill with 0's; note we don't need to worry about DWord alignment here since
' 32-bit buffers are always aligned (every pixel aligns on a DWord boundry.)
Call RtlFillMemory(ByVal DataPtr, Width * Height * 4, 0)
'***
In your case though, you want to fill the alpha channel with 0xFF instead, which you can either accomplish by using
RtlFillMemory() with &HFF as the last parameter or go through and inject the data yourself. The latter is a bit more of
a pain, but does mean the transparent pixels are correctly pre-multiplied and you don't run into the same problem as we
found in your PNG's with transparent white pixels.
Indeed, in my DIB class I have a Fill(), FillRGBA() and FillAlpha() methods specifically for dealing with these kinds of
cases.
2.) Once this layer is created and I need to re-render the objects on it, is there a quick way to "wipe it clean" --
resetting everything as above to alpha 0 with nothing on it??
See above.
I hope I'm making myself clear :( Sorry for all the confusion.
Not a problem, hopefully the above makes sense.
Hope this helps,
Mike
- Microsoft Visual Basic MVP -
E-Mail: EDais@xxxxxxxx
WWW: Http://EDais.mvps.org/
.
- References:
- Re: Unknown transparency mask color -- how to?
- From: Mike D Sutton
- Re: Unknown transparency mask color -- how to?
- From: wxforecaster
- Re: Unknown transparency mask color -- how to?
- Prev by Date: Re: Unknown transparency mask color -- how to?
- Next by Date: transparency
- Previous by thread: Re: Unknown transparency mask color -- how to?
- Next by thread: transparency
- Index(es):
Relevant Pages
|