BMPError BMPLoad(std::string fname,BMPClass& bmp) { 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" } if(sizeof(int)==4) //Annoyingly I can't just assume this { bmp.width=*(int*)(header+18); bmp.height=*(int*)(header+22); } else { bmp.width=header[18]+256*header[19]+256*256*header[20]+256*256*256*header[21]; bmp.height=header[22]+256*header[23]+256*256*header[24]+256*256*256*header[25]; } bmp.allocateMem(); int bits=int(header[28]); //colourdepth int x,y,c; BYTE cols[256*4]; switch(bits) { case(24): fread(bmp.bytes,bmp.width*bmp.height*3,1,f); //24bit is easy for(x=0;x<bmp.width*bmp.height*3;x+=3) //except the format is BGR, grr { BYTE temp=bmp.bytes[x]; bmp.bytes[x]=bmp.bytes[x+2]; bmp.bytes[x+2]=temp; } break; case(8): fread(cols,256*4,1,f); //read colortable for(y=0;y<bmp.height;++y) //(Notice 4bytes/col for some reason) for(x=0;x<bmp.width;++x) { BYTE byte; fread(&byte,1,1,f); //just read byte for(int c=0;c<3;++c) bmp.pixel(x,y,c)=cols[byte*4+2-c]; //and look up in the table } break; case(4): fread(cols,16*4,1,f); for(y=0;y<256;++y) for(x=0;x<256;x+=2) { BYTE byte; fread(&byte,1,1,f); //as above, but need to exract two for(c=0;c<3;++c) //pixels from each byte bmp.pixel(x,y,c)=cols[byte/16*4+2-c]; for(c=0;c<3;++c) bmp.pixel(x+1,y,c)=cols[byte%16*4+2-c]; } break; //NOT CURRENTLY WORKING PROPERLY //case(1): // fread(cols,8,1,f); //colourtable // for(y=0;y<256;++y) // for(x=0;x<256;x+=8) // { // BYTE byte; // fread(&byte,1,1,f); // //The idea here is that every byte is eight pixels // //so I'm shifting the byte to the relevant position, then masking out // //all but the lowest bit in order to get the index into the colourtable. // for(int x2=0;x2<8;++x2) // { // for(int c=0;c<3;++c) // bmp.pixel(x+x2,y,c)=cols[((byte>>(7-x2))&1)*4+2-c]; // } // } // break; default: fclose(f); return BMPUNKNOWNFORMAT; } fclose(f); if(ferror(f)) return BMPFILEERROR; return BMPNOERROR; }
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<bmp.width*bmp.height*3;x+=3) //except the format is BGR, grr { BYTE temp=bmp.bytes[x]; bmp.bytes[x]=bmp.bytes[x+2]; bmp.bytes[x+2]=temp; } break; case(8): fread(cols,256*4,1,f); //read colortable fseek(f,offset,SEEK_SET); for(y=0;y<bmp.height;++y) //(Notice 4bytes/col for some reason) for(x=0;x<bmp.width;++x) { BYTE byte; fread(&byte,1,1,f); //just read byte for(int c=0;c<3;++c) bmp.pixel(x,y,c)=cols[byte*4+2-c]; //and look up in the table } break; case(4): fread(cols,16*4,1,f); fseek(f,offset,SEEK_SET); for(y=0;y<256;++y) for(x=0;x<256;x+=2) { BYTE byte; fread(&byte,1,1,f); //as above, but need to exract two for(c=0;c<3;++c) //pixels from each byte bmp.pixel(x,y,c)=cols[byte/16*4+2-c]; for(c=0;c<3;++c) bmp.pixel(x+1,y,c)=cols[byte%16*4+2-c]; } break; case(1): fread(cols,8,1,f); fseek(f,offset,SEEK_SET); for(y=0;y<bmp.height;++y) for(x=0;x<bmp.width;x+=8) { BYTE byte; fread(&byte,1,1,f); //Every byte is eight pixels //so I'm shifting the byte to the relevant position, then masking out //all but the lowest bit in order to get the index into the colourtable. for(int x2=0;x2<8;++x2) for(int c=0;c<3;++c) bmp.pixel(x+x2,y,c)=cols[((byte>>(7-x2))&1)*4+2-c]; } break; default: fclose(f); return BMPUNKNOWNFORMAT; } if(ferror(f)) { fclose(f); return BMPFILEERROR; } fclose(f); return BMPNOERROR; }