Hello all,
I’m trying to convert a visual basic algorithm that copy a bitmap into
another performing a transparency effect. The transparence is the fined
by a chosen color. In orther to do that, it’s necessary to create a mask
to be used during some win32api bitblt operatios. That mask is a
mocromatic bitmap which has just 1 bit per pixel. Now comes, the
problem, how to create in ruby this kind of bitmap with the win32api
function CreateBitmap? That function prototype is:
Public Declare Function CreateBitmap Lib “gdi32” Alias “CreateBitmap”
(ByVal nWidth As Long, ByVal nHeight As Long, ByVal nPlanes As Long,
ByVal nBitCount As Long, lpBits As Any) As Long
And when it’s used in visual basic to generate the monocromatic bitmap,
it is called like that:
hMaskBmp = CreateBitmap(Width, Height, 1, 1, ByVal 0&)
The problem is the last value: Byval 0&. This is a “special” convention
by vb for DLL function calls to pass an empty value for “pointer”
values. The & in the end indicates that the data type of the 0 should be
“long” and not integer or byte.
How to do the same thing in ruby? I tried several things but none
worked. Could someone help me with that? The code that I last tried is
at follow.
class Bitmap
RtlMoveMemory_pi = Win32API.new(‘kernel32’, ‘RtlMoveMemory’, ‘pii’, ‘i’)
FindWindow = Win32API.new(‘user32’, ‘FindWindow’, ‘pp’, ‘i’)
GetDC = Win32API.new(‘user32’, ‘GetDC’, ‘i’, ‘i’)
ReleaseDC = Win32API.new(‘user32’, ‘ReleaseDC’, ‘ii’, ‘i’)
BitBlt = Win32API.new(‘gdi32’, ‘BitBlt’, ‘iiiiiiiii’, ‘i’)
CreateCompatibleBitmap = Win32API.new(‘gdi32’,
‘CreateCompatibleBitmap’, ‘iii’, ‘i’)
CreateCompatibleDC = Win32API.new(‘gdi32’, ‘CreateCompatibleDC’, ‘i’,
‘i’)
DeleteObject = Win32API.new(‘gdi32’, ‘DeleteObject’, ‘i’, ‘i’)
GetDIBits = Win32API.new(‘gdi32’, ‘GetDIBits’, ‘iiiiipi’, ‘i’)
SelectObject = Win32API.new(‘gdi32’, ‘SelectObject’, ‘ii’, ‘i’)
SetDIBits = Win32API.new(‘gdi32’, ‘SetDIBits’, ‘iiiiipi’, ‘i’)
TransparentBlt = Win32API.new(‘msimg32’, ‘TransparentBlt’,
‘iiiiiiiiiii’,‘i’)
SetBkColor = Win32API.new(‘gdi32’, ‘SetBkColor’, ‘ii’, ‘i’)
CreateBitmap = Win32API.new(‘gdi32’, ‘CreateBitmap’, ‘iiiip’, ‘i’)
DeleteDC = Win32API.new(‘gdi32’, ‘DeleteDC’, ‘i’, ‘i’)
def address
unless @address
RtlMoveMemory_pi.call(a="\0"*4, id*2+16, 4)
RtlMoveMemory_pi.call(a, a.unpack(‘L’)[0]+8, 4)
RtlMoveMemory_pi.call(a, a.unpack(‘L’)[0]+16, 4)
@address = a.unpack(‘L’)[0]
end
return @address
end
def transpblt2(x, y, src_bmp, src_rect, color_obj)
hDC1, hBM1, info = *self.BltApiInit
hDC2, hBM2 = *src_bmp.BltApiInit
#---------------------------------------------------------------------------
dsthDC = hDC1
srchDC = hDC2
crTransparent = color_obj.red + color_obj.green*256 +
color_obj.blue*65536
#First create some DC's. These are our gateways to assosiated
bitmaps in RAM
maskDC = CreateCompatibleDC.call(dsthDC) #DC for the mask
tempDC = CreateCompatibleDC.call(dsthDC) #DC for temproary data
#Then we need the bitmaps. Note that we create a monochrome bitmap
here!
#this is a trick we use for creating a mask fast enough:
#Bitmap for mask
info2 = [40,width,height,1,1,0,0,0,0,0,0].pack('LllSSLLllLL')
hMaskBmp = CreateBitmap.call(src_rect.width, src_rect.height, 1, 1,
info2)
# Bitmap for temporary data
hTempBmp = CreateCompatibleBitmap.call(dsthDC, src_rect.width,
src_rect.height)
#..then we can assign the bitmaps to the DCs
hMaskBmp = SelectObject.call(maskDC, hMaskBmp)
hTempBmp = SelectObject.call(tempDC, hTempBmp)
#Now we can create a mask..First we set the background color to the
#transparent color then we copy the image into the monochrome
bitmap.
#When we are done, we reset the background color of the original
source.
crTransparent = SetBkColor.call(srchDC, crTransparent)
BitBlt.call( maskDC, 0, 0, src_rect.width, src_rect.height, srchDC,
src_rect.x, src_rect.y, 0xCC0020)
crTransparent = SetBkColor.call(srchDC, crTransparent)
#'The first we do with the mask is to MergePaint it into the
destination.
#this will punch a WHITE hole in the background exactly were we want
the
#graphics to be painted in.
BitBlt.call( tempDC, 0, 0, src_rect.width, src_rect.height, maskDC,
0, 0, 0xCC0020)
BitBlt.call( dsthDC, x, y, src_rect.width, src_rect.height, tempDC,
0, 0, 0xBB0226) #merpaint
#Now we delete the transparent part of our source image. To do this
#we must invert the mask and MergePaint it into the source image.
the
#transparent area will now appear as WHITE.
BitBlt.call( maskDC, 0, 0, src_rect.width, src_rect.height, maskDC,
0, 0, 0x330008) #vbNotSrcCopy
BitBlt.call( tempDC, 0, 0, src_rect.width, src_rect.height, srchDC,
0, 0, 0xCC0020)#vbSrcCopy
BitBlt.call( tempDC, 0, 0, src_rect.width, src_rect.height, maskDC,
0, 0, 0xBB0226)#vbMergePaint
#Both target and source are clean, all we have to do is to AND them
together!
BitBlt.call(dsthDC, x, y, src_rect.width, src_rect.height, tempDC,
0, 0, 0x8800C6)#vbSrcAnd
#Now all we have to do is to clean up after us and free system
resources…
DeleteObject.call(hMaskBmp)
DeleteObject.call(hTempBmp)
DeleteDC.call(maskDC)
DeleteDC.call(tempDC)
#-------------------------------------------------------------------------------
GetDIBits.call(hDC1, hBM1, 0, height, address, info, 0)
DeleteObject.call(hBM1); DeleteObject.call(hDC1)
DeleteObject.call(hBM2); DeleteObject.call(hDC2)
end
def BltApiInit
info = [40,width,height,1,32,0,0,0,0,0,0].pack(‘LllSSLLllLL’)
hWndDC = GetDC.call(hWnd=FindWindow.call(‘RGSS Player’, 0))
hMemDC = CreateCompatibleDC.call(hWndDC)
hMemBM = CreateCompatibleBitmap.call(hWndDC, width, height)
ReleaseDC.call(hWnd, hWndDC)
SelectObject.call(hMemDC, hMemBM)
SetDIBits.call(hMemDC, hMemBM, 0, height, address, info, 0)
return hMemDC, hMemBM, info
end
#------------------------------------------------------------------------------
end