Chris Pollett >
Old Classes >
PIC197

   ( Print View )

Enrollment info

Course Info:


Homework Assignments:
Practice Exams: PIC:
                                   












HW1 Solutions Page

Return to homework page.

Note only the files from Demo 01 that were changed are posted below.

//bmp.h: header file for the bmp file reader
//
//      Added to class draw direction flag and
//      red offset flag
//
//Modified by Chris Pollett, 2001
//
//Copyright Ian Parberry, 1999
//Last updated September 2, 1999

#include <windows.h>
#include <windowsx.h>
#include <ddraw.h>

#include "defines.h"

#ifndef __bmp_h__
#define __bmp_h__

class CBmpFileReader{ //bmp file input class
  protected:
    BITMAPFILEHEADER m_BMPFileHead; //bmp header
    BITMAPINFOHEADER m_BMPFileInfo; //bmp file information
    RGBQUAD m_rgbPalette[COLORS]; //the palette
    BYTE *m_cImage; //the image
    BYTE redOffset; //red offset for each palette entry
    BOOL direction; // TRUE -- draw right side up
                    // FAlSE -- draw upside down

  public:
    CBmpFileReader(); //constructor
    ~CBmpFileReader(); //destructor
    BOOL load(char *filename); //load from file
    BOOL draw(LPDIRECTDRAWSURFACE surface); //draw image
    BOOL setpalette(LPDIRECTDRAWPALETTE palette); //set palette
    void setdirection(BOOL d); // set the draw direction
                               // TRUE - right side up
                               // FALSE - up side down
    void incRedOffset(); // increase by one the offset
                         // to the red palette entries
};

#endif
//bmp.cpp: member functions for the bmp file reader
//
//Modified by Chris Pollett, 2001
//Copyright Ian Parberry, 1999
//Last updated May 22, 2000

#include "bmp.h" //header file

//constructors and destructors

CBmpFileReader::CBmpFileReader(){ //constructor
  m_cImage=0; //memory not yet allocated
  redOffset=0;
  direction = TRUE;
}

CBmpFileReader::~CBmpFileReader(){ //destructor
  delete[]m_cImage; //reclaim memory from image data
}

//member functions

void CBmpFileReader::incRedOffset(){ redOffset++;}
                         //increase by one offset to red palette
                         //entries

void CBmpFileReader::setdirection(BOOL d){direction=d; }
                                     //set draw direction

BOOL CBmpFileReader::load(char *filename){ //load bmp from this file
  HANDLE hfile; //input file handle
  DWORD actualRead; //number of bytes actually read
  int image_size; //size of image (width*height)
  BOOL OK=TRUE; //no error has occurred yet
  //open input file for reading
  hfile=CreateFile(filename,GENERIC_READ,FILE_SHARE_READ,
    (LPSECURITY_ATTRIBUTES)NULL,OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,(HANDLE)NULL);
  //bail if file could not be opened
  if(hfile==INVALID_HANDLE_VALUE)return FALSE;
  //read the header and info structures
  OK=ReadFile(hfile,&m_BMPFileHead,sizeof(m_BMPFileHead),
    &actualRead,NULL);
  if(OK)OK=ReadFile(hfile,&m_BMPFileInfo,
    sizeof(m_BMPFileInfo),&actualRead,NULL);
  //make sure the bmp is 8-bit color
  if(OK)OK=m_BMPFileInfo.biBitCount==COLOR_DEPTH;
  //get the bmp palette
  if(OK)OK=ReadFile(hfile,m_rgbPalette,sizeof(m_rgbPalette),
    &actualRead,NULL);
  //bail out is something went wrong
  if(!OK){CloseHandle(hfile); return FALSE;}
  //allocate memory for image data
  image_size=m_BMPFileInfo.biWidth*m_BMPFileInfo.biHeight;
  if(m_cImage)delete[]m_cImage; //dispose of any old space
  m_cImage=new BYTE[image_size]; //allocate new space
  if(!m_cImage){ //bail if alloc failed
    CloseHandle(hfile); return FALSE;
  }
  //round up line width to next multiple of 4
  int width=(m_BMPFileInfo.biWidth+3)&~3;
  //read bmp image
  int i=0; //counter
  BYTE trash[4]; //to hold the trash at the end of each line
  int remainder=width-m_BMPFileInfo.biWidth; //width of trash
  while(OK&&i<m_BMPFileInfo.biHeight){
    //read data
    OK=OK&&ReadFile(hfile,
      (BYTE*)(m_cImage+i*m_BMPFileInfo.biWidth),
      m_BMPFileInfo.biWidth,&actualRead,NULL);
    //read trash at end of line
    OK=OK&&ReadFile(hfile,trash,remainder,&actualRead,NULL);
    i++; //next line
  }
  if(!OK)delete[]m_cImage; //clean up if failed
  //close up and exit
  CloseHandle(hfile);
  return OK;
} //load

BOOL CBmpFileReader::draw(LPDIRECTDRAWSURFACE surface){
  DDSURFACEDESC ddsd; //direct draw surface descriptor
  BYTE *dest,*src; //destination and source pointers
  int src_width; //width of source
  //init surface descriptor
  memset(&ddsd,0,sizeof(DDSURFACEDESC));
  ddsd.dwSize=sizeof(ddsd);
  //lock down surface
  if(FAILED(surface->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL)))
    return FALSE;
  //calculate addresses and width
  dest=(BYTE*)ddsd.lpSurface; //destination

  if(direction) src=m_cImage+
      ((m_BMPFileInfo.biHeight-1)*m_BMPFileInfo.biWidth);
  else src = m_cImage;

  //trim bmp if too wide
  if(m_BMPFileInfo.biWidth>ddsd.lPitch)src_width=ddsd.lPitch;
  else src_width=m_BMPFileInfo.biWidth;
  //move data to surface
  if(direction)
  {
  	for(int i=0; i<m_BMPFileInfo.biHeight; i++){
      memcpy(dest,src,src_width);
      dest+=ddsd.lPitch; src-=src_width;
    }
  }
  else
  {
    for(int i=0; i<m_BMPFileInfo.biHeight; i++){
      memcpy(dest,src,src_width);
      dest+=ddsd.lPitch; src+=src_width;
    }
  }
  //clean up and return
  surface->Unlock(NULL);
  return TRUE;
} //draw

BOOL CBmpFileReader::setpalette(LPDIRECTDRAWPALETTE palette){
  PALETTEENTRY pe[COLORS]; //intermediate palette
  //construct pe[]
  for(int i=0; i<COLORS; i++){ //for each palette entry
    pe[i].peRed=m_rgbPalette[i].rgbRed + redOffset; //set red
    pe[i].peGreen=m_rgbPalette[i].rgbGreen; //set green
    pe[i].peBlue=m_rgbPalette[i].rgbBlue; //set blue
  }
  //load direct draw palette to surface
  palette->SetEntries(NULL,0,COLORS,pe);
  return TRUE;
}
// FileName: Main.cpp
//
// Purpose: Simple prectice with DirectDraw. Left and right
//          arrows change a BitMap to be displayed.
//          Space changes the red offset on each palette entry
//          Up and down flip an image.
//
//
// Modified from Author below by Chris Pollett

//Copyright Ian Parberry, 1999
//Last updated May 22, 2000



//system includes
#include <windows.h>
#include <windowsx.h>
#include <ddraw.h>
#include <stdio.h>

//system defines
#define WIN32_LEAN_AND_MEAN

//custom includes
#include "defines.h"
#include "bmp.h"

//globals
LPDIRECTDRAW lpDirectDrawObject=NULL; //direct draw object
LPDIRECTDRAWSURFACE lpPrimary=NULL; //primary surface
LPDIRECTDRAWPALETTE lpPrimaryPalette; //its palette
LPDIRECTDRAWSURFACE lpSecondary=NULL; //back buffer
LPDIRECTDRAWPALETTE lpSecondaryPalette; //its palette
BOOL ActiveApp; //is this application active?
CBmpFileReader frame[3];
BYTE curFrame = 0;

//helper functions

LPDIRECTDRAWPALETTE CreatePalette(LPDIRECTDRAWSURFACE surface);
BOOL InitDirectDraw(HWND hwnd);
HWND CreateDefaultWindow(char* name,HINSTANCE hInstance);

BOOL LoadImages(){


  //draw the first image to the primary surface
  if(!frame[0].load("up.bmp"))return FALSE; //read from file
  if(!frame[0].setpalette(lpPrimaryPalette)) //set palette
    return FALSE;
  if(!frame[0].draw(lpPrimary))return FALSE; //draw

  if(!frame[0].setpalette(lpSecondaryPalette)) //set palette
    return FALSE;
  if(!frame[0].draw(lpSecondary))return FALSE; //draw

  //get other images
  if(!frame[1].load("down.bmp"))return FALSE; //read our other two images
  if(!frame[2].load("up2.bmp"))return FALSE;

  //success exit
  return TRUE;
} //LoadImages

BOOL RestoreSurfaces(){ //restore all surfaces
  BOOL result=TRUE;
  if(SUCCEEDED(lpPrimary->Restore()))
    result=result&&frame[curFrame].draw(lpPrimary)&& //redraw image
      frame[curFrame].setpalette(lpPrimaryPalette); //set palette
  else return FALSE;
  if(SUCCEEDED(lpSecondary->Restore()))
    result=result&&frame[curFrame].draw(lpSecondary)&& //redraw image
      frame[curFrame].setpalette(lpSecondaryPalette); //set palette
  else return FALSE;
  return result;
} //RestoreSurfaces

BOOL PageFlip(){ //return TRUE if page flip succeeds
  if(lpPrimary->Flip(NULL,DDFLIP_WAIT)==DDERR_SURFACELOST)
    return RestoreSurfaces();
  return TRUE;
} //PageFlip

BOOL keyboard_handler(WPARAM keystroke){ //keyboard handler
  BOOL result=FALSE; //return TRUE if game is to end
  switch(keystroke){
    case VK_ESCAPE: result=TRUE;
    break; //exit game

    case VK_LEFT: //change image to previous
        if(curFrame) curFrame--;
        else curFrame=2;
    	frame[curFrame].draw(lpSecondary);
    	result=!PageFlip();
    	frame[curFrame].setpalette(lpPrimaryPalette);
    break;

    case VK_RIGHT: //change image to next
        if(curFrame<3) curFrame++;
        else curFrame=0;
    	frame[curFrame].draw(lpSecondary);
    	result=!PageFlip();
    	frame[curFrame].setpalette(lpPrimaryPalette);
    break;


    case VK_UP: //flip image upright
    	frame[curFrame].setdirection(TRUE);
    	frame[curFrame].draw(lpSecondary);
    	result=!PageFlip();
    break;

    case VK_DOWN: // flip image upside down
    	frame[curFrame].setdirection(FALSE);
    	frame[curFrame].draw(lpSecondary);
    	result=!PageFlip();
    break;

    case VK_SPACE: // change red offset
    	frame[curFrame].incRedOffset();
    	frame[curFrame].setpalette(lpPrimaryPalette);

    break;

  }
  return result;
} //keyboard_handler

//message handler (window procedure)
long CALLBACK WindowProc(HWND hwnd,UINT message,
                         WPARAM wParam,LPARAM lParam){
  switch(message){
    case WM_ACTIVATEAPP: ActiveApp=wParam; break;
    case WM_CREATE: break;
    case WM_KEYDOWN: //keyboard hit
      if(keyboard_handler(wParam))DestroyWindow(hwnd);
      break;
    case WM_DESTROY: //end of game
      if(lpDirectDrawObject!=NULL){ //if DD object exists
        if(lpSecondary!=NULL) //if secondary surface exists
          lpSecondary->Release(); //release secondary surface
        if(lpPrimary!=NULL) //if primary surface exists
          lpPrimary->Release(); //release primary surface
        lpDirectDrawObject->Release(); //release DD object
      }
      ShowCursor(TRUE); //show the mouse cursor
      PostQuitMessage(0); //and exit
      break;
    default: //default window procedure
      return DefWindowProc(hwnd,message,wParam,lParam);
  } //switch(message)
  return 0L;
} //WindowProc

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,int nCmdShow){
  MSG msg; //current message
  HWND hwnd; //handle to fullscreen window
  hwnd=CreateDefaultWindow("directX demo 1",hInstance);
  if(!hwnd)return FALSE;
  //set up window
  ShowWindow(hwnd,nCmdShow); UpdateWindow(hwnd);
  SetFocus(hwnd); //allow input from keyboard
  ShowCursor(FALSE); //hide the cursor
  //init graphics
  BOOL OK=InitDirectDraw(hwnd);//initialize DirectDraw
  if(OK)OK=LoadImages(); //load images from disk
  if(!OK){ //bail out if initialization failed
    DestroyWindow(hwnd); return FALSE;
  }
  //message loop
  while(TRUE)
    if(PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)){
      if(!GetMessage(&msg,NULL,0,0))return msg.wParam;
      TranslateMessage(&msg); DispatchMessage(&msg);
    }
    else if(!ActiveApp)WaitMessage();
} //WinMain