DirectDraw and Bitmaps Part 3 - PowerPoint PPT Presentation

1 / 50
About This Presentation
Title:

DirectDraw and Bitmaps Part 3

Description:

– PowerPoint PPT presentation

Number of Views:98
Avg rating:3.0/5.0
Slides: 51
Provided by: enginUm
Category:

less

Transcript and Presenter's Notes

Title: DirectDraw and Bitmaps Part 3


1
DirectDraw and BitmapsPart 3
  • CIS 487/587
  • Bruce R. Maxim
  • UM-Dearborn

2
Reading Bitmap Files
  • The process of reading bit maps from files
    involves reading header information and then
    reading byte data into memory
  • The size of the memory region is determined the
    the color depth and screen dimensions from the
    header

3
Bitmap File Header
  • Bitmap file header
  • Bitmap info
  • Palette if palettized
  • Bitmap data
  • RGB Pixels
  • or
  • Indexed data

4
Bitmap File Header
  • typedef struct tag8BITMAPFILEHEADFER
  • WORD bfType // file type 0xD42 for
    .BMP
  • DWORD bfSize // file size in bytes
  • WORD bfReserved // must be 0
  • WORD bfReserved2 // must be 0
  • DWORD bfOffBits // length in bytes of header
  • BITMAPFILEHEADER

5
Bitmap Info Header
  • typedef struct tagBITMAPINFOHEADER
  • DWORD biSize // structure size in
    bytes
  • LONG biWidth // bitmap width
  • LONG biHeight // bitmap height (lt0
    upside down)
  • WORD biPlanes // color planes
  • WORD biBitCount // bits per pixel
    1,4,8,16,24,32
  • DWORD biCompression // compression type
    BI_RGB for .bmp
  • DWORD biSizeIMage // image size in bytes
  • LONG biXPelsPerMeter // pixels per meter
    x-axis
  • LONG biYPelsPerMeter // pixels per meter
    y-axis
  • DWORD biClrUsed // colors used in
    bitmap
  • DWORD biClrImportant // important colors
  • BITMAPFILEHEADER

6
Bitmap Info Section
  • typedef struct BITMAP_FILE_TAG
  • BITMAPINFOHEADER bmiHeader // header info
  • RGBQUAD bmiColors1 // palette if one
    is used
  • BITMAPINFO

7
Bitmap Data Area
  • It is possible that the bitmap image was written
    line by line to the file upside down
  • It is also the case that the bitmap palette (if
    it exists) is written in RGB Quad which the
    reverse normal palette entries
  • It is easier to write your own bitmap loader than
    to tweak the data and try to use the LoadImage( )
    function in Win32 API

8
LaMothe Examples
9
BITMAP_FILE_TAG
  • // container structure for bitmaps .BMP file
  • typedef struct BITMAP_FILE_TAG
  • BITMAPFILEHEADER bitmapfileheader
  • // this contains the bitmapfile header
  • BITMAPINFOHEADER bitmapinfoheader
  • // this is all the info including the palette
  • PALETTEENTRY palette256
  • // we will store the palette here
  • UCHAR buffer
  • // this is a pointer to the data 
  • BITMAP_FILE, BITMAP_FILE_PTR

10
Load_Bitmap_File
  • int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char
    filename)
  • // this function opens a bitmap file and loads
    the data into bitmap
  • int file_handle, // the file handle
  • index // looping index
  • UCHAR temp_buffer NULL // used to convert
    24 bit images to 16 bit
  • OFSTRUCT file_data // the file data
    information
  • // open the file if it exists
  • if ((file_handle OpenFile(filename,file_data,
    OF_READ))-1)
  • return(0)
  • // now load the bitmap file header
  • _lread(file_handle, bitmap-gtbitmapfileheader,si
    zeof(BITMAPFILEHEADER))
  • // test if this is a bitmap file
  • if (bitmap-gtbitmapfileheader.bfType!BITMAP_ID)
  • _lclose(file_handle) // close the file
  • return(0) // return error
  • // end if

11
Load_Bitmap_File
  • // load the bitmap file header
  • _lread(file_handle, bitmap-gtbitmapinfoheader,si
    zeof(BITMAPINFOHEADER)) 
  • // now load the color palette if there is one
  • if (bitmap-gtbitmapinfoheader.biBitCount 8)
  • _lread(file_handle, bitmap-gtpalette,MAX_COLOR
    S_PALETTEsizeof(PALETTEENTRY))
  • // now set all the flags in the palette
    correctly and fix the reversed
  • // BGR RGBQUAD data format
  • for (index0 index lt MAX_COLORS_PALETTE
    index)
  • // reverse the red and green fields
  • int temp_color
    bitmap-gtpaletteindex.peRed
  • bitmap-gtpaletteindex.peRed
    bitmap-gtpaletteindex.peBlue
  • bitmap-gtpaletteindex.peBlue temp_color
  • // always set the flags word to this
  • bitmap-gtpaletteindex.peFlags
    PC_NOCOLLAPSE
  • // end for index
  • // end if

12
Load_Bitmap_File
  • // finally the image data itself
  • _lseek(file_handle,-(int)(bitmap-gtbitmapinfohead
    er.biSizeImage),SEEK_END)
  • // now read in the image
  • if (bitmap-gtbitmapinfoheader.biBitCount8
  • bitmap-gtbitmapinfoheader.biBitCount16
  • bitmap-gtbitmapinfoheader.biBitCount24)
  • // delete the last image if there was one
  • if (bitmap-gtbuffer)
  • free(bitmap-gtbuffer)
  • // allocate the memory for the image
  • if (!(bitmap-gtbuffer(UCHAR
    )malloc(bitmap-gtbitmapinfoheader.biSizeImage)))
  • _lclose(file_handle) // close the file
  • return(0) // return error
  • // end if
  • // now read it in
  • _lread(file_handle,bitmap-gtbuffer,bitmap-gtbit
    mapinfoheader.biSizeImage)
  • // end if

13
Load_Bitmap_File
  • // close the file
  • _lclose(file_handle)
  •  
  • // flip the bitmap
  • Flip_Bitmap(bitmap-gtbuffer,
  • bitmap-gtbitmapinfoheader.biWidth(bitmap
    gtbitmapinfoheader.biBitCount/8),
  • bitmap-gtbitmapinfoheader.biHeight)
  •  
  • // return success
  • return(1)
  • // end Load_Bitmap_File

14
Unload_Bitmap_File
  • int Unload_Bitmap_File(BITMAP_FILE_PTR bitmap)
  • // this function releases all memory associated
    with "bitmap"
  • if (bitmap-gtbuffer)
  • // release memory
  • free(bitmap-gtbuffer)
  •  
  • // reset pointer
  • bitmap-gtbuffer NULL
  • // end if
  •  
  • // return success
  • return(1)
  • // end Unload_Bitmap_File

15
Flip_BitMap
  • int Flip_Bitmap(UCHAR image, int bytes_per_line,
    int height)
  • // used to flip bottom-up .BMP images
  • UCHAR buffer // used to perform the image
    processing
  • int index // looping index
  • // allocate the temporary buffer
  • if (!(buffer (UCHAR )malloc(bytes_per_linehe
    ight)))
  • return(0)
  • // copy image to work area
  • memcpy(buffer,image,bytes_per_lineheight)
  • // flip vertically
  • for (index0 index lt height index)
  • memcpy(image((height-1) -
    index)bytes_per_line,
  • bufferindexbytes_per_line,
    bytes_per_line)
  • // release the memory
  • free(buffer)
  • // return success
  • return(1)
  • // end Flip_Bitmap

16
DDraw_Fill_Surface
  • int DDraw_Fill_Surface(LPDIRECTDRAWSURFACE7
    lpdds,int color)
  • DDBLTFX ddbltfx // this contains the DDBLTFX
    structure 
  • // clear out the structure and set the size
    field
  • DDRAW_INIT_STRUCT(ddbltfx)
  • // set the dwfillcolor field to the desired
    color
  • ddbltfx.dwFillColor color
  • // ready to blt to surface
  • lpdds-gtBlt(NULL, // ptr to dest rectangle
  • NULL, // ptr to source
    surface, NA
  • NULL, // ptr to source
    rectangle, NA
  • DDBLT_COLORFILL DDBLT_WAIT, //
    fill and wait
  • ddbltfx) // ptr to DDBLTFX
    structure 
  • // return success
  • return(1)
  • // end DDraw_Fill_Surface

17
Loading 16-Bit Bitmap
  • There is no palette to load
  • Very few paint programs actually create 16-bit
    bitmaps, so you may need to convert 24-bit to
    16-bit before drawing
  • LaMothes Load_Bitmap_File( ) does all this work
    for you

18
Loading 24-Bit Bitmaps
  • This is simplest of the 3 cases
  • However since many graphics cards support 32-bit
    pixel data rather than 24-bit and extra byte is
    used for padding or alpha channeling
  • Again Load_Bitmap_File( ) does most of the work
    for you

19
Using Offscreen Surfaces
  • Create a DirectDraw application
  • Create primary and secondary surfaces
  • Load bitmap into secondary surface
  • Load palette info in primary surface palette
  • Scan rectangles from regions on secondary surface
    and blit them to the primary surface
  • Note Steps 1 to 4 done in GameInit( ) and
  • ScanImage( ) used to extract animation frames

20
Game_Init( )
  • // create IDirectDraw interface 7.0 object and
    test for error
  • // set cooperation to full screen
  • // set display mode to 640x480x8
  • // we need a complex surface system with a
    primary and backbuffer
  • // set the backbuffer count field to 1
  • // request a complex, flippable
  • // create the primary surface
  • // now query for attached surface from the
    primary surface
  • // get the attached back buffer surface
  • // create the palette object
  • // finally attach the palette to the primary
    surface
  • // set clipper up on back buffer since that's
    where well clip

21
Game_Init( )
  • // load the 8-bit image
  • if (!Load_Bitmap_File(bitmap,"alley8.bmp"))
  • return(0)
  • // load it's palette into directdraw
  • if (FAILED(lpddpal-gtSetEntries(0,0,MAX_COLORS_PALE
    TTE,bitmap.palette)))
  • return(0)
  • // clean the surfaces
  • DDraw_Fill_Surface(lpddsprimary,0)
  • DDraw_Fill_Surface(lpddsback,0)
  • // create the buffer to hold the background
  • lpddsbackground DDraw_Create_Surface(640,480,0,-
    1)
  • // copy the background bitmap image to the
    background surface
  •  
  • // lock the surface
  • lpddsbackground-gtLock(NULL,ddsd,
    DDLOCK_SURFACEMEMORYPTR DDLOCK_WAIT,NULL)
  • // get video pointer to primary surfce
  • UCHAR image_buffer (UCHAR )ddsd.lpSurface

22
Game_Init( )
  • // copy memory from double buffer to primary
    buffer
  • // now unlock the primary surface
  •  
  • // unload the bitmap file, we no longer need it
  • Unload_Bitmap_File(bitmap)
  •  
  • // seed random number generator
  • srand(GetTickCount()) 
  • // initialize all the aliens
  • // alien on level 1 of complex
  • aliens0.x rand()SCREEN_WIDTH
  • aliens0.y 116 - 72
  • aliens0.velocity 2rand()4
  • aliens0.current_frame 0
  • aliens0.counter 0

23
Game_Init( )
  • // now load the bitmap containing the alien
    imagery
  • // then scan the images out into the surfaces of
    alien0
  • // and copy then into the other two, be careful
    of reference counts!
  •  
  • // load the 8-bit image
  • if (!Load_Bitmap_File(bitmap,"dedsp0.bmp"))
  • return(0)
  • // create each surface and load bits
  • for (int index 0 index lt 3 index)
  • // create surface to hold image
  • aliens0.framesindex DDraw_Create_Surface(7
    2,80,0)
  • // now load bits...
  • Scan_Image_Bitmap(bitmap, // bitmap file to
    scan image data from
  • aliens0.framesindex, // surface to hold
    data
  • index, 0) // cell to scan
    image from
  • // end for index

24
Game_Init( )
  • // unload the bitmap file, we no longer need it
  • Unload_Bitmap_File(bitmap)
  • // now for the tricky part. There is no need to
    create more
  • // surfaces with the same data, so you copy the
    surface
  • // pointers member for member to each alien
  • // however, be careful, since the reference
    counts do NOT go
  • // up, you still only need
  • // to release() each surface once!
  • for (index 0 index lt 3 index)
  • aliens1.framesindex
  • aliens2.framesindex
  • aliens0.framesindex

25
Scan_Image_Bitmap
  • int Scan_Image_Bitmap(BITMAP_FILE_PTR bitmap, //
    bitmap file
  • LPDIRECTDRAWSURFACE7 lpdds, //
    surface to hold data
  • int cx, int cy) //
    cell to scan image from
  • // this function extracts a bitmap out of a
    bitmap file
  • UCHAR source_ptr, // working pointers
  • dest_ptr
  • DDSURFACEDESC2 ddsd // direct draw surface
    description
  •  
  • // get the addr to destination surface memory
  • // set size of the structure
  • ddsd.dwSize sizeof(ddsd)
  • // lock the display surface
  • lpdds-gtLock(NULL,
  • ddsd,
  • DDLOCK_WAIT DDLOCK_SURFACEMEMORYPTR,
  • NULL)

26
Scan_Image_Bitmap
  • // compute position to start scanning bits from
  • cx cx(ddsd.dwWidth1) 1
  • cy cy(ddsd.dwHeight1) 1
  •  
  • gwidth ddsd.dwWidth
  • gheight ddsd.dwHeight
  •  
  • // extract bitmap data
  • source_ptr bitmap-gtbuffer cybitmap-gtbitmapinf
    oheader.biWidthcx
  •  
  • // assign a pointer to the memory surface for
    manipulation
  • dest_ptr (UCHAR )ddsd.lpSurface

27
Scan_Image_Bitmap
  • // iterate thru each scanline and copy bitmap
  • for (int index_y0 index_y lt ddsd.dwHeight
    index_y)
  • // copy next line of data to destination
  • memcpy(dest_ptr, source_ptr, ddsd.dwWidth)
  •  
  • // advance pointers
  • dest_ptr (ddsd.lPitch) //
    (ddsd.dwWidth)
  • source_ptr bitmap-gtbitmapinfoheader.biWidth
  • // end for index_y
  •  
  • // unlock the surface
  • lpdds-gtUnlock(NULL)

28
Drawing Blitter Objects
  • int DDraw_Draw_Surface(LPDIRECTDRAWSURFACE7
    source, // source surface to draw
  • int x, int y,
    // position to draw at
  • int width, int height,
    // size of source surface
  • LPDIRECTDRAWSURFACE7 dest,
    // surface to draw bob on
  • int transparent 1)
    // transparency flag
  • // draw a bob at the x,y defined in the BOB
  • // on the destination surface defined in dest
  • RECT dest_rect, // the destination rectangle
  • source_rect // the source rectangle
  • // fill in the destination rect
  • dest_rect.left x
  • dest_rect.top y
  • dest_rect.right xwidth-1
  • dest_rect.bottom yheight-1
  • // fill in the source rect
  • source_rect.left 0
  • source_rect.top 0
  • source_rect.right width-1

29
Drawing Blitter Objects
  • // test transparency flag
  • if (transparent)
  • // enable color key blit
  • // blt to destination surface
  • if (FAILED(dest-gtBlt(dest_rect, source,
    source_rect,
  • (DDBLT_WAIT DDBLT_KEYSRC),
    NULL)))
  • return(0)
  • // end if
  • else
  • // perform blit without color key
  • // blt to destination surface
  • if (FAILED(dest-gtBlt(dest_rect, source,
    source_rect,(DDBLT_WAIT), NULL)))
  • return(0)
  • // end if

30
Transparency
  • When your bitmap does not cover an entire
    rectangle you need to designate the background
    color as a transparent color so that screen in
    not wiped out when you blit
  • Most people use RGB black (0,0,0) when in RGB
    mode and color index 0 in palette color mode

31
Transparency
  • Each pixel is tested for transparency as it is
    drawn
  • To keep black objects in the foreground you might
    decide that anything blue in the destination
    cant be blitted

32
Color Keying
  • One nice thing about Direct Draw is that you can
    control which colors are transparent and then the
    blitter handles testing pixels for transparency
  • Source key blits are accomplished by using
    SetColorKey( ) to make a range of colors
    transparent
  • Destination key are also possible but not used in
    the LaMothe text

33
Rotaton and Scaling
  • The Direct Draw allows blitting with size
    scaling, but does not allow blitting with
    rotation
  • To get the effect of blitting with rotation in
    Direct Draw you need to set up your bitmap frames
    to show the rotation

34
Scaling (jaggies)
  • 1x4 pixels 1x8 pixels
  • 0 20 0 20
  • 5 1 20
  • 12 2 5
  • 85 3 5
  • 4 12
  • 5 12
  • 6 85
  • 7 85

35
Scaling (data loss)
  • 1x4 pixels 1x2 pixels
  • 0 20 0 20
  • 5 1 12
  • 12
  • 85

36
Filtering
  • To avoid severe data loss you could use a could
    probability filter to select colors to copy (e.g.
    sample_rate 4 / 3 1.33)
  • 0 12 0 0 12
  • 1 34 1.33 1 34
  • 2 56 2.66 2 56
  • 3 90

37
Game_Init
  • // initialize all the aliens
  • // alien on level 1 of complex
  • aliens0.x rand()SCREEN_WIDTH
  • aliens0.y 116 - 72
  • aliens0.velocity 2rand()4
  • aliens0.current_frame 0
  • aliens0.counter 0
  • aliens0.width 72 // set real size
  • aliens0.height 80
  • aliens0.scale ((float)(1rand()20))/
    10 // scale 0.1 to 2.0
  • // fix up feet so they still contact floor
  • aliens0.y(72 - aliens0.scale72)
  • // do the same for each alien and then load
    bitmaps as before

38
DDRaw_Draw_Surface_Scaled
  • int DDraw_Draw_Surface_Scaled(LPDIRECTDRAWSURFACE7
    source, // source
  • int x, int y,
    // position to draw
  • int width_src, int
    height_src, // size of source
  • int width_dest, int
    height_dest,// size of dest
  • LPDIRECTDRAWSURFACE7 dest,
    // surface to draw on
  • int transparent 1)
    // transparency flag
  • // draw the surface at the x,y defined by dest,
    send both the original
  • // source size of surface, along with the desired
    size, if they are
  • // different then directdraw will scale the
    bitmap for you
  • // note that we are sending the size of the
    surface

39
DDRaw_Draw_Surface_Scaled
  • RECT dest_rect, // the destination rectangle
  • source_rect // the source rectangle
  • // fill in the destination rect
  • dest_rect.left x
  • dest_rect.top y
  • dest_rect.right xwidth_dest-1
  • dest_rect.bottom yheight_dest-1
  •  
  • // fill in the source rect
  • source_rect.left 0
  • source_rect.top 0
  • source_rect.right width_src-1
  • source_rect.bottom height_src-1

40
DDRaw_Draw_Surface_Scaled
  • // test transparency flag
  • if (transparent)
  • // enable color key blit blt to destination
    surface
  • if (FAILED(dest-gtBlt(dest_rect, source,
  • source_rect,(DDBLT_WAIT
    DDBLT_KEYSRC),
  • NULL)))
  • return(0)
  • // end if
  • else
  • // perform blit without color key blt to
    destination surface
  • if (FAILED(dest-gtBlt(dest_rect, source,
  • source_rect,(DDBLT_WAIT),
  • NULL)))
  • return(0)
  • // end if

41
Blinking Lights
  • The palette can be used to animate blinking
    lights
  • Basically, you need to pick 2 colors like 253 and
    254
  • Then write code to toggle the colors in the bit
    map using SetEntries( )

42
Blinking Lights
  • // defines for Blink_Colors
  • define BLINKER_ADD 0 // add a light
    to database
  • define BLINKER_DELETE 1 // delete a
    light from database
  • define BLINKER_UPDATE 2 // update a
    light
  • define BLINKER_RUN 3 // run normal
  • // blinking light structure
  • typedef struct BLINKER_TYP
  • // user sets these
  • int color_index // index of color to
    blink
  • PALETTEENTRY on_color // RGB value of "on"
    color
  • PALETTEENTRY off_color // RGB value of "off"
    color
  • int on_time // number of frames to
    keep "on"
  • int off_time // number of frames to
    keep "off" 
  • // internal member
  • int counter // counter for state
    transitions
  • int state // state of light, -1
    off, 1 on, 0 dead
  • BLINKER, BLINKER_PTR

43
Blink_Colors( )
  • int Blink_Colors(int command, BLINKER_PTR
    new_light, int id)
  • // this function blinks a set of lights
  •  
  • static BLINKER lights256 // supports up to
    256 blinking lights
  • static int initialized 0 // tracks if
    function has initialized
  •  
  • // test if this is the first time function has
    ran
  • if (!initialized)
  • // set initialized
  • initialized 1
  • // clear out all structures
  • memset((void )lights,0, sizeof(lights))
  • // end if

44
Blink_Colors( )
  • // clear out all structures
  • memset((void )lights,0, sizeof(lights))
  • // end if
  • // now test what command user is sending
  • switch (command)
  • case BLINKER_ADD // add a light to the
    database
  • // update palette entry
  • lpddpal-gtSetEntries(0,lightsindex.color_i
    ndex,1,lightsindex.off_color)
  • break
  •   case BLINKER_DELETE // delete light from
    database
  •  
  • // delete the light sent in id
  • if (lightsid.state ! 0)
  • // kill the light

45
Blink_Colors( )
  • case BLINKER_UPDATE // update the light
    indicated by id
  •  
  • // update palette entry
  • if (lightsid.state -1)
  • lpddpal-gtSetEntries(0,lightsid.color_in
    dex,1,lightsid.off_color)
  • else
  • lpddpal-gtSetEntries(0,lightsid.color_in
    dex,1,lightsid.on_color)
  • break
  • case BLINKER_RUN // run the algorithm
  • // run thru database and process each
    light
  • // update color
  • lpddpal-gtSetEntries(0,lightsindex.color
    _index,1,lightsindex.on_color)
  • default break 
  • // end switch

46
Color Rotation
  • Easy way to simulate motion
  • Used to simulate flying through trenches on the
    Death Star
  • Done by retrieving a palette entry using
    GetEntries( )
  • The shifting the entry one place to the right and
    writing it back using SetEntries( )

47
Rotate_Colors( )
  • int Rotate_Colors(int start_index, int end_index)
  • // this function rotates the color between
    start and end
  • int colors end_index - start_index 1
  • PALETTEENTRY work_palMAX_COLORS_PALETTE //
    working palett
  • // get the color palette
  • lpddpal-gtGetEntries(0,start_index,colors,work_pa
    l)
  • // shift the colors
  • lpddpal-gtSetEntries(0,start_index1,colors-1,wor
    k_pal)
  • // fix up the last color
  • lpddpal-gtSetEntries(0,start_index,1,work_palco
    lors - 1)
  • // update shadow palette
  • lpddpal-gtGetEntries(0,0,MAX_COLORS_PALETTE,palet
    te)
  • // return success
  • return(1)
  • // end Rotate_Colors

48
Mixing GDI and DirectX
  • You are allowed to mix calls to these two
    libraries, but you need to do the work yourself
    since the cooperative level is set to full
    screen, exlcusive
  • The reason you might like to do this is that GDI
    is much better at drawing text than Direct Draw

49
GDI Options
  • Via high level controls (e.g. dialog boxes,
    message boxes, and avoiding graphic device
    contexts)
  • Via GDC (by requesting a GDC from inside
    DirectDraw using the function IDIRECTDRAWSURFACE)
  • Via one of the standard windowed modes, but
    writing games to work in windowed mode is tough

50
Draw_Text_GDI( )
  • int Draw_Text_GDI(char text, int x,int y,
  • COLORREF color,
    LPDIRECTDRAWSURFACE7 lpdds)
  • // this function draws the sent text on the
    sent surface
  • // using color index as the color in the
    palette
  • HDC xdc // the working dc
  • // get the dc from surface
  • if (FAILED(lpdds-gtGetDC(xdc)))
  • return(0)
  • // set the colors for the text up
  • SetTextColor(xdc,color)
  • // set background mode to transparent so black
    isn't copied
  • SetBkMode(xdc, TRANSPARENT)
  • TextOut(xdc,x,y,text,strlen(text))
  • // release the dc
  • lpdds-gtReleaseDC(xdc)
  • return(1) // return success
  • // end Draw_Text_GDI
Write a Comment
User Comments (0)
About PowerShow.com