Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifndef _BITMAP_H
- #define _BITMAP_H
- #include <iostream>
- #include <cstdio>
- #include <string>
- using namespace std;
- const short BITMAP_MAGIC_NUMBER=19778;
- const int RGB_BYTE_SIZE=3;
- #pragma pack(push,bitmap_data,1)
- typedef struct tagRGBQuad {
- char rgbBlue;
- char rgbGreen;
- char rgbRed;
- char rgbReserved;
- } __attribute__ ((packed)) RGBQuad;
- typedef struct tagBitmapFileHeader {
- unsigned short bfType;
- unsigned int bfSize;
- unsigned short bfReserved1;
- unsigned short bfReserved2;
- unsigned int bfOffBits;
- } __attribute__ ((packed)) BitmapFileHeader;
- typedef struct tagBitmapInfoHeader {
- unsigned int biSize;
- int biWidth;
- int biHeight;
- unsigned short biPlanes;
- unsigned short biBitCount;
- unsigned int biCompression;
- unsigned int biSizeImage;
- int biXPelsPerMeter;
- int biYPelsPerMeter;
- unsigned int biClrUsed;
- unsigned int biClrImportant;
- } __attribute__ ((packed)) BitmapInfoHeader;
- #pragma pack(pop,bitmap_data)
- class Bitmap {
- public:
- //variables
- RGBQuad *colours;
- char *data;
- bool loaded;
- int width,height;
- unsigned short bpp;
- string error;
- //methods
- Bitmap(void);
- Bitmap(char *);
- ~Bitmap();
- bool loadBMP(char *);
- private:
- //variables
- BitmapFileHeader bmfh;
- BitmapInfoHeader bmih;
- int byteWidth; //the width in bytes of the image
- int padWidth; //the width in bytes of the added image
- unsigned int dataSize; //size of the data in the file
- //methods
- void reset(void);
- bool convert24(char *); //convert to 24bit RGB bottom up data
- bool convert8(char *); //convert to 24bit RGB bottom up data
- };
- #endif //_BITMAP_H
- //basic constructor
- Bitmap::Bitmap(){
- reset();
- }
- //constructor loads the bitmap when it is created
- Bitmap::Bitmap(char *file){
- reset();
- loadBMP(file);
- }
- //destructor
- Bitmap::~Bitmap(){
- if(colours!=0) {
- delete[] colours;
- }
- if(data!=0) {
- delete[] data;
- }
- }
- //load a bitmap from a file and represent it correctly
- //in memory
- bool Bitmap::loadBMP(char *file) {
- FILE *in; //file stream for reading
- char *tempData; //temp storage for image data
- int numColours; //total available colours
- //bitmap is not loaded yet
- loaded=false;
- //make sure memory is not lost
- if(colours!=0) {
- delete[] colours;
- }
- if(data!=0) {
- delete[] data;
- }
- //open the file for reading in binary mode
- in=fopen(file,"rb");
- //if the file does not exist return in error
- if(in==NULL) {
- error="File not found";
- fclose(in);
- return false;
- }
- //read in the entire BITMAPFILEHEADER
- fread(&bmfh,sizeof(BitmapFileHeader),1,in);
- cout << "sizeof(BitmapFileHeader)=" << sizeof(BitmapFileHeader) << endl;
- //check for the magic number that says this is a bitmap
- if(bmfh.bfType!=BITMAP_MAGIC_NUMBER) {
- error="File is not in DIB format";
- fclose(in);
- return false;
- }
- //read in the entire BITMAPINFOHEADER
- fread(&bmih,sizeof(BitmapInfoHeader),1,in);
- cout << "sizeof(BitmapInfoHeader)=" << sizeof(BitmapInfoHeader) << endl;
- //save the width, height and bits per pixel for external use
- width=bmih.biWidth;
- height=bmih.biHeight;
- bpp=bmih.biBitCount;
- cout << "biBitCount =" << bmih.biBitCount << endl;
- cout << "biClrImportant =" << bmih.biClrImportant << endl;
- cout << "biClrUsed =" << bmih.biClrUsed << endl;
- cout << "biCompression =" << bmih.biCompression << endl;
- cout << "biHeight =" << bmih.biHeight << endl;
- cout << "biPlanes =" << bmih.biPlanes << endl;
- cout << "biSize =" << bmih.biSize << endl;
- cout << "biSizeImage =" << bmih.biSizeImage << endl;
- cout << "biWidth =" << bmih.biWidth << endl;
- cout << "biXPelsPerMeter =" << bmih.biXPelsPerMeter << endl;
- cout << "biYPelsPerMeter =" << bmih.biYPelsPerMeter << endl;
- //calculate the size of the image data with padding
- dataSize=(width*height*(unsigned int)(bmih.biBitCount/8.0));
- //calculate the number of available colours
- numColours=1<<bmih.biBitCount;
- //if the bitmap is not 8 bits per pixel or more
- //return in error
- if(bpp<8) {
- error="File is not 8 or 24 bits per pixel";
- fclose(in);
- return false;
- }
- //load the palette for 8 bits per pixel
- if(bpp==8) {
- colours=new RGBQuad[numColours];
- fread(colours,sizeof(RGBQuad),numColours,in);
- }
- //set up the temporary buffer for the image data
- tempData=new char[dataSize];
- //exit if there is not enough memory
- if(tempData==NULL) {
- error="Not enough memory to allocate a temporary buffer";
- fclose(in);
- return false;
- }
- //read in the entire image
- fread(tempData,sizeof(char),dataSize,in);
- //close the file now that we have all the info
- fclose(in);
- //calculate the witdh of the final image in bytes
- byteWidth=padWidth=(int)((float)width*(float)bpp/8.0);
- //adjust the width for padding as necessary
- while(padWidth%4!=0) {
- padWidth++;
- }
- //change format from GBR to RGB
- if(bpp==8) {
- loaded=convert8(tempData);
- }
- else if(bpp==24) {
- loaded=convert24(tempData);
- }
- //clean up memory
- delete[] tempData;
- //bitmap is now loaded
- error="Bitmap loaded";
- //return success
- return loaded;
- }
- //function to set the inital values
- void Bitmap::reset(void) {
- loaded=false;
- colours=0;
- data=0;
- error="";
- }
- bool Bitmap::convert24(char* tempData) {
- int offset,diff;
- diff=width*height*RGB_BYTE_SIZE;
- //allocate the buffer for the final image data
- data=new char[diff];
- //exit if there is not enough memory
- if(data==NULL) {
- error="Not enough memory to allocate an image buffer";
- delete[] data;
- return false;
- }
- if(height>0) {
- offset=padWidth-byteWidth;
- //count backwards so you start at the front of the image
- for(int i=0;i<dataSize;i+=3) {
- //jump over the padding at the start of a new line
- if((i+1)%padWidth==0) {
- i+=offset;
- }
- //transfer the data
- *(data+i+2)=*(tempData+i);
- *(data+i+1)=*(tempData+i+1);
- *(data+i)=*(tempData+i+2);
- }
- }
- //image parser for a forward image
- else {
- offset=padWidth-byteWidth;
- int j=dataSize-3;
- //count backwards so you start at the front of the image
- //here you can start from the back of the file or the front,
- //after the header The only problem is that some programs
- //will pad not only the data, but also the file size to
- //be divisible by 4 bytes.
- for(int i=0;i<dataSize;i+=3) {
- //jump over the padding at the start of a new line
- if((i+1)%padWidth==0) {
- i+=offset;
- }
- //transfer the data
- *(data+j+2)=*(tempData+i);
- *(data+j+1)=*(tempData+i+1);
- *(data+j)=*(tempData+i+2);
- j-=3;
- }
- }
- return true;
- }
- bool Bitmap::convert8(char* tempData) {
- int offset,diff;
- diff=width*height*RGB_BYTE_SIZE;
- //allocate the buffer for the final image data
- data=new char[diff];
- //exit if there is not enough memory
- if(data==NULL) {
- error="Not enough memory to allocate an image buffer";
- delete[] data;
- return false;
- }
- if(height>0) {
- offset=padWidth-byteWidth;
- int j=0;
- //count backwards so you start at the front of the image
- for(int i=0;i<dataSize*RGB_BYTE_SIZE;i+=3) {
- //jump over the padding at the start of a new line
- if((i+1)%padWidth==0) {
- i+=offset;
- }
- //transfer the data
- *(data+i)=colours[*(tempData+j)].rgbRed;
- *(data+i+1)=colours[*(tempData+j)].rgbGreen;
- *(data+i+2)=colours[*(tempData+j)].rgbBlue;
- j++;
- }
- }
- //image parser for a forward image
- else {
- offset=padWidth-byteWidth;
- int j=dataSize-1;
- //count backwards so you start at the front of the image
- for(int i=0;i<dataSize*RGB_BYTE_SIZE;i+=3) {
- //jump over the padding at the start of a new line
- if((i+1)%padWidth==0) {
- i+=offset;
- }
- //transfer the data
- *(data+i)=colours[*(tempData+j)].rgbRed;
- *(data+i+1)=colours[*(tempData+j)].rgbGreen;
- *(data+i+2)=colours[*(tempData+j)].rgbBlue;
- j--;
- }
- }
- return true;
- }
- int main()
- {
- // Odczytanie bitmapy
- Bitmap *tex = new Bitmap();
- if (!tex->loadBMP("kot.bmp")) {
- printf("fukcup\n");
- return -1;
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement