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
|