#include "stdio.h" #include "sys/stat.h"//required for setting file permissions #include "fcntl.h"//required for setting create/readwrite/read only etc. #include #include #include #include using namespace std; #include "BMP.h" ///// note for other viewers: doesn't have anything other than function prototypes void saveBMP(const char *filepath, OGL_Surface *Surface, int bpp, uint8_t compression) { if (bpp==32 || bpp==4){bpp=24;}//do not support 32bit if (bpp==3){bpp=24;} int palettecols =0;// (should be included as function arg) uint32_t imgbytes = (Surface->w*Surface->h*bpp)/8; int padding = (Surface->w*3)%4; if (padding != 0){padding=4-padding; imgbytes += Surface->h*padding;} uint32_t data = 0; int file = open(filepath, O_CREAT | O_RDWR, S_IRWXU); if (file < 0 ){perror("ERROR CREATING/OPENING BMP FILE");exit(1);} lseek(file, 0, SEEK_SET); /// file header (14 bytes) //BitMap declaraction write(file, "BM", 2); //complete file size in bytes. 14+40 + num bytes for image data + (palette) if (bpp>8){data = imgbytes + 54;} else{data = imgbytes + 54 + palettecols*4;} write(file, &data, 4); //reserved nulls data=0; write(file, &data, 4); //offset to actual pixel data (again 14+40) + (palette) if (bpp>8){data=54;} else{data = 54 + palettecols*4;} write(file, &data, 4); /// file info (40 bytes) //size of info data data=40; write(file, &data, 4); //image width, height data=Surface->w; write(file, &data, 4); data=Surface->h; write(file, &data, 4); //must be set to 1 data=1; write(file, &data, 2); //bits per pixel (MAX 24!) data= min(bpp,24); write(file, &data, 2); //compression, compression notes: http://netghost.narod.ru/gff/vendspec/micbmp/bmp.txt data=0; write(file, &data, 4); //image size in bytes data=imgbytes; write(file, &data, 4); //x,y pixels per meter (set to 0) data=0; write(file, &data, 4); write(file, &data, 4); /// palette (only for 1,4 and 8 bit images, 4 bytes per colour, min 8 bytes) //colours used (0=autodetect from bpp, for 8bpp or less palette will only use the amount of colours) write(file, &data, 4); //important colours (0=all are important) write(file, &data, 4); //palette (should be included as function arg) uint32_t *palette = NULL; uint8_t r,g,b; if (bpp<24){ for (uint8_t i = 0; i>8; b=(palette[i]&0x00FF0000)>>16; write(file, &b, 1);//b write(file, &g, 1);//g write(file, &r, 1);//r write(file, 0, 1);//null } } /// pixeldata uint8_t *buffer = new uint8_t[imgbytes]; memset(buffer, 0, imgbytes); int datawidth = (Surface->w*3)+padding; int pos = 0; int buf_pos = imgbytes-datawidth; for (uint32_t y = 0; yh; y++){ for (uint32_t x = 0; xw; x++){ buffer[buf_pos] = Surface->PixData[pos]; buffer[buf_pos+1]= Surface->PixData[pos+1]; buffer[buf_pos+2]= Surface->PixData[pos+2]; buf_pos+=3; pos+=Surface->bpp; } //return buffer to start of line then up one line buf_pos += padding; buf_pos -= datawidth+datawidth; } write(file, buffer, imgbytes); close(file); delete [] buffer; } void loadBMP(const char *filepath, OGL_Surface *Surface) { char BMP[3]= {0,0}; int dataoffset=0; int imgbytes=0; int compression=0; char bpp= 0; int file = open(filepath, O_RDONLY, S_IRWXU); if (file < 0 ){perror("ERROR LOADING BMP FILE");exit(1);} /// file header //BitMap declaraction lseek(file, 0, SEEK_SET); read(file, BMP, 2); if (BMP[0] != 'B' || BMP[1] != 'M'){printf("UNSUPPORTED FILE TYPE (not BMP)");exit(1);} //skip file size, 4 //skip reserved nulls, 4 //offset to actual pixel data lseek(file, 10, SEEK_SET); read(file, &dataoffset, 4); //skip headersize, 4 //width & height lseek(file, 18, SEEK_SET); read(file, &Surface->w, 4); read(file, &Surface->h, 4); //skip "planes", 2 //bits per pixel lseek(file, 28, SEEK_SET); read(file, &bpp, 2); //compression read(file, &compression, 4); if (compression != 0){printf("FILE USING UNSUPPORTED COMPRESSION");exit(1);} //size of image data in bytes read(file, &imgbytes, 4); //skip hres, 4 //skip vres, 4 /// palette (only for 1,4 and 8 bit images) uint32_t *palette; if (bpp<24){ //colours used lseek(file, 46, SEEK_SET); int palettecols; read(file, &palettecols, 4); //skip important colours, 4 if (palettecols != 0){ palette = new uint32_t[palettecols]; memset(palette, 0, palettecols*4); } for (int i = 0; iPixData != NULL){delete [] Surface->PixData;} Surface->PixData = new uint8_t[Surface->w*Surface->h*Surface->bpp]; memset(Surface->PixData, 255, Surface->w*Surface->h*Surface->bpp); int padding = (Surface->w*3)%4; if (padding != 0){padding=4-padding;} int datawidth = (Surface->w*3)+padding; int pos = 0; int buf_pos = imgbytes-datawidth; for (uint32_t y = 0; yh; y++){ for (uint32_t x = 0; xw; x++){ Surface->PixData[pos] = buffer[buf_pos]; Surface->PixData[pos+1]= buffer[buf_pos+1]; Surface->PixData[pos+2]= buffer[buf_pos+2]; //if supporting alpha, set 255,0,255 to transparent if(Surface->bpp==4 && buffer[buf_pos] == 255 && buffer[buf_pos+1] == 0 && buffer[buf_pos+2] == 255){Surface->PixData[pos+3]= 0;} buf_pos+=3; pos+=Surface->bpp; } //return buffer to start of line then up one line buf_pos += padding; buf_pos -= datawidth+datawidth; } delete [] buffer; } void loadBMP(const char *filepath, OGL_Texture *Texture) { OGL_Surface *Surface = new OGL_Surface; Surface->Create_Surface(1,1,4); loadBMP(filepath, Surface); Texture->gen_texture(Surface->w, Surface->h, Surface->PixData); delete Surface; }