Bitmaps

·       draw your bitmaps in cells (frames) to keep them the same size

·       must all use same color values, bit-depth, palettes, etc.

·       make size a power of 2 for efficiency 32x16, 64x64

o      see my templates

 

 

 

loading bitmaps

 

// bitmap loading software – “bitmapReader.H”

 

#define WIN32_LEAN_AND_MEAN 

#include <windows.h> 

#include <windowsx.h> 

#include <iostream.h>

#include <stdlib.h>

#include <stdarg.h>

#include <stdio.h>

#include <math.h>

#include <io.h>

#include <fcntl.h>

#include <signal.h>

#include <float.h>

#define BITMAP_ID        0x4D42       // this is the universal id for a bitmap

#define _RGB16BIT(r,g,b) ((b%32)+((g%32)<<5)+((r%32)<<10))

 

// 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     palette[256];      // we will store the palette here

        UCHAR            *buffer;           // this is a pointer to the data

 

        } BITMAP_FILE, *BITMAP_FILE_PTR;

 

int LoadBitmapFile(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->bitmapfileheader,sizeof(BITMAPFILEHEADER));

  // test if this is a bitmap file

  if (bitmap->bitmapfileheader.bfType!=BITMAP_ID)

  { // close the file

    _lclose(file_handle);

 

    // return error

    return(0);

  } // end if

 

  // now we know this is a bitmap, so read in all the sections

  // first the bitmap infoheader now load the bitmap file header

  _lread(file_handle, &bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER));

 

  // now load the color palette if there is one

  if (bitmap->bitmapinfoheader.biBitCount == 8)

  { _lread(file_handle, &bitmap->palette,256*sizeof(PALETTEENTRY));

 

    // now set all the flags in the palette correctly and fix the reversed

    // BGR RGBQUAD data format

    for (index=0; index<256; index++)

    { // reverse the red and green fields

      int temp_color = bitmap->palette[index].peRed;

      bitmap->palette[index].peRed  = bitmap->palette[index].peBlue;

      bitmap->palette[index].peBlue = temp_color;

      

      // always set the flags word to this

      bitmap->palette[index].peFlags = PC_NOCOLLAPSE;

    } // end for index

  } // end if

 

  // finally the image data itself

  _lseek(file_handle,-(int)(bitmap->bitmapinfoheader.biSizeImage),SEEK_END);

 

  // now read in the image, if the image is 8 or 16 bit then simply read it

  // but if its 24 bit then read it into a temporary area and then convert

  // it to a 16 bit image

 

  if (bitmap->bitmapinfoheader.biBitCount==8 || bitmap->bitmapinfoheader.biBitCount==16)

  { // allocate the memory for the image

    if (!(bitmap->buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))

    { // close the file

      _lclose(file_handle);

 

      // return error

      return(0);

    } // end if

 

    // now read it in

    _lread(file_handle,bitmap->buffer,bitmap->bitmapinfoheader.biSizeImage);

  } // end if

  else

  { // this must be a 24 bit image, load it in and convert it to 16 bit

    printf("\nconverting 24 bit image...");

 

    // allocate temporary buffer

    if (!(temp_buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.biSizeImage)))

    {  // close the file

      _lclose(file_handle);

 

      // return error

      return(0);

    } // end if

  

    // allocate final 16 bit storage buffer

    if (!(bitmap->buffer = (UCHAR *)malloc(2 * bitmap->bitmapinfoheader.biWidth * bitmap->bitmapinfoheader.biHeight)))

    { // close the file

      _lclose(file_handle);

 

      // release working buffer

      free(temp_buffer);

 

      // return error

      return(0);

    } // end if

 

    // now read it in

    _lread(file_handle,temp_buffer,bitmap->bitmapinfoheader.biSizeImage);

 

    // now convert each 24 bit RGB value into a 16 bit value

    for (index=0; index<bitmap->bitmapinfoheader.biWidth*bitmap->bitmapinfoheader.biHeight; index++)

    { // extract RGB components

      UCHAR red    = temp_buffer[index*3 + 0],

            green  = temp_buffer[index*3 + 1],

            blue   = temp_buffer[index*3 + 2];

 

      // build up 16 bit color word

      USHORT color = _RGB16BIT(red,green,blue);

      // write color to buffer

      ((USHORT *)bitmap->buffer)[index] = color;

    } // end for index

  } // end if

 

  // write the file info out 

  printf("\nfilename:%s \nsize=%d \nwidth=%d \nheight=%d \nbitsperpixel=%d \ncolors=%d \nimpcolors=%d",

         filename, bitmap->bitmapinfoheader.biSizeImage, bitmap->bitmapinfoheader.biWidth,

         bitmap->bitmapinfoheader.biHeight, bitmap->bitmapinfoheader.biBitCount,

         bitmap->bitmapinfoheader.biClrUsed, bitmap->bitmapinfoheader.biClrImportant);

 

  // close the file

  _lclose(file_handle);

 

  // return success

  return(1);

} // end Load_Bitmap_File

 

int UnloadBitmapFile(BITMAP_FILE_PTR bitmap)

{ // this function releases all memory associated with "bitmap"

  if (bitmap->buffer)

  { // release memory

    free(bitmap->buffer);

 

    // reset pointer

    bitmap->buffer = NULL;

  } // end if

 

  // return success

  return(1);

} // end Unload_Bitmap_File

 

 

int FlipBitmap(UCHAR *image, int bytes_per_line, int height)

{

  // this function is used to flip upside down .BMP images

 

  UCHAR *buffer; // used to perform the image processing

  int index;     // looping index

 

  // allocate the temporary buffer

  if (!(buffer = (UCHAR *)malloc(bytes_per_line*height)))

     return(0);

 

  // copy image to work area

  memcpy(buffer,image,bytes_per_line*height);

 

  // flip vertically

  for (index=0; index < height; index++)

      memcpy(&image[((height-1) - index)*bytes_per_line],

           &buffer[index*bytes_per_line], bytes_per_line);

 

  // release the memory

  free(buffer);

  // return success

  return(1);

} // end Flip_Bitmap

 

To Use:

#include “bitmapReader.H”

 

void main(void)

{ char filename[80];

  BITMAP_FILE bitmap;

  bool more = true;

 

  // load in .bmp files

  while(more)

  {  printf("\nenter filename to load or 'end' to stop?");

     scanf("%s", filename);

       if (strcmp(filename, "end") != 0)

     { Load_BitmapFile(&bitmap,filename);

       UnloadBitmapFile(&bitmap);

     }

       else

       more = false;

  } // end while

} // end main

 

Example – bmp16Loader.cpp

 

// a 640x480x16 bitmap loader

#define WIN32_LEAN_AND_MEAN 

#include <windows.h>   // include important windows stuff

#include <windowsx.h>

#include <mmsystem.h>

#include <iostream.h> // include important C/C++ stuff

#include <conio.h>

#include <stdlib.h>

#include <malloc.h>

#include <memory.h>

#include <string.h>

#include <stdarg.h>

#include <stdio.h>

#include <math.h>

#include <io.h>

#include <fcntl.h>

 

#include <ddraw.h>  // directX includes

#include "bitmapReader.h"

 

// defines for windows

#define WINDOW_CLASS_NAME "WINXCLASS"  // class name

#define WINDOW_WIDTH  640         // size of window

#define WINDOW_HEIGHT 480

#define SCREEN_WIDTH  640         // size of screen

#define SCREEN_HEIGHT 480

#define SCREEN_BPP    16          // bits per pixel

 

// these read the keyboard asynchronously

#define KEY_DOWN(vk_code)((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)

#define KEY_UP(vk_code)  ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

 

typedef unsigned short USHORT;

typedef unsigned short WORD;

typedef unsigned char  UCHAR;

typedef unsigned char  BYTE;

 

int GameInit(void *parms=NULL);

int GameShutdown(void *parms=NULL);

int GameMain(void *parms=NULL);

 

// GLOBALS

 

HWND mainWindowHandle = NULL; // save the window handle

HINSTANCE mainInstance = NULL; // save the instance

char buffer[80];                // used to print text

 

LPDIRECTDRAW         lpdd         = NULL;  // dd object

LPDIRECTDRAWSURFACE  lpddsprimary = NULL;  // dd primary surface

LPDIRECTDRAWSURFACE  lpddsback    = NULL;  // dd back surface

LPDIRECTDRAWPALETTE  lpddpal      = NULL;  // ptr to created dd palette

DDSURFACEDESC        ddsd;                 // ddraw surface description

DDSCAPS              ddscaps;              // ddraw surf capabilities

HRESULT              ddrval;               // result back from dd calls

UCHAR                *primary_buffer = NULL; // primary video buffer

BITMAP_FILE          bitmap16bit;            // a 16 bit bitmap file

 

// FUNCTIONS

LRESULT CALLBACK WindowProc(HWND hwnd,

                            UINT msg,

                            WPARAM wparam,

                            LPARAM lparam)

{ // this is the main message handler of the system

  PAINTSTRUCT     ps;            // used in WM_PAINT

  HDC             hdc;     // handle to a device context

 

  // what is the message

  switch(msg)

  {  

    case WM_CREATE:

    {

        // do initialization stuff here

        return(0);

    } break;

 

    case WM_PAINT:

    {

         // start painting

         hdc = BeginPaint(hwnd,&ps);

 

         // end painting

         EndPaint(hwnd,&ps);

         return(0);

    } break;

 

    case WM_DESTROY:

    {

       // kill the application                 

       PostQuitMessage(0);

       return(0);

    } break;

 

    default:break;

  } // end switch

 

  // process any messages that we didn't take care of

  return (DefWindowProc(hwnd, msg, wparam, lparam));

} // end WinProc

 

// *************** WINMAIN *****************

int WINAPI WinMain(     HINSTANCE hinstance,

                        HINSTANCE hprevinstance,

                        LPSTR lpcmdline,

                        int ncmdshow)

{

 

  WNDCLASS winclass;    // this will hold the class we create

  HWND      hwnd;            // generic window handle

  MSG       msg;       // generic message

  HDC      hdc;       // generic dc

  PAINTSTRUCT ps;     // generic paintstruct

 

  // first fill in the window class stucture

  winclass.style = CS_DBLCLKS | CS_OWNDC |

                   CS_HREDRAW | CS_VREDRAW;

  winclass.lpfnWndProc  = WindowProc;

  winclass.cbClsExtra         = 0;

  winclass.cbWndExtra         = 0;

  winclass.hInstance          = hinstance;

  winclass.hIcon              = LoadIcon(NULL, IDI_APPLICATION);

  winclass.hCursor            = LoadCursor(NULL, IDC_ARROW);

  winclass.hbrBackground      = (HBRUSH)GetStockObject(BLACK_BRUSH);

  winclass.lpszMenuName = NULL;

  winclass.lpszClassName      = WINDOW_CLASS_NAME;

 

  // register the window class

  if (!RegisterClass(&winclass))

      return(0);

 

  // create the window, note the use of WS_POPUP

  if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, // class

                          "WinX Game Console",  // title

                          WS_POPUP | WS_VISIBLE,

                          0,0,         // x,y

                          WINDOW_WIDTH,  // width

                          WINDOW_HEIGHT, // height

                          NULL,        // handle to parent

                          NULL,        // handle to menu

                          hinstance,// instance

                          NULL)))   // creation parms

       return(0);

 

  // hide the mouse

  ShowCursor(FALSE);

 

  // save the window handle and instance in a global

  mainWindowHandle = hwnd;

  mainInstance      = hinstance;

 

  // perform all game console specific initialization

  GameInit();

 

  // enter main event loop

  while(1)

  {

      if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))

      {

            // test if this is a quit

           if (msg.message == WM_QUIT)

              break;

     

            // translate any accelerator keys

            TranslateMessage(&msg);

 

            // send the message to the window proc

            DispatchMessage(&msg);

      } // end if

   

    // main game processing goes here

    GameMain();

 

  } // end while

 

  // shutdown game and release all resources

  GameShutdown();

 

  // return to Windows like this

  return(msg.wParam);

} // end WinMain

 

// WINX GAME PROGRAMMING CONSOLE FUNCTIONS

 

int GameInit(void *parms)

{

  // this function is where you do all the initialization

  // for your game

 

  // create object and test for error

  if (DirectDrawCreate(NULL,&lpdd,NULL)!=DD_OK)

     return(0);

 

  // set cooperation level to windowed mode normal

  if (lpdd->SetCooperativeLevel(mainWindowHandle,

           DDSCL_ALLOWMODEX | DDSCL_FULLSCREEN |

           DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)!=DD_OK)

     return(0);

 

  // set the display mode

  if (lpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP)!=DD_OK)

     return(0);

 

  // Create the primary surface

  memset(&ddsd,0,sizeof(ddsd));

  ddsd.dwSize         = sizeof(ddsd);

  ddsd.dwFlags        = DDSD_CAPS;

  ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

 

  if (lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL)!=DD_OK)

     return(0);

 

  // now load the 16 bit color bitmap

  LoadBitmapFile(&bitmap16bit, "bmp.BMP");

 

  // return success

  return(1);

} // end GameInit

 

int GameShutdown(void *parms)

{

  // this function is where you shutdown your game and

  // release all resources that you allocated

 

  // first release the primary surface

  if (lpddsprimary!=NULL)

     lpddsprimary->Release();

      

  // release the directdraw object

  if (lpdd!=NULL)

     lpdd->Release();

 

  // delete the bitmap

  UnloadBitmapFile(&bitmap16bit);

 

  // return success

  return(1);

} // end GameShutdown

 

 

 

int GameMain(void *parms)

{

  // this is the workhorse of your game it will be called

  // continuously in real-time this is like main() in C

  // all the calls for you game go here!

 

  // check of user is trying to exit

  if (KEY_DOWN(VK_ESCAPE) || KEY_DOWN(VK_SPACE))

      PostMessage(mainWindowHandle, WM_DESTROY,0,0);

 

  // set up the surface description to lock the surface

  memset(&ddsd,0,sizeof(ddsd));

  ddsd.dwSize = sizeof(ddsd);

 

  // lock the primary surface, note in a real game you would

  lpddsprimary->Lock(NULL,&ddsd,

                   DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL);

 

  // get video pointer

  primary_buffer = (UCHAR *)ddsd.lpSurface;

 

  // copy each bitmap line into primary buffer

  // taking into consideration non-linear video

  // cards and the memory pitch lPitch

  for (int y=0; y < SCREEN_HEIGHT; y++)

  {

    // copy the line

    memcpy(&primary_buffer[y*ddsd.lPitch], // dest address

           &bitmap16bit.buffer[y*SCREEN_WIDTH*2],   // src address

           SCREEN_WIDTH*2);                         // bytes to copy

  } // end for y

 

  // unlock the surface

  lpddsprimary->Unlock(primary_buffer);

  // return success

  return(1);

} // end GameMain