Code:
#include <cstring>
#include <cctype>
#include <fstream>
typedef unsigned char Uint8;
typedef unsigned short Uint16;
typedef unsigned int Uint32;
enum ImageExtensions { NO_EXT, EXT_INVALID, BMP, JPG, PNG, TGA };
enum ImageLoad { LOAD_IMAGE_SUCCESS, LOAD_IMAGE_INVALID, LOAD_IMAGE_UNSUPPORTED_BITDEPTH };
class Image
{
public:
Image(){w=0;h=0;pixels=NULL;}
~Image(){delete[] pixels;}
bool Load(const char*);
bool Save(const char*);
int GetWidth();
int GetHeight();
Uint32* GetImage();
private:
int GetExt(const char*);
int LoadBMP(const char*);
int LoadJPG(const char*);
int LoadPNG(const char*);
int LoadTGA(const char*);
int SaveBMP(const char*);
int BytesToInt(char*);
short BytesToShort(char*);
void IntToBytes(char*, Uint32);
void ShortToBytes(char*, Uint16);
int w, h;
Uint32 *pixels;
};
//------------------------------------------------------------------//
//********************* PUBLIC FUNCTIONS ***************************//
//------------------------------------------------------------------//
bool Image::Load(const char* filename)
{
switch(GetExt(filename))
{
case NO_EXT:
return false;
case EXT_INVALID:
return false;
case BMP:
LoadBMP(filename);
break;
case JPG:
break;
case PNG:
break;
case TGA:
break;
}
return true;
}
bool Image::Save(const char* filename)
{
SaveBMP(filename);
return 0;
}
int Image::GetWidth()
{
return w;
}
int Image::GetHeight()
{
return h;
}
Uint32* Image::GetImage()
{
return pixels;
}
//------------------------------------------------------------------//
//********************* PRIVATE FUNCTIONS **************************//
//------------------------------------------------------------------//
int Image::GetExt(const char* filename)
{
//This function gets a file extension and checks if it is valid
char ext[10]="";
char *e_ptr = ext;
char *f_ptr = (char*)filename;
f_ptr = strrchr((char*)filename, '.');
if(!f_ptr) return NO_EXT;
//Copy The extension converting to upper case
while(*e_ptr++ = toupper(*f_ptr++));
//Check against valid extensions
if(!strcmp(ext, ".BMP")) return BMP;
if(!strcmp(ext, ".JPG")) return JPG;
if(!strcmp(ext, ".JPEG")) return JPG;
if(!strcmp(ext, ".PNG")) return PNG;
if(!strcmp(ext, ".TGA")) return TGA;
if(!strcmp(ext, ".TARGA"))return TGA;
return EXT_INVALID;
}
int Image::LoadBMP(const char* filename)
{
ifstream in;
in.open(filename, ios::binary);
if(! in.is_open()) return LOAD_IMAGE_INVALID;
char bytes[4];
in.seekg(18, ios::beg);
in.read(bytes, 4);
w=BytesToInt(bytes);
in.read(bytes, 4);
h=BytesToInt(bytes);
in.seekg(2, ios::cur);
in.read(bytes, 2);
short bpp=BytesToShort(bytes);
if(bpp != 24) return LOAD_IMAGE_UNSUPPORTED_BITDEPTH;
//Allocate space for image data
pixels = new Uint32[w*h];
Uint32 *px = pixels;
in.seekg(54, ios::beg);
for(int y=h; y>0; y--)
{
for(int x=0; x<w; x++)
{
in.read(bytes, 3);
*px=((Uint8)bytes[2]<<16)+((Uint8)bytes[1]<<8)+(Uint8)bytes[0];
px++;
}
}
in.close();
return true;
}
int Image::BytesToInt(char* i)
{
return ((Uint8)i[3]<<24)+((Uint8)i[2]<<16)+((Uint8)i[1]<<8)+(Uint8)i[0];
}
short Image::BytesToShort(char* i)
{
return ((Uint8)i[1]<<8)+(Uint8)i[0];
}
int Image::SaveBMP(const char* filename)
{
ofstream out;
out.open(filename, ios::binary);
if(! out.is_open()) return 1;
char bytes[4]={'B','M','B', 'M'};
//-------HEADER--------------//
out.write(bytes, 2); //Write bitmap ID
IntToBytes(bytes, w*h*3+54);
out.write(bytes, 4); //Uint32 File Size In Bytes
IntToBytes(bytes, 0);
out.write(bytes, 4); //Uint16 reserved 1 and 2
IntToBytes(bytes, 44);
out.write(bytes, 4); //Int Offset To Image Data
//------- FILE INFO --------//
IntToBytes(bytes, 40);
out.write(bytes, 4); //Uint32 Header Size In Bytes
IntToBytes(bytes, (Uint32)w);
out.write(bytes, 4); //Int Image Width
IntToBytes(bytes, (Uint32)h);
out.write(bytes, 4); //Int Image Height
ShortToBytes(bytes, 1);
out.write(bytes, 2); //Unsigned Short Planes = 1
ShortToBytes(bytes, 24);
out.write(bytes, 2); //Unsigend Short Bit Depth = 24
IntToBytes(bytes, 0);
out.write(bytes, 4); //Unsigned Int Compression = 0 (No compression)
IntToBytes(bytes, w*h*3);
out.write(bytes, 4); //Unsigned Int Image Size In Bytes
IntToBytes(bytes, 2835);
out.write(bytes, 4);
out.write(bytes, 4); //Int X_Res, Y_Rex (pixes per meter)
IntToBytes(bytes, 0);
out.write(bytes, 4); //Uint32 number of paletted colours =0
out.write(bytes, 4); //Uint32 Important colours
//------ IMAGE DATA --------//
Uint32 *px = pixels;
for(int y=h; y>0; y--)
{
for(int x=0; x<w; x++)
{
IntToBytes(bytes, *px);
out.write(bytes, 3);
px++;
}
}
out.close();
return 0;
}
void Image::IntToBytes(char* bytes, Uint32 num)
{
bytes[3] = num >> 24;
bytes[2] = (num >> 16) & 255;
bytes[1] = (num >> 8) & 255;
bytes[0] = num & 255;
}
void Image::ShortToBytes(char* bytes, Uint16 num)
{
bytes[1] = num >> 8;
bytes[0] = num & 255;
}
[edit] Actually you could probably get rid of just about everything and just use the load bmp function [/edit]