#include "stdafx.h" /*BMPLoader - loads Microsoft .bmp format Copyright (C) 2006 Chris Backhouse This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. cjbackhouse@hotmail.com www.backhouse.tk I would appreciate it if anyone using this in something cool would tell me so I can see where it ends up. Takes a filename, returns an array of RGB pixel data Loads: 24bit bitmaps 256 colour bitmaps 16 colour bitmaps 2 colour bitmaps (Thanks to Charles Rabier) This code is designed for use in openGL programs, so bitmaps not correctly padded will not load properly, I believe this only applies to: 256cols if width is not a multiple of 4 16cols if width is not a multiple of 8 2cols if width is not a multiple of 32 Sample code: BMPClass bmp; BMPLoad(fname,bmp); glTexImage2D(GL_TEXTURE_2D,0,3,bmp.width,bmp.height,0,GL_RGB,GL_UNSIGNED_BYTE,bmp.bytes); */ #include "BMPLoader.h" BMPClass::BMPClass(){bytes=0;} BMPClass::~BMPClass(){delete[] bytes;} BYTE& BMPClass::pixel(int x,int y,int c){return bytes[(y*width+x)*3+c];} void BMPClass::allocateMem(){delete[] bytes;bytes=new BYTE[width*height*3];} std::string TranslateBMPError(BMPError err) { switch(err) { case(BMPNOTABITMAP): return "This file is not a bitmap, specifically it doesn't start 'BM'"; case(BMPNOOPEN): return "Failed to open the file, suspect it doesn't exist"; case(BMPFILEERROR): return "ferror said we had an error. This error seems to not always mean anything, try ignoring it"; case(BMPBADINT): return "sizeof(int)!=4 quite a lot of rewriting probably needs to be done on the code"; case(BMPNOERROR): return "No errors detected"; case(BMPUNKNOWNFORMAT): return "Unknown bmp format, ie not 24bit, 256,16 or 2 colour"; default: return "Not a valid error code"; } } BMPError BMPLoad(std::string fname,BMPClass& bmp) { if(sizeof(int)!=4) return BMPBADINT; FILE* f=fopen(fname.c_str(),"rb"); //open for reading in binary mode if(!f) return BMPNOOPEN; char header[54]; fread(header,54,1,f); //read the 54bit main header if(header[0]!='B' || header[1]!='M') { fclose(f); return BMPNOTABITMAP; //all bitmaps should start "BM" } //it seems gimp sometimes makes its headers small, so we have to do this. hence all the fseeks int offset=*(unsigned int*)(header+10); bmp.width=*(int*)(header+18); bmp.height=*(int*)(header+22); //now the bitmap knows how big it is it can allocate its memory bmp.allocateMem(); int bits=int(header[28]); //colourdepth int x,y,c; BYTE cols[256*4]; //colourtable switch(bits) { case(24): fseek(f,offset,SEEK_SET); fread(bmp.bytes,bmp.width*bmp.height*3,1,f); //24bit is easy for(x=0;x>(7-x2))&1)*4+2-c]; } break; default: fclose(f); return BMPUNKNOWNFORMAT; } if(ferror(f)) { fclose(f); return BMPFILEERROR; } fclose(f); return BMPNOERROR; } BMPError BMPLoad(std::string fname){BMPClass bmp;return BMPLoad(fname,bmp);} #ifdef __gl_h BMPError BMPLoadGL(std::string fname) { BMPClass bmp; BMPError e=BMPLoad(fname,bmp); if(e!=BMPNOERROR) return e; glEnable(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexImage2D(GL_TEXTURE_2D,0,3,bmp.width,bmp.height,0,GL_RGB,GL_UNSIGNED_BYTE,bmp.bytes); return BMPNOERROR; } #endif