grham Posted November 6, 2010 Share Posted November 6, 2010 Hello, I was playing around with the bitblt function, this time I was using it to create a Mask for an image. It's successfull when I load the image with _WinAPI_LoadImage It has to be from a BMP file. Here an simple working example (with double buffering). In my case the "color for transparency" is black but you can change it. The "color for transparency has to be BGR. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Don't forget to put your image there!!!!!!!!!!!!!!!!!!!!!!!!!!!!! expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=n #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <Winapi.au3> #include <Constants.au3> #include <WindowsConstants.au3> $sImage = "(PUT HERE THE PATH OF YOUR IMAGE!!!!!!!!!).bmp" $hBmp_Source = _WinAPI_LoadImage(0, $sImage, $IMAGE_BITMAP, 0, 0, $LR_LOADFROMFILE) $stBitmap = DllStructCreate("long bmType;long bmWidth;long bmHeight;long bmWidthBytes;WORD bmPlanes;WORD bmBitsPixel;ptr bmBits") _WinAPI_GetObject($hBmp_Source, DllStructGetSize($stBitmap), DllStructGetPtr($stBitmap)) $nWidth = DllStructGetData($stBitmap, "bmWidth") $nHeight = DllStructGetData($stBitmap, "bmHeight") $hWindow = GUICreate("GDI BitBlt (Masked image)", $nWidth, $nHeight) Global $clrBackground = 0x10A040 GUISetBkColor($clrBackground, $hWindow) Global $clrTransparent = 0x000000 ; BGR! $hBmp_Mask = _CreateMask($hBmp_Source, $clrTransparent) ; Now we have our source image and its mask that we will use ; in the _OnPaint function GUIRegisterMsg($WM_PAINT, "WM_PAINT") GUISetState() While True If GUIGetMsg() = -3 Then ExitLoop WEnd _WinAPI_DeleteObject($hBmp_Mask) _WinAPI_DeleteObject($hBmp_Source) ; ======================================================================== ; FUNCTIONS ; ======================================================================== Func _CreateMask(ByRef $hBmp_Source, $clrTransparent) $hDC_Dest = _WinAPI_CreateCompatibleDC(0) ; DC (Mask) $hBmp_Mask = _WinAPI_CreateBitmap($nWidth, $nHeight, 1, 1, 0) ; Mask (1 bit per pixel) $hBmp_Mask_Prev = _WinAPI_SelectObject($hDC_Dest, $hBmp_Mask) ; Select Mask to DC $hDC_Source = _WinAPI_CreateCompatibleDC(0) ; DC (Source) $hBmp_Source_Prev = _WinAPI_SelectObject($hDC_Source, $hBmp_Source) ; Select Source image (BMP) to DC (Source) _WinAPI_SetBkColor($hDC_Source, $clrTransparent) ; Set background color of the Source DC _WinAPI_BitBlt ($hDC_Dest, 0, 0, $nWidth, $nHeight, $hDC_Source, 0, 0, $SRCCOPY) ; pixels in the "Source color bitmap" that are equal to the background color ; are blitted as white. All the remaining pixels are blitted as black. _WinAPI_BitBlt ($hDC_Source, 0, 0, $nWidth, $nHeight, $hDC_Dest, 0, 0, $SRCINVERT) ; Paint onto the original image, making sure that ; the "transparent" area is set to black. _WinAPI_SelectObject($hDC_Source, $hBmp_Source_Prev) ; Clean te two DCs _WinAPI_DeleteDC ($hDC_Source) _WinAPI_SelectObject($hDC_Dest, $hBmp_Mask_Prev) _WinAPI_DeleteDC ($hDC_Dest) Return $hBmp_Mask EndFunc ; ==> _CreateMask Func _OnPaint($hWnd) $hDC = _WinAPI_GetDC($hWnd) ; DC (Screen / Window) $hDC_Buf = _WinAPI_CreateCompatibleDC($hDC) ; Do all the painting on this buffer $hBmp_Buf = _WinAPI_CreateCompatibleBitmap($hDC, $nWidth, $nHeight) ; Then copy the content of this buffer to your Window / GUI (see 4.) $Buf_Prev = _WinAPI_SelectObject($hDC_Buf, $hBmp_Buf) _WinAPI_BitBlt ($hDC_Buf, 0, 0, $nWidth, $nHeight, $hDC, 0, 0, $SRCCOPY) ; 1. Copy the content of your Window / GUI to the buffer $hDC_Mem = _WinAPI_CreateCompatibleDC(0) ; Memory DC $hBmp_Prev = _WinAPI_SelectObject($hDC_Mem, $hBmp_Mask) _WinAPI_BitBlt ($hDC_Buf, 0, 0, $nWidth, $nHeight, $hDC_Mem, 0, 0, $SRCAND) ; 2. (AND) BitBlt the mask to the buffer with SRCAND _WinAPI_SelectObject($hDC_Mem, $hBmp_Source) _WinAPI_BitBlt ($hDC_Buf, 0, 0, $nWidth, $nHeight, $hDC_Mem, 0, 0, $SRCPAINT) ; 3. (OR) BitBlt your source image to he buffer with $SRCPAINT _WinAPI_BitBlt($hDC, 0, 0, $nWidth, $nHeight, $hDC_Buf, 0, 0, $SRCCOPY) ; 4. Copy the content of the buffer back to your Window / GUI _WinAPI_SelectObject($hDC_Mem, $hBmp_Prev) ; Clean ressources _WinAPI_DeleteDC ($hDC_Mem) _WinAPI_SelectObject($hDC_Buf, $Buf_Prev) _WinAPI_DeleteDC ($hDC_Buf) _WinAPI_DeleteObject($hBmp_Buf) _WinAPI_ReleaseDC($hWnd, $hDC) EndFunc ; ==> _OnPaint Func WM_PAINT($hWnd, $Msg, $wParam, $lParam) _OnPaint($hWnd) EndFunc ; ==> WM_PAINT but if you load an image from (for instance) a jpg with gdi+, you have to create a GDI hBitmap from it first. This hBitmap is not the same as when its loaded directly with GDI. When you bitblt it to an 1 bit per pixel Bitmap (to create a mask) the result is all black. If I understand it correctly, this is because it's a DIB and not a DDB. In that case it should be "converted" to a DDB Bitmap. I tried to do it but still without success. There is somethig incorrect in the code. I use _GDI_CreateDIBitmap (by Prog@ndy). RGBQuad member of BITMAPINFO has to be an array but I don't know the required size of that array. but from MSDN (for a 32 bpp image): The bitmap has a maximum of 2^32 colors. If the biCompression member of the BITMAPINFOHEADER is BI_RGB, the bmiColors member of BITMAPINFO is NULL. Each DWORD in the bitmap array represents the relative intensities of blue, green, and red, respectively, for a pixel. The high byte in each DWORD is not used. _GDI_CreateDIBitmap returns a Handle to a new bitmap but it's all black. Here is what I tried (and is wrong). !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Don't forget to put your image there!!!!!!!!!!!!!!!!!!!!!!!!!!!!! expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=n #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <GdiPlus.au3> #include <Winapi.au3> #include <Constants.au3> #include <WindowsConstants.au3> Global Const $BI_RGB = 0 Global Const $DIB_RGB_COLORS = 0 Global Const $CBM_INIT = 0x4 ; tagBITMAPINFOHEADER Global Const $tagBITMAPINFOHEADER = "DWORD biSize;" & _ "LONG biWidth;" & _ "LONG biHeight;" & _ "ushort biPlanes;" & _ "ushort biBitCount;" & _ "DWORD biCompression;" & _ "DWORD biSizeImage;" & _ "LONG biXPelsPerMeter;" & _ "LONG biYPelsPerMeter;" & _ "DWORD biClrUsed;" & _ "DWORD biClrImportant;" Global Const $tagBMPInfo256 = $tagBITMAPINFOHEADER & "dword RGBQuad;" $BMPInfo = DllStructCreate ($tagBMPInfo256) $stBitmap = DllStructCreate("long bmType;long bmWidth;long bmHeight;long bmWidthBytes;WORD bmPlanes;WORD bmBitsPixel;ptr bmBits") ; ============================================= _GDIPlus_Startup() $pImage = _GDIPlus_ImageLoadFromFile ("HERE THE IMAGE FROM FILE PATH") $hBmp_Source = _GDIPlus_BitmapCreateHBITMAPFromBitmap($pImage) _GDIPlus_ImageDispose($pImage) _GDIPlus_Shutdown() ; ========================================================= ; Get DDC Bitmap $hdcTmp = _WinAPI_GetDC (0) $hdcMem = _WinAPI_CreateCompatibleDC ($hdcTmp) _WinAPI_ReleaseDC (0, $hdcTmp) $hBitmapOld = _WinAPI_SelectObject ($hdcMem, $hBmp_Source) _WinAPI_GetObject($hBmp_Source, DllStructGetSize($stBitmap), DllStructGetPtr($stBitmap)) $xWidth = DllStructGetData($stBitmap, "bmWidth") $xHeight = DllStructGetData($stBitmap, "bmHeight") DllStructSetData ($BMPInfo, 1, DllStructGetSize($BMPInfo)) DllStructSetData ($BMPInfo, "biWidth" , $xWidth) DllStructSetData ($BMPInfo, "biHeight" , -$xHeight) DllStructSetData ($BMPInfo, "biPlanes" , 1) DllStructSetData ($BMPInfo, "biBitCount" , 32) DllStructSetData ($BMPInfo, "biCompression", $BI_RGB) DllStructSetData ($BMPInfo, "biSizeImage" , $xWidth * $xHeight) DllStructSetData ($BMPInfo, "biClrUsed" , 2^32) $BMPData = DllStructCreate("byte[" & ($xWidth * $xHeight) & "]") Local $pBMPData = DllStructGetPtr($BMPData) $hDDC_BMP = _GDI_CreateDIBitmap($hdcMem, DllStructGetPtr($BMPInfo), 0, $pBMPData, DllStructGetPtr($BMPInfo), $DIB_RGB_COLORS) ConsoleWrite("New Bitmap Handle: " & $hDDC_BMP & @CRLF & @CRLF) _WinAPI_SelectObject($hdcMem, $hBitmapOld) _WinAPI_DeleteDC ($hdcMem) _WinAPI_DeleteObject($hBmp_Source) If Not $hDDC_BMP Then Exit _WinAPI_GetObject($hDDC_BMP, DllStructGetSize($stBitmap), DllStructGetPtr($stBitmap)) ; Get Info about the new bitmap ConsoleWrite("Info about the new bitmap: " & @CRLF) For $i = 1 To 7 ConsoleWrite(DllStructGetData($stBitmap, $i) & @CRLF) Next ; EndOf DDC Bitmap Creation ; =========================================================== $nWidth = DllStructGetData($stBitmap, "bmWidth") $nHeight = DllStructGetData($stBitmap, "bmHeight") $hWindow = GUICreate("GDI BitBlt", $nWidth, $nHeight) GUISetState() ; ==================================================================== $hDC = _WinAPI_GetDC($hWindow) ; DC (Screen / Window) $hDC_Source = _WinAPI_CreateCompatibleDC($hDC) $hBmp_Prev = _WinAPI_SelectObject($hDC_Source, $hDDC_BMP) ; ===================================================================== _WinAPI_BitBlt($hDC, 0, 0, $nWidth, $nHeight, $hDC_Source, 0, 0, $SRCCOPY) ; BitBlt (Source to Buffer) _WinAPI_SelectObject($hDC_Source, $hBmp_Prev) _WinAPI_DeleteDC ($hDC_Source) _WinAPI_DeleteObject($hDDC_BMP) _WinAPI_ReleaseDC($hWindow, $hDC) While True If GUIGetMsg() = -3 Then ExitLoop WEnd Func _GDI_CreateDIBitmap($hDC, $lpbmih, $fdwInit, $lpbInit, $lpbmi, $fuUsage) Local $aResult = DllCall("Gdi32.dll", "ptr", "CreateDIBitmap", "ptr", $hDC, "ptr", $lpbmih, "DWORD", $fdwInit, "ptr", $lpbInit, "ptr", $lpbmi, "UINT", $fuUsage) If @error Then Return SetError(1, 0, 0) Return $aResult[0] EndFunc ;==>_GDI_CreateDIBitmap Info in Console. Thanks (AKA Grham) Link to comment Share on other sites More sharing options...
AdmiralAlkex Posted November 6, 2010 Share Posted November 6, 2010 May I ask, why do you want the black parts to be green (transparent)? Is there actually a point other than playing around with _WinAPI_BitBlt()? .Some of my scripts: ShiftER, Codec-Control, Resolution switcher for HTC ShiftSome of my UDFs: SDL UDF, SetDefaultDllDirectories, Converting GDI+ Bitmap/Image to SDL Surface Link to comment Share on other sites More sharing options...
grham Posted November 6, 2010 Author Share Posted November 6, 2010 (edited) I started: hereand here Edited November 6, 2010 by grham Link to comment Share on other sites More sharing options...
AndyG Posted November 6, 2010 Share Posted November 6, 2010 Hi, if you want to blit "sprites" there are two methods: Bitblt(background,0,0,x,y,mask,0,0,SRCAND) ;mask AND background Bitblt(background,0,0,x,y,sprite,0,0,SRCINVERT) ;sprite INVERT background or Transparentblt((background,0,0,x,y,sprite,0,0,x1,y1,COLOR) ;sprite onto background The sprite has a backgroundcolor, which will be transparent after Transparentblt(). No mask needed.... #include <WinAPIEX.au3> _WinAPI_transparentblt() Link to comment Share on other sites More sharing options...
grham Posted November 6, 2010 Author Share Posted November 6, 2010 Cool! I will give it a try this weekend. Danke schön für die Information! Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now