Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "stdio.h"
- #include "sys/stat.h"//required for setting file permissions
- #include "fcntl.h"//required for setting create/readwrite/read only etc.
- #include <cstring>
- #include <stdlib.h>
- #include <stdint.h>
- #include <iostream>
- 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<palettecols; i++){
- r=(palette[i]&0x000000FF);
- g=(palette[i]&0x0000FF00)>>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; y<Surface->h; y++){
- for (uint32_t x = 0; x<Surface->w; 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; i<palettecols; i++){
- read(file, &palette[i], 4);
- }
- }
- /// pixeldata
- lseek(file, dataoffset, SEEK_SET);
- uint8_t *buffer = new uint8_t[imgbytes];
- memset(buffer, 0, imgbytes);
- read(file, buffer, imgbytes);
- close(file);
- /// convert data to rgb format
- if (Surface->PixData != 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; y<Surface->h; y++){
- for (uint32_t x = 0; x<Surface->w; 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;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement