CS-460/560, Week 8-C
Spring, 1998
R. Eckert


If an image is stored in frame buffer, we can translate it by:

   Embed it in a rectangle
   Copy the bit pattern of each pixel in the rectangle to a destination rectangle

   This is a simple double loop.

   Assume coordinates of diagonally opposite corners of the embedding rectangle
   are (x1,y1) and (x2,y2), and that we want to translate the enclosed image to 
   by (tx,ty). The following pseudocode will do the job:

   for (x=x1 to x2)
      for (y=y1 to y2)
         color = GetPixel(x,y);        //retrieve color of each pixel
         SetPixel(x+tx, y+ty, color);  //paint destination rectangle pixels

This kind of operation is known as a Bit Block Transfer (BIT BLT, or "blitting").
It CAN be very fast if we have direct access to the frame buffer. 

Windows uses bitmaps to achieve the effect of Bit Blitting. The Windows API also
provides functions to move and stretch bitmaps. Unfortunately, they are very


Bitmap--An Off-screen Canvas:

  -rectangular image, can be created with painting pgms
  -data structure that stores a matrix of pixel values in memory
  -pixel value stored determines color of pixel in image
  -Windows supports 4-bit, 8-bit (indirect), & 24-bit (direct) pixel values
  -can be stored as .bmp files (static resource data)
  -can be edited; can save any picture
  -but takes up lots of space
  -a GDI object that must be selected into a Device Context to be used
  -can be thought of as the canvas of a DC upon which drawing takes place
  -must be compatible with a video display or printer
  -can be manipulated invisibly and apart from physical display device
  -fast transfer to/from physical device ==> flicker free animation
  -does not store info on drawing commands (use metafiles for that)
  -icons & cursors are small bitmaps

Using bitmaps--
  -Create and save bitmap using a paint editor --> image.bmp
  -Add to pgm's resource script file, e.g.:     Img   BITMAP   image.bmp

  -To display it, we must first load it from the pgm's resources:
      HBITMAP    hBitmap;
      HANDLE     hINstance;
      hInstance = (HINSTANCE)GetWindowLong (hWnd, GWL_HINSTANCE);
      hBitmap = LoadBitmap (hInstance, "Img");
  -Note the use of GetWindowLong() to get the pgm's instance handle which
   identifies the pgm's resource data. This is one possible way of getting
   hInstance. (The type cast is necessary to avoid a compiler warning since
   GetWindowLong() is typed as a ptr to a void--which is not the same as
   HINSTANCE.) Once we have the instance handle, we can call any of the
   Windows functions that load in program resources. Here LoadBitmap() is
   used to get our bitmap.

To display the bitmap--
   0. Get a DC (as usual)
   1. Create a memory device context with CreateCompatibleDC()
   2. Load bitmap with LoadBitmap() [or create it w/ CreateCompatibleBitmap()]
   3. Select bitmap into the memory DC with SelectObject()
   4. Copy bitmap from memory DC to device DC using BitBlt() or StretchBit()

We can say:       Bitmap          Window Client Area
                ----------   =   --------------------
                Memory DC                DC

Memory DC-- Like a DC for a physical device, but not tied to device. Used
to access a bitmap rather than a device. A bitmap must be selected into a
memory DC before it can be displayed on the physical device.

CreateCompatibleDC(hDC)-- creates a memory DC with same physical attributes
as DC of the given device. Subsequent call to SelectObject() to select a
bitmap into this DC sets up the bitmap data with the exact sequence of data
needed to display on the physical device ==> copying from Memory DC to
device DC is very fast!

BitBlt (hDestinationDC, x, y, w, h, hSrcDC, xsrc, ysrc, dwRop) --
   Copies pixels from bitmap selected into source DC to destination DC.
   (x,y) specify upper left hand corner on destination rectangle;
   w,h -- width, height in pixels of rectangle to be copied
   xsrc, ysrc -- upper left hand corner source bitmap
   dwRop -- raster operation for copy

Raster Ops-- how to combine source pixel colors with current pixel colors on
destination screen. Boolean logic combinations (AND, NOT, OR, XOR, etc.)
Currently-selected brush pattern also can be combined==> 256 different
possible combintations, 15 named.  (in ff table: S=source bitmap,
D=destination bitmap, P=currently-selected brush, i.e., the current Pattern)

BLACKNESS       0 (all black)
PATCOPY         P
PATPAINT        (~S | P) | D
SRCAND          S & D
SRCCOPY         S
SRCERASE        S & ~D
SRCPAINT        S | D
WHITENESS       1 (all white)

StretchBlt()-- Same as BitBlt() except size of copied bitmap can be changed.
Both source and destination width/height specified.

 StretchBlt (hDestinationDC,x,y,w,h,hSrcDC, xsrc,ysrc,wsrc,hsrc,RasterOp)

PatBlt (hDC, x, y, w, h, dwRop) -- Paints a bit pattern on the specified
DC. The pattern is a combination of the currently-selected brush and the
pattern already on the destination device. x,y,w,h determine the rectangular
area and dwRop (raster op) specifies how the pattern will be combined with
the destination pixels. Possible dwRops are: BLACKNESS (0), DSTINVERT (~D),
PATCOPY (P), PATINVERT (P^D), and WHITENESS (1). The pattern is tiled across
the specified area.

The following is an example of how BitBlt() and StretchBlt() can be used
in a WndProc():

                          WPARAM wParam, LPARAM lParam)
    HDC         hDC, hMemDC ;
    HBITMAP     hBitmap ;
    HINSTANCE   hInstance ;
    switch (wMessage)       /* process windows messages */
        case WM_COMMAND:
            switch (wParam)
                case IDM_SHOW:
                hInstance = (HINSTANCE)GetWindowLong (hWnd, GWL_HINSTANCE) ;
                hBitmap = LoadBitmap (hInstance, "HouseBmp") ;  //load from resources
                hDC = GetDC (hWnd) ;
                hMemDC = CreateCompatibleDC (hDC) ;
                SelectObject (hMemDC, hBitmap) ;
                BitBlt (hDC, 0, 0, 32, 32, hMemDC, 0, 0, SRCCOPY) ;
                BitBlt (hDC, 50, 0, 64, 64, hMemDC, 0, 0, SRCCOPY) ;
                BitBlt (hDC, 150, 0, 32, 32, hMemDC, 32, 32, SRCCOPY) ;
                StretchBlt (hDC, 0,100,32,32, hMemDC, 0,0,64,64, SRCCOPY) ;
                StretchBlt (hDC, 50,100,64,64, hMemDC, 0,0,64,64, SRCCOPY) ;
                StretchBlt (hDC, 150,100,128,128, hMemDC, 0,0,64,64, SRCCOPY) ;
                StretchBlt (hDC, 300,100,128,128, hMemDC, 0,0,32,32, SRCCOPY) ;  
                DeleteDC (hMemDC) ;
                ReleaseDC (hWnd, hDC) ;
                DeleteObject (hBitmap) ;
                break ;
            case IDM_QUIT:              // Quit menu item
                DestroyWindow (hWnd) ;
                break ;
            break ;
        case WM_DESTROY:                // stop application
            PostQuitMessage (0) ;
            break ;
            return (DefWindowProc (hWnd, wMessage, wParam, lParam)) ;
    return (0) ;