User Tools

Site Tools


drawing_20a_20transparent_20bitmap

Drawing a Transparent Bitmap

Introduction by Richard Russell

The commands built into BBC BASIC for Windows for displaying a bitmap image (*DISPLAY and *MDISPLAY) can only display an opaque image, i.e. anything 'underneath' the image will be obliterated. You may sometimes want to display a transparent image, that is one which has some regions in which you can see 'through' it to what lies beneath; you can do that using Windows GDI (Graphics Device Interface) API functions or BB4W library functions.

There are a number of different ways in which you can create and display a 'transparent' image:

  • Create the image as an icon (e.g. in the form of a .ICO file). An icon consists of two parts: a bitmap image and a mask; the mask is a one-bit-per-pixel bitmap determining which pixels of the image are opaque and which are transparent. You can create an icon in memory (e.g. CreateIcon API) or load it from a file (e.g. LoadIcon or LoadImage) and then display it using (e.g.) the Windows DrawIcon API or the SPRITELIB library.
  • Use a separate mask. As with the icon method, the mask consists of a one-bit-per-pixel monochrome bitmap (having the same dimensions as the image), determining which pixels of the image are opaque and which are transparent. You can display the resulting transparent bitmap using the MaskBlt API.
  • Define one of the colours in the bitmap image as 'transparent'; for example you could define all the 'black' pixels as being transparent. You can achieve that using the TransparentBlt function described in the main article below, or by means of the GFXLIB library.
  • Create the image as a 32-bits-per-pixel ARGB bitmap, in which each pixel consists of a 24-bit RGB value (8 bits red, 8 bits green, 8 bits blue) plus an 8-bit alpha value. The alpha value defines a 'per-pixel' opacity which can be anything from 0 (fully transparent) to 255 (fully opaque). You can display such a bitmap using the AlphaBlend API, by using the GDIplus or Direct3D subsystems, or by means of the GFXLIB library.
  • Create the image as a Transparent GIF or PNG and display it using, for example, the code listed here.


by Michael Hutton, July 2009

How do you make a part of a bitmap transparent? One way is to use the “TransparentBlt” function supplied in MSIMG32.DLL.

First select a MODE and define some constants:

        MODE 8
 
        REM!WC
        IMAGE_BITMAP = 0
        LR_LOADFROMFILE = &10
 
        DIM rect{l%,t%,r%,b%}
 
        cx% = 64 : REM width
        cy% = 64 : REM height

Next, we have to load the MSIMG32.DLL into memory and get the address of the “TransparentBlt” function.

        SYS "LoadLibrary", "MSIMG32.DLL" TO msimg32%
        SYS "GetProcAddress", msimg32%, "TransparentBlt" TO `TransparentBlt`

Next, load the image we want (we will assume it's in the same directory and is called star.bmp).

        bmpfile$ = @dir$ + "star.bmp"
        SYS "LoadImage", 0, bmpfile$, IMAGE_BITMAP, cx%, cy%, LR_LOADFROMFILE TO hbitmap%
        IF hbitmap% = 0 THEN ERROR 100,"Cannot Load Image."

Now, because we are using GDI and we only have a handle to the bitmap we have to create a new Device Context and select our bitmap into it. (A bitmap can only be selected into one DC at a time).

        SYS "CreateCompatibleDC", @memhdc% TO hdc%
        SYS "SelectObject", hdc%, hbitmap% TO old%

Now, we can ask GDI to transfer that bitmap into our main window. When using “TransparentBlt” we can select an RGB (COLOURREF) value to make transparent when it is drawing. It is the last parameter in “TranparentBlt”. Here I have selected 0 which is all the black bits (Red = 0, Green = 0, Blue = 0) but you can make it any colour you want. We also update a RECT{} so that we only update the region of the screen which has changed. It is much quicker to do this than update the whole window.

        FOR I% = 0 TO 50
          xpos% = RND(640)
          ypos% = RND(500)
          rect.l% = xpos%
          rect.r% = xpos% + cx%
          rect.t% = ypos%
          rect.b% = ypos% + cy%
          SYS `TransparentBlt`, @memhdc%, xpos%, ypos%, cx%, cy%, hdc%, 0, 0, cx%, cy%, 0
          SYS "InvalidateRect", @hwnd%, rect{}, 0
          WAIT 1
        NEXT

Now we must remember to cleanup all the GDI objects we have created otherwise we will end up with a leak.

        SYS "SelectObject", hdc%, old%
        SYS "DeleteDC", hdc%
        SYS "DeleteObject", hbitmap%
        SYS "FreeLibrary", msimg32%
        END

The example to copy and paste:

        MODE 8
 
        REM!WC
        IMAGE_BITMAP = 0
        LR_LOADFROMFILE = &10
 
        DIM rect{l%,t%,r%,b%}
 
        SYS "LoadLibrary", "MSIMG32.DLL" TO msimg32%
        SYS "GetProcAddress", msimg32%, "TransparentBlt" TO `TransparentBlt`
 
        cx% = 64
        cy% = 64
 
        bmpfile$ = @dir$ + "star.bmp"
 
        SYS "LoadImage", 0, bmpfile$, IMAGE_BITMAP, cx%, cy%, LR_LOADFROMFILE TO hbitmap%
        IF hbitmap% = 0 THEN ERROR 100,"Cannot Load Image."
 
        SYS "CreateCompatibleDC", @memhdc% TO hdc%
        SYS "SelectObject", hdc%, hbitmap% TO old%
 
        FOR I% = 0 TO 50
          xpos% = RND(640)
          ypos% = RND(500)
          rect.l% = xpos%
          rect.r% = xpos% + cx%
          rect.t% = ypos%
          rect.b% = ypos% + cy%
          SYS `TransparentBlt`, @memhdc%, xpos%, ypos%, cx%, cy%, hdc%, 0, 0, cx%, cy%, 0
          SYS "InvalidateRect", @hwnd%, rect{}, 0
          WAIT 1
        NEXT
 
        SYS "SelectObject", hdc%, old%
        SYS "DeleteDC", hdc%
        SYS "DeleteObject", hbitmap%
        SYS "FreeLibrary", msimg32%
 
        END

And there we are! Enjoy.

Michael Hutton

This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information
drawing_20a_20transparent_20bitmap.txt · Last modified: 2018/04/13 15:38 by richardrussell