This one is simpler in nature...
I want to add bitmap suport for the control im making, however all i *know* with gdi is how to bitblt dc's.
The problem is that i cant mask the backgrounds of bitmaps that would be used. So if someone's desktop is neon green and i have a standard grey background, its going to show up.
How would i go about taking a bitmap, and then building a mask for it such that only the "graphical" info is bitblt'd to another DC. Is there api's for this (briefly looked but didnt see anything). Code fragments would rock, but a basic pseudo outline is all i really need.
Thanx again for any advice.
:alright:
NaN
I want to add bitmap suport for the control im making, however all i *know* with gdi is how to bitblt dc's.
The problem is that i cant mask the backgrounds of bitmaps that would be used. So if someone's desktop is neon green and i have a standard grey background, its going to show up.
How would i go about taking a bitmap, and then building a mask for it such that only the "graphical" info is bitblt'd to another DC. Is there api's for this (briefly looked but didnt see anything). Code fragments would rock, but a basic pseudo outline is all i really need.
Thanx again for any advice.
:alright:
NaN
NaN,
The methods I use with bitmaps that have to have the correct background colour is to set them to a single background colour when I make them and flood fill the background colour at runtime. Only problem is you cannot have enclosed areas with the background as the flood fill will not work there.
Regards,
hutch@movsd.com
The methods I use with bitmaps that have to have the correct background colour is to set them to a single background colour when I make them and flood fill the background colour at runtime. Only problem is you cannot have enclosed areas with the background as the flood fill will not work there.
Regards,
hutch@movsd.com
First, let me explain I've never done this, just that I looked up a few things along the way.
msimg32.dll contains an interesting API named TransparentBlt. This BLT function contains the interesting parameter crTransparent, "The RGB color in the source bitmap to treat as transparent."
The "user beware" catch is this API is only good for W98 and NT5 or later. And Microsoft themselves recomends you don't use it in 98 cause it has a memory leak bug.
So... on to manual methods. Rather then deescribe how I remember it done, just check out HOWTO: Drawing Transparent Bitmaps (Q79212)
Hrmmm.... I've seen this question come up about every 3-4 months. Maybe it's time someone write up a routine for the MASM32 library.
Any takers? :-)
msimg32.dll contains an interesting API named TransparentBlt. This BLT function contains the interesting parameter crTransparent, "The RGB color in the source bitmap to treat as transparent."
The "user beware" catch is this API is only good for W98 and NT5 or later. And Microsoft themselves recomends you don't use it in 98 cause it has a memory leak bug.
So... on to manual methods. Rather then deescribe how I remember it done, just check out HOWTO: Drawing Transparent Bitmaps (Q79212)
Hrmmm.... I've seen this question come up about every 3-4 months. Maybe it's time someone write up a routine for the MASM32 library.
Any takers? :-)
Aww heck, I've got time for another cup of coffee today. Here's a direct "C to ASM" translation of that articles code.
All I claim is it compiles, I have not tested it.
All I claim is it compiles, I have not tested it.
DrawTransparentBitmap PROC hdc:DWORD, hBitmap:DWORD, xStart:DWORD, yStart:DWORD,
cTransparentColor:DWORD
LOCAL bm:DWORD, cColor:DWORD,
LOCAL bmAndBack:DWORD, bmAndObject:DWORD, bmAndMem:DWORD, bmSave:DWORD
LOCAL bmBackOld:DWORD, bmObjectOld:DWORD, bmMemOld:DWORD, bmSaveOld:DWORD
LOCAL hdcMem:DWORD, hdcBack:DWORD, hdcObject:DWORD, hdcTemp:DWORD, hdcSave:DWORD;
LOCAL ptSize:POINT;
invoke CreateCompatibleDC, hdc
mov hdcTemp, eax
invoke SelectObject, hdcTemp, hBitmap ; Select the bitmap
invoke GetObject, hBitmap, sizeof(BITMAP), ADDR bm
mov eax, bm.bmWidth ; Get width of bitmap
mov ptSize.x, eax
mov eax, bm.bmHeight ; Get height of bitmap
mov ptSize.y, eax
invoke DPtoLP, hdcTemp, ADDR ptSize, 1 ; Convert from device
; to logical points
; Create some DCs to hold temporary data.
invoke CreateCompatibleDC, hdc
mov hdcBack, eax
invoke CreateCompatibleDC, hdc
mov hdcObject, eax
invoke CreateCompatibleDC, hdc
mov hdcMem, eax
invoke CreateCompatibleDC, hdc
mov hdcSave, eax
; Create a bitmap for each DC. DCs are required for a number of
; GDI functions.
; Monochrome DC
invoke CreateBitmap, ptSize.x, ptSize.y, 1, 1, NULL
mov bmAndBack, eax
; Monochrome DC
invoke CreateBitmap, ptSize.x, ptSize.y, 1, 1, NULL
mov bmAndObject, eax
invoke CreateCompatibleBitmap, hdc, ptSize.x, ptSize.y
mov bmAndMem, eax
invoke CreateCompatibleBitmap, hdc, ptSize.x, ptSize.y
mov bmSave, eax
; Each DC must select a bitmap object to store pixel data.
invoke SelectObject, hdcBack, bmAndBack
mov bmBackOld, eax
invoke SelectObject, hdcObject, bmAndObject
mov bmObjectOld, eax
invoke SelectObject, hdcMem, bmAndMem
mov bmMemOld, eax
invoke SelectObject, hdcSave, bmSave
mov bmSaveOld, eax
; Set proper mapping mode.
invoke GetMapMode, hdc
invoke SetMapMode, hdcTemp, eax
; Save the bitmap sent here, because it will be overwritten.
invoke BitBlt, hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY
; Set the background color of the source DC to the color.
; contained in the parts of the bitmap that should be transparent
invoke SetBkColor, hdcTemp, cTransparentColor
mov cColor, eax
; Create the object mask for the bitmap by performing a BitBlt
; from the source bitmap to a monochrome bitmap.
invoke BitBlt, hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY
; Set the background color of the source DC back to the original
; color.
invoke SetBkColor, hdcTemp, cColor
; Create the inverse of the object mask.
invoke BitBlt, hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, NOTSRCCOPY
; Copy the background of the main DC to the destination.
invoke BitBlt, hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, xStart, yStart, SRCCOPY
; Mask out the places where the bitmap will be placed.
invoke BitBlt, hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND
; Mask out the transparent colored pixels on the bitmap.
invoke BitBlt, hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND
; XOR the bitmap with the background on the destination DC.
invoke BitBlt, hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT
; Copy the destination to the screen.
invoke BitBlt, hdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0, SRCCOPY
; Place the original bitmap back into the bitmap sent here.
invoke BitBlt, hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY
; Delete the memory bitmaps.
invoke DeleteObject, SelectObject, hdcBack, bmBackOld
invoke DeleteObject, SelectObject, hdcObject, bmObjectOld
invoke DeleteObject, SelectObject, hdcMem, bmMemOld
invoke DeleteObject, SelectObject, hdcSave, bmSaveOld
; Delete the memory DCs.
invoke DeleteDC, hdcMem
invoke DeleteDC, hdcBack
invoke DeleteDC, hdcObject
invoke DeleteDC, hdcSave
invoke DeleteDC, hdcTemp
ret
DrawTransparentBitmap ENDP
this is only a guess...
oh, the _MakeRegion proc will look up the
pixel-color in x:0/y:0 and mark it as "transparent"
then it will create a region for you. this was written
for window-skinning so i think you have to correct
some parts...
oh, the _MakeRegion proc will look up the
pixel-color in x:0/y:0 and mark it as "transparent"
then it will create a region for you. this was written
for window-skinning so i think you have to correct
some parts...
.DATA
f_dc dd 0
... alot of handle vars
.CODE
--WM_CREATE:
invoke LoadBitmap,hInst, BM_ID
mov bm_handle,eax
invoke CreatePatternBrush, bm_handle
mov bm_brush,eax
invoke _MakeRegion, bm_handle
mov bm_region, eax
invoke OffsetRgn,bm_region,X,Y ;<-???
--WM_PAINT:
invoke BeginPaint,hwnd,addr paint_struc
mov hdc,eax
invoke SelectObject,hdc,bm_brush
invoke PaintRgn,hdc,bm_region
invoke EndPaint,hwnd,addr paint_struc
--WM_CLOSE:
close all handles (api-ref)
_MakeRegion PROC USES ESI EDI EBX bhnd:DWORD
LOCAL flag: DWORD
LOCAL frun: DWORD
LOCAL d_dc: DWORD
LOCAL oldx: DWORD
LOCAL tcol: DWORD
LOCAL _hdc: DWORD
invoke CreateCompatibleDC,NULL
mov _hdc,eax
invoke SelectObject,_hdc,bhnd
mov flag,FALSE
mov frun,TRUE
mov oldx,0
xor edi,edi
xor esi,esi
invoke GetPixel,_hdc,0,0
mov tcol,eax
_xloop: invoke GetPixel,_hdc,edi,esi
cmp eax,tcol
jz _letsgo
cmp edi,PictureW
jnz _fndone
_letsgo:cmp flag,TRUE
jnz _nxtone
mov flag,FALSE
mov eax,esi
inc eax
invoke CreateRectRgn,ebx,esi,edi,eax
mov d_dc,eax
cmp frun,TRUE
jnz _nofrun
mov frun,FALSE
push d_dc
pop f_dc
jmp _nxtone
_nofrun:invoke CombineRgn,f_dc,f_dc,d_dc,RGN_OR
invoke DeleteObject,d_dc
jmp _nxtone
_fndone:cmp flag,FALSE
jnz _nxtone
mov flag,TRUE
mov ebx,edi
_nxtone:inc edi
cmp edi,PictureW
jbe _xloop
xor edi,edi
inc esi
cmp esi,PictureH
jb _xloop
_exit: invoke DeleteDC,_hdc
mov eax,f_dc
ret
This should also be done easily if you load the image up in an Image list i believe. You can use a Bitmap that contains the Mask when you add it to an Image List
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/CommCtls/ImageList/Functions/ImageList_Add.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/imagelist/reflist.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/CommCtls/ImageList/Functions/ImageList_Add.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/imagelist/reflist.asp
Thanx alot everyone! This is oooodles of stuff for me to hack thru.
Ernie, I plan on writting my first formal tutorial outa this, so it will eventually get discussed ~ however, thanx for the source!
PS: How did you ever get this to compile ( :grin: )
Hutch, i looked over your Bitmap Button example but it confused me what you were trying to do, however with you above explaination i think i now know what your were up to. I will have to look it over again as well :)
Volcano_88101, Thanx for the info. I knew about this, but from past experiences i didnt *enjoy* using them. However, if it fits the bill i might have to ;) . Thanx!
Mob, Thanx as well for your source on regions. I will admit this is one GDI area i've never set foot into so perhaps it holds some uses for this purpose... thanx again!
:alright:
NaN
Ernie, I plan on writting my first formal tutorial outa this, so it will eventually get discussed ~ however, thanx for the source!
PS: How did you ever get this to compile ( :grin: )
; Delete the memory bitmaps.
invoke DeleteObject, SelectObject, hdcBack, bmBackOld
invoke DeleteObject, SelectObject, hdcObject, bmObjectOld
invoke DeleteObject, SelectObject, hdcMem, bmMemOld
invoke DeleteObject, SelectObject, hdcSave, bmSaveOld
Hutch, i looked over your Bitmap Button example but it confused me what you were trying to do, however with you above explaination i think i now know what your were up to. I will have to look it over again as well :)
Volcano_88101, Thanx for the info. I knew about this, but from past experiences i didnt *enjoy* using them. However, if it fits the bill i might have to ;) . Thanx!
Mob, Thanx as well for your source on regions. I will admit this is one GDI area i've never set foot into so perhaps it holds some uses for this purpose... thanx again!
:alright:
NaN
Whoops... thats what I get for covering my desktop with multiple source images.
This will compile a little better. ;-)
This will compile a little better. ;-)
;-------------------------------------------------------------------------------
;
; DrawTransparentBitmap: bitmap blit function that respects the background color
; and does not copy over it
;
; Code is directly written from "HOWTO: Drawing Transparent Bitmaps (Q79212)"
; (no copyright noted on orgional code, none claimed here either)
;
;-------------------------------------------------------------------------------
DrawTransparentBitmap PROC hdc:DWORD, hBitmap:DWORD, xStart:DWORD, yStart:DWORD, \
cTransparentColor:DWORD
LOCAL bm:BITMAP, cColor:DWORD
LOCAL bmAndBack:DWORD, bmAndObject:DWORD, bmAndMem:DWORD, bmSave:DWORD
LOCAL bmBackOld:DWORD, bmObjectOld:DWORD, bmMemOld:DWORD, bmSaveOld:DWORD
LOCAL hdcMem:DWORD, hdcBack:DWORD, hdcObject:DWORD, hdcTemp:DWORD, hdcSave:DWORD
LOCAL ptSize:POINT
invoke CreateCompatibleDC, hdc
mov hdcTemp, eax
invoke SelectObject, hdcTemp, hBitmap ; Select the bitmap
invoke GetObject, hBitmap, sizeof(BITMAP), ADDR bm
mov eax, bm.bmWidth ; Get width of bitmap
mov ptSize.x, eax
mov eax, bm.bmHeight ; Get height of bitmap
mov ptSize.y, eax
invoke DPtoLP, hdcTemp, ADDR ptSize, 1 ; Convert from device
; to logical points
; Create some DCs to hold temporary data.
invoke CreateCompatibleDC, hdc
mov hdcBack, eax
invoke CreateCompatibleDC, hdc
mov hdcObject, eax
invoke CreateCompatibleDC, hdc
mov hdcMem, eax
invoke CreateCompatibleDC, hdc
mov hdcSave, eax
; Create a bitmap for each DC. DCs are required for a number of GDI functions.
; Monochrome DC
invoke CreateBitmap, ptSize.x, ptSize.y, 1, 1, NULL
mov bmAndBack, eax
; Monochrome DC
invoke CreateBitmap, ptSize.x, ptSize.y, 1, 1, NULL
mov bmAndObject, eax
invoke CreateCompatibleBitmap, hdc, ptSize.x, ptSize.y
mov bmAndMem, eax
invoke CreateCompatibleBitmap, hdc, ptSize.x, ptSize.y
mov bmSave, eax
; Each DC must select a bitmap object to store pixel data.
invoke SelectObject, hdcBack, bmAndBack
mov bmBackOld, eax
invoke SelectObject, hdcObject, bmAndObject
mov bmObjectOld, eax
invoke SelectObject, hdcMem, bmAndMem
mov bmMemOld, eax
invoke SelectObject, hdcSave, bmSave
mov bmSaveOld, eax
; Set proper mapping mode.
invoke GetMapMode, hdc
invoke SetMapMode, hdcTemp, eax
; Save the bitmap sent here, because it will be overwritten.
invoke BitBlt, hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY
; Set the background color of the source DC to the color.
; contained in the parts of the bitmap that should be transparent
invoke SetBkColor, hdcTemp, cTransparentColor
mov cColor, eax
; Create the object mask for the bitmap by performing a BitBlt
; from the source bitmap to a monochrome bitmap.
invoke BitBlt, hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCCOPY
; Set the background color of the source DC back to the original color.
invoke SetBkColor, hdcTemp, cColor
; Create the inverse of the object mask.
invoke BitBlt, hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, NOTSRCCOPY
; Copy the background of the main DC to the destination.
invoke BitBlt, hdcMem, 0, 0, ptSize.x, ptSize.y, hdc, xStart, yStart, SRCCOPY
; Mask out the places where the bitmap will be placed.
invoke BitBlt, hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND
; Mask out the transparent colored pixels on the bitmap.
invoke BitBlt, hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND
; XOR the bitmap with the background on the destination DC.
invoke BitBlt, hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, 0, 0, SRCPAINT
; Copy the destination to the screen.
invoke BitBlt, hdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0, SRCCOPY
; Place the original bitmap back into the bitmap sent here.
invoke BitBlt, hdcTemp, 0, 0, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY
; Delete the memory bitmaps.
invoke SelectObject, hdcBack, bmBackOld
invoke DeleteObject, eax
invoke SelectObject, hdcObject, bmObjectOld
invoke DeleteObject, eax
invoke SelectObject, hdcMem, bmMemOld
invoke DeleteObject, eax
invoke SelectObject, hdcSave, bmSaveOld
invoke DeleteObject, eax
; Delete the memory DCs.
invoke DeleteDC, hdcMem
invoke DeleteDC, hdcBack
invoke DeleteDC, hdcObject
invoke DeleteDC, hdcSave
invoke DeleteDC, hdcTemp
ret
DrawTransparentBitmap ENDP
My only question about this is how fast would this actually be?
Hmmm.. still uncertain. I manually transcribed it myself as well, but it doesn't work. Im still tracking thu it and seeing where it fails.
However, there is an odd API in there:
What im testing with is a 23*23 bitmap. ANd would like to be able to suport 32x32 etc. However, im not positive this is the problem anyways..
:alright:
NaN
However, there is an odd API in there:
invoke DPtoLP, hdcTemp, ADDR ptSize, 1 ; Convert from device
; to logical points
; WARNING: This function fails if the device coordinates exceed 27 bits, or if the converted logical
; coordinates exceed 32 bits. In the case of such an overflow, the results for all the points
; are undefined.
What im testing with is a 23*23 bitmap. ANd would like to be able to suport 32x32 etc. However, im not positive this is the problem anyways..
:alright:
NaN
Thanx Everyone who got into this converstaion!
Im now satisfied with what i have and seems to work good. As well the warning on the API doesnt seem to be in 'pixels' as it works fine with 60x60 images.
So im happy with what Ernie pointed me to. And in light of what Ernie suggested, i made a formal MASM32.lib file so that it can be easily added to you libraries. There is nothing to optomize really (well maybe cut out one less DC, but ah, it works smoothly as far as i can tell anyways).
I did however make one param. Its to suport stuff like what hutch does and samples the first bit for transparency.
The file is attached below. In the header i tell you what to do with the file to add it to the lib, so i wont go over this. What i will talk about is its usage:
In usage the x,y point is where the upper right corner of the bitmap will be on the DC. The Transparency color can either be:
Im now satisfied with what i have and seems to work good. As well the warning on the API doesnt seem to be in 'pixels' as it works fine with 60x60 images.
So im happy with what Ernie pointed me to. And in light of what Ernie suggested, i made a formal MASM32.lib file so that it can be easily added to you libraries. There is nothing to optomize really (well maybe cut out one less DC, but ah, it works smoothly as far as i can tell anyways).
I did however make one param. Its to suport stuff like what hutch does and samples the first bit for transparency.
The file is attached below. In the header i tell you what to do with the file to add it to the lib, so i wont go over this. What i will talk about is its usage:
invoke DrawTransparentBitmap, hDC_Destination,
hBitmap to draw,
DC starting x point,
DC starting y point,
Transparent color
In usage the x,y point is where the upper right corner of the bitmap will be on the DC. The Transparency color can either be:
- [*] Any RGB color you choose, but as a DWORD, it must not have the 32nd bit set ( 80000000h ).
[*] TBM_FIRSTPIXEL :: This will use the first pixel (0,0) in the bitmap as the transparency color used. This equate is the 8000000h value.
There you go!.. Works very well on Win98SE. If you have problems with it let me know! As well Hutch, please feel free to add this to you next revision. I think Ernie's sugestion was a good one. (already added on my home masm32.lib).
Enjoy! And thanx again for all the other source everyone.
:alright:
NaN