Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

BMP.cpp

By: a guest on Jul 5th, 2012  |  syntax: C++  |  size: 6.03 KB  |  views: 8  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
This paste has a previous version, view the difference. Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1.  
  2. #include "stdio.h"
  3. #include "sys/stat.h"//required for setting file permissions
  4. #include "fcntl.h"//required for setting create/readwrite/read only etc.
  5. #include <cstring>
  6. #include <stdlib.h>
  7. #include <stdint.h>
  8. #include <iostream>
  9. using namespace std;
  10. #include "BMP.h" ///// note for other viewers: doesn't have anything other than function prototypes
  11.  
  12.  
  13. void saveBMP(const char *filepath, OGL_Surface *Surface, int bpp, uint8_t compression)
  14. {
  15.         if (bpp==32 || bpp==4){bpp=24;}//do not support 32bit
  16.         if (bpp==3){bpp=24;}
  17.         int palettecols =0;// (should be included as function arg)
  18.         uint32_t imgbytes = (Surface->w*Surface->h*bpp)/8;
  19.         int padding = (Surface->w*3)%4;
  20.         if (padding != 0){padding=4-padding; imgbytes += Surface->h*padding;}
  21.         uint32_t data = 0;
  22.  
  23.         int file = open(filepath, O_CREAT | O_RDWR, S_IRWXU);
  24.         if (file < 0 ){perror("ERROR CREATING/OPENING BMP FILE");exit(1);}
  25.         lseek(file, 0, SEEK_SET);
  26.  
  27.         /// file header (14 bytes)
  28.         //BitMap declaraction
  29.         write(file, "BM", 2);
  30.         //complete file size in bytes. 14+40 + num bytes for image data  + (palette)
  31.         if (bpp>8){data = imgbytes + 54;}
  32.         else{data = imgbytes + 54 + palettecols*4;}
  33.         write(file, &data, 4);
  34.         //reserved nulls
  35.         data=0;
  36.         write(file, &data, 4);
  37.         //offset to actual pixel data (again 14+40) + (palette)
  38.         if (bpp>8){data=54;}
  39.         else{data = 54 + palettecols*4;}
  40.         write(file, &data, 4);
  41.  
  42.         /// file info (40 bytes)
  43.         //size of info data
  44.         data=40;
  45.         write(file, &data, 4);
  46.         //image width, height
  47.         data=Surface->w;
  48.         write(file, &data, 4);
  49.         data=Surface->h;
  50.         write(file, &data, 4);
  51.         //must be set to 1
  52.         data=1;
  53.         write(file, &data, 2);
  54.         //bits per pixel (MAX 24!)
  55.         data= min(bpp,24);
  56.         write(file, &data, 2);
  57.         //compression, compression notes: http://netghost.narod.ru/gff/vendspec/micbmp/bmp.txt
  58.         data=0;
  59.         write(file, &data, 4);
  60.         //image size in bytes
  61.         data=imgbytes;
  62.         write(file, &data, 4);
  63.         //x,y pixels per meter (set to 0)
  64.         data=0;
  65.         write(file, &data, 4);
  66.         write(file, &data, 4);
  67.  
  68.         /// palette (only for 1,4 and 8 bit images, 4 bytes per colour, min 8 bytes)
  69.         //colours used (0=autodetect from bpp, for 8bpp or less palette will only use the amount of colours)
  70.         write(file, &data, 4);
  71.         //important colours (0=all are important)
  72.         write(file, &data, 4);
  73.         //palette (should be included as function arg)
  74.         uint32_t *palette = NULL;
  75.         uint8_t r,g,b;
  76.         if (bpp<24){
  77.                 for (uint8_t i = 0; i<palettecols; i++){
  78.                         r=(palette[i]&0x000000FF);
  79.                         g=(palette[i]&0x0000FF00)>>8;
  80.                         b=(palette[i]&0x00FF0000)>>16;
  81.                         write(file, &b, 1);//b
  82.                         write(file, &g, 1);//g
  83.                         write(file, &r, 1);//r
  84.                         write(file, 0, 1);//null
  85.                 }
  86.         }
  87.         /// pixeldata
  88.         uint8_t *buffer =  new uint8_t[imgbytes];
  89.         memset(buffer, 0, imgbytes);
  90.         int datawidth = (Surface->w*3)+padding;
  91.         int pos = 0;
  92.         int buf_pos = imgbytes-datawidth;
  93.         for (uint32_t y = 0; y<Surface->h; y++){
  94.                 for (uint32_t x = 0; x<Surface->w; x++){
  95.                         buffer[buf_pos]  = Surface->PixData[pos];
  96.                         buffer[buf_pos+1]= Surface->PixData[pos+1];
  97.                         buffer[buf_pos+2]= Surface->PixData[pos+2];
  98.                         buf_pos+=3;
  99.                         pos+=Surface->bpp;
  100.                 }
  101.                 //return buffer to start of line then up one line
  102.                 buf_pos += padding;
  103.                 buf_pos -= datawidth+datawidth;
  104.         }
  105.         write(file, buffer, imgbytes);
  106.         close(file);
  107.         delete [] buffer;
  108. }
  109.  
  110. void loadBMP(const char *filepath, OGL_Surface *Surface)
  111. {
  112.  
  113.         char BMP[3]= {0,0};
  114.         int dataoffset=0;
  115.         int imgbytes=0;
  116.         int compression=0;
  117.         char bpp= 0;
  118.         int file = open(filepath, O_RDONLY, S_IRWXU);
  119.         if (file < 0 ){perror("ERROR LOADING BMP FILE");exit(1);}
  120.  
  121.         /// file header
  122.         //BitMap declaraction
  123.         lseek(file, 0, SEEK_SET);
  124.         read(file, BMP, 2);
  125.         if (BMP[0] != 'B' || BMP[1] != 'M'){printf("UNSUPPORTED FILE TYPE (not BMP)");exit(1);}
  126.         //skip file size, 4
  127.         //skip reserved nulls, 4
  128.         //offset to actual pixel data
  129.         lseek(file, 10, SEEK_SET);
  130.         read(file, &dataoffset, 4);
  131.         //skip headersize, 4
  132.         //width & height
  133.         lseek(file, 18, SEEK_SET);
  134.         read(file, &Surface->w, 4);
  135.         read(file, &Surface->h, 4);
  136.         //skip "planes", 2
  137.         //bits per pixel
  138.         lseek(file, 28, SEEK_SET);
  139.         read(file, &bpp, 2);
  140.         //compression
  141.         read(file, &compression, 4);
  142.         if (compression != 0){printf("FILE USING UNSUPPORTED COMPRESSION");exit(1);}
  143.         //size of image data in bytes
  144.         read(file, &imgbytes, 4);
  145.         //skip hres, 4
  146.         //skip vres, 4
  147.  
  148.         /// palette (only for 1,4 and 8 bit images)
  149.         uint32_t *palette;
  150.         if (bpp<24){
  151.                 //colours used
  152.                 lseek(file, 46, SEEK_SET);
  153.                 int palettecols;
  154.                 read(file, &palettecols, 4);
  155.                 //skip important colours, 4
  156.                 if (palettecols != 0){
  157.                         palette = new uint32_t[palettecols];
  158.                         memset(palette, 0, palettecols*4);
  159.                 }
  160.                 for (int i = 0; i<palettecols; i++){
  161.                         read(file, &palette[i], 4);
  162.                 }
  163.         }
  164.  
  165.         /// pixeldata
  166.         lseek(file, dataoffset, SEEK_SET);
  167.         uint8_t *buffer =  new uint8_t[imgbytes];
  168.         memset(buffer, 0, imgbytes);
  169.         read(file, buffer, imgbytes);
  170.         close(file);
  171.  
  172.         /// convert data to rgb format
  173.         if (Surface->PixData != NULL){delete [] Surface->PixData;}
  174.         Surface->PixData = new uint8_t[Surface->w*Surface->h*Surface->bpp];
  175.         memset(Surface->PixData, 255, Surface->w*Surface->h*Surface->bpp);
  176.         int padding = (Surface->w*3)%4;
  177.         if (padding != 0){padding=4-padding;}
  178.         int datawidth = (Surface->w*3)+padding;
  179.         int pos = 0;
  180.         int buf_pos = imgbytes-datawidth;
  181.         for (uint32_t y = 0; y<Surface->h; y++){
  182.                 for (uint32_t x = 0; x<Surface->w; x++){
  183.                         Surface->PixData[pos]  = buffer[buf_pos];
  184.                         Surface->PixData[pos+1]= buffer[buf_pos+1];
  185.                         Surface->PixData[pos+2]= buffer[buf_pos+2];
  186.                         //if supporting alpha, set 255,0,255 to transparent
  187.                         if(Surface->bpp==4 && buffer[buf_pos] == 255 && buffer[buf_pos+1] == 0 && buffer[buf_pos+2] == 255){Surface->PixData[pos+3]= 0;}
  188.                         buf_pos+=3;
  189.                         pos+=Surface->bpp;
  190.                 }
  191.                 //return buffer to start of line then up one line
  192.                 buf_pos += padding;
  193.                 buf_pos -= datawidth+datawidth;
  194.         }
  195.         delete [] buffer;
  196. }
  197.  
  198. void loadBMP(const char *filepath, OGL_Texture *Texture)
  199. {
  200.         OGL_Surface *Surface = new OGL_Surface;
  201.         Surface->Create_Surface(1,1,4);
  202.         loadBMP(filepath, Surface);
  203.         Texture->gen_texture(Surface->w, Surface->h, Surface->PixData);
  204.         delete Surface;
  205. }