این سورس کد از سایت GPwiki برداشت شده و آن را در اینجا گذاشتم تا همه برنامه نویسان ++C از آن استفاده کنند.

این سورس کد فایل های 8 بیت و 24 بیت RGB با پسوند bmp را در ++C بار گذاری می کند.

// BMP Loader - Codehead 08/11/04
//
#include <iostream>
#include <fstream>
#include <memory.h>

#define IMG_OK 0x1
#define IMG_ERR_NO_FILE 0x2
#define IMG_ERR_MEM_FAIL 0x4
#define IMG_ERR_BAD_FORMAT 0x8
#define IMG_ERR_UNSUPPORTED 0x40

class BMPImg
{
public:
BMPImg();
~BMPImg();
int Load(char* szFilename);
int GetBPP();
int GetWidth();
int GetHeight();
unsigned char* GetImg(); // Return a pointer to image data
unsigned char* GetPalette(); // Return a pointer to VGA palette

private:
unsigned int iWidth,iHeight,iEnc;
short int iBPP,iPlanes;
int iImgOffset,iDataSize;
unsigned char *pImage, *pPalette, *pData;

// Internal workers
int GetFile(char* szFilename);
int ReadBmpHeader();
int LoadBmpRaw();
int LoadBmpRLE8();
int LoadBmpPalette();
void FlipImg(); // Inverts image data, BMP is stored in reverse scanline order
};


BMPImg::BMPImg()
{
pImage=pPalette=pData=NULL;
iWidth=iHeight=iBPP=iPlanes=iEnc=0;
}


BMPImg::~BMPImg()
{
if(pImage)
{
delete [] pImage;
pImage=NULL;
}

if(pPalette)
{
delete [] pPalette;
pPalette=NULL;
}

if(pData)
{
delete [] pData;
pData=NULL;
}
}


int BMPImg::Load(char* szFilename)
{
int iRet;

// Clear out any existing image and palette
if(pImage)
{
delete [] pImage;
pImage=NULL;
}

if(pPalette)
{
delete [] pPalette;
pPalette=NULL;
}

// Get the file into memory
iRet=GetFile(szFilename);

if(iRet!=IMG_OK)
return iRet;

// Process the header
iRet=ReadBmpHeader();

if(iRet!=IMG_OK)
return iRet;

if(iBPP<8) // We'll only bother with 8 bit and above
return IMG_ERR_UNSUPPORTED;

// Get the image data
switch(iEnc)
{
case 0: // Uncompressed
iRet=LoadBmpRaw(); // 8 / 24 Bit. (24 bit is in BGR order)
break;

case 1: // RLE 8 (Indexed 256 colour only)
iRet=LoadBmpRLE8();
break;

case 2: // RLE 4 (16 Colour indexed, Outdated, not covered here)
return IMG_ERR_UNSUPPORTED;

case 3: // Bitfields (16/32 bit only, Rare, not covered here)
return IMG_ERR_UNSUPPORTED;

default:
return IMG_ERR_UNSUPPORTED;
}

if(iRet!=IMG_OK)
return iRet;

// Flip image to correct scanline reversal
FlipImg();

// Load palette if present
iRet=LoadBmpPalette();

if(iRet!=IMG_OK)
return iRet;

// Free the file data
delete [] pData;
pData=NULL;

return IMG_OK;
}


int BMPImg::GetFile(char* szFilename)
{
using namespace std;
ifstream fIn;
unsigned long ulSize;

// Open the specified file
fIn.open(szFilename,ios::binary);

if(fIn==NULL)
return IMG_ERR_NO_FILE;

// Get file size
fIn.seekg(0,ios_base::end);
ulSize=fIn.tellg();
fIn.seekg(0,ios_base::beg);

// Allocate some space
// Check and clear pDat, just in case
if(pData)
{
delete [] pData;
pData=NULL;
}

pData=new unsigned char[ulSize];

if(pData==NULL)
{
fIn.close();
return IMG_ERR_MEM_FAIL;
}

// Read the file into memory
fIn.read((char*)pData,ulSize);

fIn.close();

return IMG_OK;
}


int BMPImg::ReadBmpHeader()
{
int iInfo;

if(pData==NULL)
return IMG_ERR_NO_FILE;

if(pData[0x0]!='B' || pData[0x1]!='M') // BMP ID Bytes, should be 'BM'
return IMG_ERR_BAD_FORMAT;

memcpy(&iImgOffset,&pData[0xA],4); // Offset to image data

memcpy(&iInfo,&pData[0xE],4); // Info header size, should be 0x28
if(iInfo!=0x28)
return IMG_ERR_BAD_FORMAT;

memcpy(&iWidth,&pData[0x12],4); // Image width
memcpy(&iHeight,&pData[0x16],4); // Image height
memcpy(&iPlanes,&pData[0x1A],2); // Colour planes
memcpy(&iBPP,&pData[0x1C],2); // BPP
memcpy(&iEnc,&pData[0x1E],4); // Encoding

iDataSize=(iWidth*iHeight*(iBPP/8)); // Calculate Image Data size

return IMG_OK;
}


int BMPImg::LoadBmpRaw()
{
if(pImage)
{
delete [] pImage;
pImage=NULL;
}

// Allocate space for the image data
pImage=new unsigned char[iDataSize];

if(pImage==NULL)
return IMG_ERR_MEM_FAIL;

memcpy(pImage,&pData[iImgOffset],iDataSize);

return IMG_OK;
}


int BMPImg::LoadBmpRLE8()
{
unsigned char bOpCode,bVal;
unsigned char *pSrc;
int iDcode=1,iCount,iPos,iIndex;

// Allocate space for the image
if(pImage)
delete [] pImage;

pImage=new unsigned char[iDataSize];

if(pImage==NULL)
return IMG_ERR_MEM_FAIL;

// Get the start of the RLE data
pSrc=&pData[iImgOffset];

iPos=0;
iIndex=0;

while(iDcode)
{
// Stay on even bytes
while(iPos%2)
{
iPos++;
}

bOpCode=pSrc[iPos];
bVal=pSrc[iPos+1];
iPos+=2;

if(bOpCode>0) // Run mode, Repeat 'bVal' 'OpCode' times
{
for(iCount=0;iCount!=bOpCode;iCount++)
{
pImage[iIndex]=bVal;
++iIndex;
}
}
else // Absolute Mode (Opcode=0), various options
{
switch(bVal)
{
case 0: // EOL, no action
break;

case 1: // EOF, STOP!
iDcode=0;
break;

case 2: // Reposition, Never used
break;

default: // Copy the next 'bVal' bytes directly to the image
for(iCount=bVal;iCount!=0;iCount--)
{
pImage[iIndex]=pSrc[iPos];
++iIndex;
++iPos;
}
break;
}

}
if(iIndex>iDataSize) // Stop if image size exceeded.
iDcode=0;
}

return IMG_OK;
}


int BMPImg::LoadBmpPalette()
{
int iIndex;
unsigned char *pPalPos, *pDatPos;

if(pPalette)
{
delete [] pPalette;
pPalette=NULL;
}

if(iBPP>8) // NULL Palette for RGB images
return IMG_OK;

// Create space for palette
pPalette=new unsigned char[768];

if(pPalette==NULL)
return IMG_ERR_MEM_FAIL;

// Set starting position for pointers
pPalPos=pPalette;
pDatPos=&pData[0x36];

// Get colour values, skip redundant 4th value
for(iIndex=0;iIndex!=256;++iIndex)
{
pPalPos[0]=pDatPos[2]; // Red
pPalPos[1]=pDatPos[1]; // Green
pPalPos[2]=pDatPos[0]; // Blue

pPalPos+=3;
pDatPos+=4;
}

return IMG_OK;
}


void BMPImg::FlipImg(void)
{
unsigned char bTemp;
unsigned char *pLine1, *pLine2;
int iLineLen,iIndex;

iLineLen=iWidth*(iBPP/8);
pLine1=pImage;
pLine2=&pImage[iLineLen * (iHeight - 1)];

for( ;pLine1<pLine2;pLine2-=(iLineLen*2))
{
for(iIndex=0;iIndex!=iLineLen;pLine1++,pLine2++,iI ndex++)
{
bTemp=*pLine1;
*pLine1=*pLine2;
*pLine2=bTemp;
}
}

}


int BMPImg::GetBPP()
{
return iBPP;
}


int BMPImg::GetWidth()
{
return iWidth;
}


int BMPImg::GetHeight()
{
return iHeight;
}


unsigned char* BMPImg::GetImg()
{
return pImage;
}


unsigned char* BMPImg::GetPalette()
{
return pPalette;
}