Fast Transparency

Environment: VB5, VB6

Visual Basic allows us programmers to develop highly graphical applications easily. Even bitmaps and text can be added in a matter of seconds. We can access the API and get even more elaborate multimedia applications. Even complex animation and games are within our grasp once we know a little about Visual Basic.

But there is one flaw. Neither Visual Basic nor the all-powerful API presents us with any possibilities for transparent bitmaps! How could this be? Did they forget? Well, it's not entirely true, because starting with Windows 2000, Microsoft added the TransparentBlt function. However, if you decide to use this, you cannot use the applications on computers having Windows 95, 98, NT, or Me, so it's useless unless you are targeting your application for a specific computer.

The only way that Visual Basic offers is to read each pixel and determine whether its color matches the transparent color, usually by iterating it through a for loop. This is a very tedious process, though, and unless the picture is smaller than an average postage stamp, the function will spend several minutes executing.

Obviously, this method cannot be used, but let's consider what it does anyway. Comparing each pixel's color to the transparent color? Isn't that what we HAVE to do? We simply have to compare each pixel for this to be possible, so we must find a faster way. The problem is that comparing colors is a major task for the CPU. Comparing two sets of 16 bit colors means that the CPU must make 32 comparisons to make sure! If you have a 640x480 pixel image, this would amount to 9,830,400 compare operations. If you want it with 32-bit color, you would double it. And, on top of this, it has the bothersome job of copying each pixel individually. This is a bit simplified, but you still get the idea. This is hard and time-consuming work for the computer.

We have to reduce the amount of data. We need to get back to the basics, a map of zeros and ones; we need a mask. And because this is a graphic image, this will appear as a black and white image. Once we understand this concept, we can apply some boolean math; we can use AND, XOR, OR, NOT, and so forth. The only information the processor has to deal with is ones and zeroes, and this, ladies and gentlemen, this is what a processor is really good at.

Creating a mask can be accomplished by a little trick of the API. First, we load a bitmap where a specific color, usually some kind of ghastly pink, marks the transparent part. Then, we set the bitmap's background color, using the API, to this transparent color. Now, we create a monochrome bitmap, and copy the source into it. The result is quite neat. Everything in the transparent color is WHITE; anything else is BLACK. The mask is completed! But beware, there are more tricks with the black and white bitmap, so if you want to avoid weird bugs, I suggest that you copy the mask into an ordinary bitmap prior to using it.

So, how do we use the mask? The answer lies in the the BitBlt-functions OpCodes. There are a whole lot of these, but the two most important ones to us are vbMergePaint (OR) and vbSrcAnd (AND). When you use the first one with a mask, everything that is BLACK will be painted and the WHITE will remain. If you use the latter, it is the other way around.

Now, the inner workings of BitBlt. The API and boolean math can be a lot to swallow at one gulp, and a full walktrough would take several pages. I suggest reading the KB and insert breakpoints to watch what happens if anything is unclear. The description here may seem shallow, but the code is well commented and pretty short so you should get by it.

We start by preparing the background. We need to punch out a white "hole" in the background were we want the source graphics to be pasted in. This is accomplished by ORing the mask with the target using vbMergePaint.

Now we must clean the foreground. We need to punch out the transparent part and make it white. This is exactly as with the background, except that we want the opposite part to be "whited out." Can we do this? Sure, just invert the mask first! Then, we can repeat the success we had with vbMergePaint.

To finish it off, we can simply AND foreground into the background, and call it a job well done!

Using this function is pretty straightforward. Just pass the hDC of the target and and source bitmap, enter the desired coordinates, and off you go! An example project is included if you are still doubting. Good Luck!

Sub TransparentBlt(dsthDC As Long, srchDC As Long, X As Integer, _
                   Y As Integer, Width As Integer, _
                   Height As Integer, TransColor As Long)
    Dim maskDC As Long      'DC for the mask
    Dim tempDC As Long      'DC for temporary data
    Dim hMaskBmp As Long    'Bitmap for mask
    Dim hTempBmp As Long    'Bitmap for temporary data

    'First, create some DC's. These are our gateways to associated
    'bitmaps in RAM
    maskDC = CreateCompatibleDC(dsthDC)
    tempDC = CreateCompatibleDC(dsthDC)

    '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.
    hMaskBmp = CreateBitmap(Width, Height, 1, 1, ByVal 0&)
    hTempBmp = CreateCompatibleBitmap(dsthDC, Width, Height)

    'Then we can assign the bitmaps to the DCs
    hMaskBmp = SelectObject(maskDC, hMaskBmp)
    hTempBmp = SelectObject(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.
    TransColor = SetBkColor(srchDC, TransColor)
    BitBlt maskDC, 0, 0, Width, Height, srchDC, 0, 0, vbSrcCopy
    TransColor = SetBkColor(srchDC, TransColor)

    'The first we do with the mask is to MergePaint it into the
    'This will punch a WHITE hole in the background exactly were
    'we want the graphics to be painted in.
    BitBlt tempDC, 0, 0, Width, Height, maskDC, 0, 0, vbSrcCopy
    BitBlt dsthDC, X, Y, Width, Height, tempDC, 0, 0, vbMergePaint

    '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 maskDC, 0, 0, Width, Height, maskDC, 0, 0, vbNotSrcCopy
    BitBlt tempDC, 0, 0, Width, Height, srchDC, 0, 0, vbSrcCopy
    BitBlt tempDC, 0, 0, Width, Height, maskDC, 0, 0, vbMergePaint

    'Both target and source are clean. All we have to do is to AND
    'them together!
    BitBlt dsthDC, X, Y, Width, Height, tempDC, 0, 0, vbSrcAnd

    'Now all we have to do is to clean up after us and free system
    DeleteObject (hMaskBmp)
    DeleteObject (hTempBmp)
    DeleteDC (maskDC)
    DeleteDC (tempDC)
End Sub


Download source - 4 Kb


  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Java developers know that testing code changes can be a huge pain, and waiting for an application to redeploy after a code fix can take an eternity. Wouldn't it be great if you could see your code changes immediately, fine-tune, debug, explore and deploy code without waiting for ages? In this white paper, find out how that's possible with a Java plugin that drastically changes the way you develop, test and run Java applications. Discover the advantages of this plugin, and the changes you can expect to see …

  • Do you know where your data is? Consumer cloud-based file sharing services store your sensitive company data on servers outside of your control, outside of your policy and regulatory guidelines – maybe even outside your country – and not managed by you. The potential for data leakage, security breaches, and harm to your business is enormous. Download this white paper to learn about file sync and share alternatives that allow you to manage and protect your sensitive data while integrating and …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds