//////////////////////////////////////////////////////////////////////////////// // // Module: bmp.cpp // Author: Tom Hicks // Creation: 09-01-2003 // LastEdit: 06-20-2005 // Editors: Tom Hicks // // Purpose: // To implement a wrapper function that will load a 24bit windows bitmap // file and return a pointer to a TextureImage object containing the image. // // Summary of Methods: // Global // -LoadBMP // Loads a 24 bit windows bitmap file specified by fn and returns a // pointer to a TextureImage object containing the bitmap image. // //////////////////////////////////////////////////////////////////////////////// #include #include "bmp.h" #ifdef WIN32 #pragma warning(disable:4996) #endif namespace OpenArena{ #pragma pack(push,1) struct BITMAP_HEADER { uint16 type; uint32 size; uint16 reserved1; uint16 reserved2; uint32 offset; }; struct BITMAP_INFO { uint32 size; uint32 width; uint32 height; uint16 planes; uint16 bitCount; uint32 compression; uint32 sizeImage; uint32 xPelsPerMeter; uint32 yPelsPerMeter; uint32 clrUsed; uint32 clrImportant; }; struct BITMAP_QUAD { uint8 blue; uint8 green; uint8 red; uint8 reserved; }; #pragma pack(pop) #define BITMAP_MAGIC 19778 void PrintBMPHeader(BITMAP_HEADER header) { printf("Header\n"); printf("Type: %X\nSize: %X\nReserved1: %X\nReserved2: %X\nOffset:%X\n", header.type, header.size, header.reserved1, header.reserved2, header.offset); } void PrintBMPInfo(BITMAP_INFO info) { printf("Info\n"); printf("Size: %X\nWidth: %X\nHeight:%X\n", info.size, info.width, info.height); printf("Planes: %X\nBitCount: %X\nCompression: %X\n", info.planes, info.bitCount, info.compression); printf("SizeImage: %X\nXPelsPerMeter: %X\nYPelsPerMeter: %X\n", info.sizeImage, info.xPelsPerMeter, info.yPelsPerMeter); printf("ClrUsed: %X\nClrImportant: %X\n", info.clrUsed, info.clrImportant); } TextureImage* LoadBMP(const char* fn) { //If anything is not perfect return NULL after cleaning up our mess FILE* f=NULL; //A pointer to our file structure //If our filename is null if(!fn) { return NULL; } //Try to open our file and if successfull... f=fopen(fn, "rb"); if(f) { BITMAP_HEADER bmpHeader; BITMAP_INFO bmpInfo; BITMAP_QUAD* bmpPallette = NULL; uint32 palletteEntries = 0; fread(&bmpHeader, sizeof(bmpHeader), 1, f); #if __BYTE_ORDER == __BIG_ENDIAN //If big endian reorder bytes bmpHeader.type = ((bmpHeader.type & 0xff00) >> 8) | ((bmpHeader.type & 0x00ff) << 8); bmpHeader.size = (bmpHeader.size & 0xff000000) >> 24 | (bmpHeader.size & 0x00ff0000) >> 8 | (bmpHeader.size & 0x0000ff00) << 8 | (bmpHeader.size & 0x000000ff) << 24; bmpHeader.reserved1 = ((bmpHeader.reserved1 & 0xff00) >> 8) | ((bmpHeader.reserved1 & 0x00ff) << 8); bmpHeader.reserved2 = ((bmpHeader.reserved2 & 0xff00) >> 8) | ((bmpHeader.reserved2 & 0x00ff) << 8); bmpHeader.offset = (bmpHeader.offset & 0xff000000) >> 24 | (bmpHeader.offset & 0x00ff0000) >> 8 | (bmpHeader.offset & 0x0000ff00) << 8 | (bmpHeader.offset & 0x000000ff) << 24; #endif PrintBMPHeader(bmpHeader); fread(&bmpInfo, sizeof(bmpInfo), 1, f); #if __BYTE_ORDER == __BIG_ENDIAN //If big endian reorder bytes bmpInfo.size = (bmpInfo.size & 0xff000000) >> 24 | (bmpInfo.size & 0x00ff0000) >> 8 | (bmpInfo.size & 0x0000ff00) << 8 | (bmpInfo.size & 0x000000ff) << 24; bmpInfo.width = (bmpInfo.width & 0xff000000) >> 24 | (bmpInfo.width & 0x00ff0000) >> 8 | (bmpInfo.width & 0x0000ff00) << 8 | (bmpInfo.width & 0x000000ff) << 24; bmpInfo.height = (bmpInfo.height & 0xff000000) >> 24 | (bmpInfo.height & 0x00ff0000) >> 8 | (bmpInfo.height & 0x0000ff00) << 8 | (bmpInfo.height & 0x000000ff) << 24; bmpInfo.planes = ((bmpInfo.planes & 0xff00) >> 8) | ((bmpInfo.planes & 0x00ff) << 8); bmpInfo.bitCount = ((bmpInfo.bitCount & 0xff00) >> 8) | ((bmpInfo.bitCount & 0x00ff) << 8); bmpInfo.compression = (bmpInfo.compression & 0xff000000) >> 24 | (bmpInfo.compression & 0x00ff0000) >> 8 | (bmpInfo.compression & 0x0000ff00) << 8 | (bmpInfo.compression & 0x000000ff) << 24; bmpInfo.sizeImage = (bmpInfo.sizeImage & 0xff000000) >> 24 | (bmpInfo.sizeImage & 0x00ff0000) >> 8 | (bmpInfo.sizeImage & 0x0000ff00) << 8 | (bmpInfo.sizeImage & 0x000000ff) << 24; bmpInfo.xPelsPerMeter = (bmpInfo.xPelsPerMeter & 0xff000000) >> 24 | (bmpInfo.xPelsPerMeter & 0x00ff0000) >> 8 | (bmpInfo.xPelsPerMeter & 0x0000ff00) << 8 | (bmpInfo.xPelsPerMeter & 0x000000ff) << 24; bmpInfo.yPelsPerMeter = (bmpInfo.yPelsPerMeter & 0xff000000) >> 24 | (bmpInfo.yPelsPerMeter & 0x00ff0000) >> 8 | (bmpInfo.yPelsPerMeter & 0x0000ff00) << 8 | (bmpInfo.yPelsPerMeter & 0x000000ff) << 24; bmpInfo.clrUsed = (bmpInfo.clrUsed & 0xff000000) >> 24 | (bmpInfo.clrUsed & 0x00ff0000) >> 8 | (bmpInfo.clrUsed & 0x0000ff00) << 8 | (bmpInfo.clrUsed & 0x000000ff) << 24; bmpInfo.clrImportant = (bmpInfo.clrImportant & 0xff000000) >> 24 | (bmpInfo.clrImportant & 0x00ff0000) >> 8 | (bmpInfo.clrImportant & 0x0000ff00) << 8 | (bmpInfo.clrImportant & 0x000000ff) << 24; #endif PrintBMPInfo(bmpInfo); if(bmpInfo.width < 0) { //This needs to be abstracted somehow #ifdef WIN32 MessageBox(NULL, "Image width is negative", "ERROR", MB_OK); #endif fclose(f); return NULL; } if(bmpInfo.width % 4 != 0) { //This needs to be abstracted somehow #ifdef WIN32 MessageBox(NULL, "Image width must be a multiple of 8", "ERROR", MB_OK); #endif fclose(f); return NULL; } if(bmpInfo.height < 0) { //This needs to be abstracted somehow #ifdef WIN32 MessageBox(NULL, "Image height is negative", "ERROR", MB_OK); #endif fclose(f); return NULL; } if(bmpInfo.height % 4 != 0) { //This needs to be abstracted somehow #ifdef WIN32 MessageBox(NULL, "Image height must be a multiple of 8", "ERROR", MB_OK); #endif fclose(f); return NULL; } if((bmpInfo.bitCount != 8 && bmpInfo.bitCount != 24) || bmpInfo.compression != 0) { //This needs to be abstracted somehow #ifdef WIN32 MessageBox(NULL, "Only 8 and 24 bit uncompressed windows bmp files are currently supported", "ERROR", MB_OK); #endif fclose(f); return NULL; } //Allocate memory for a TextureImage structure TextureImage* tex = new TextureImage; tex->sizeX = bmpInfo.width; tex->sizeY = bmpInfo.height; if(bmpInfo.bitCount >= 8) { tex->bpp = bmpInfo.bitCount >> 3; } tex->type = GL_RGB; uint32 pixels = tex->sizeX * tex->sizeY; uint32 bytes = pixels * tex->bpp; tex->data = new uint8[bytes]; if(bmpInfo.bitCount == 8) { //Load the pallette palletteEntries = bmpInfo.bitCount << 8; bmpPallette = new BITMAP_QUAD[palletteEntries]; fread(bmpPallette, sizeof(BITMAP_QUAD), palletteEntries, f); } fseek(f, bmpHeader.offset, SEEK_SET); fread(tex->data, bytes, 1, f); if(bmpInfo.bitCount == 8) { //Apply the pallette uint8* image = tex->data; tex->bpp = 24; bytes = pixels * tex->bpp; tex->data = new uint8[bytes]; uint32 i; uint32 i2; for(i=0; idata[i2] = bmpPallette[image[i]].red; tex->data[i2 + 1] = bmpPallette[image[i]].blue; tex->data[i2 + 2] = bmpPallette[image[i]].green; } delete [] image; image = NULL; } else if(bmpInfo.bitCount == 24) { uint32 i; uint8 t; for(i=0; idata[i]; tex->data[i] = tex->data[i+2]; tex->data[i+2] = t; } } return tex; } return NULL; } };