讀取BMP主要分為讀取
1. //位圖文件頭
BITMAPFILEHEADER header;
2.. //位圖信息頭
BITMAPINFOHEADER info;
3.讀取數據
BMP的數據格式是BGR,所以我們要轉換為RGB格式,同時注意,BMP圖像中存儲的數據是從左下角開始存儲的,到右上角結束,也就是最后一行是正常的第一行,倒是第二行是正常的第二行...
我們可以根據這些作出一些效果,比如翻轉etc.
//圖像倒轉

for( int height = texture->height - 1; height >= 0 ; height-- )
{
GLubyte* pdest = texture->imageData + height * texture->width * channel;
fread( pdest, 1, texture->width * channel,file );

for( int i = 0; i < texture->width* channel; i+=channel )
{
pdest[ i ] ^= pdest[i+2] ^= pdest[i] ^= pdest[i+2];
}
}

//正常圖像

for( int h = 0; h < (int)texture->height; h++ )
{
GLubyte* pdest = texture->imageData + h * texture->width * channel;
fread( pdest, 1, texture->width * channel,file );

for( int i = 0; i < texture->width* channel; i+=channel )
{
pdest[ i ] ^= pdest[i+2] ^= pdest[i] ^= pdest[i+2]; //將BGR轉為RGB,BMP數據從左下角到右上角的方式存儲
}
}
4..這里比較簡單,只考慮讀取24位和32位的,1,2,4,8,16位的BMP圖像沒有做處理
switch(infoheader->biBitCount)

{
case 1:
case 2:
case 4:

{
for(i=0;i<pxcnt;i++)

{
DWORD px=bits[i*infoheader->biBitCount>>8]>>(i&7)&((1<<infoheader->biBitCount)-1);//取得某一個位置的像素
if(px<infoheader->biClrUsed)
pixels[i]=palette[px];
else
pixels[i]=undefinedQuad;
}
}
break;
case 8:

{
for(i=0;i<pxcnt;i++)

{
DWORD px=bits[i];//取得某一個位置的像素
if(px<infoheader->biClrUsed)//出于安全問題,限制色彩范圍。
pixels[i]=palette[px];
else
pixels[i]=undefinedQuad;//超出調色板范圍,
}
}
break;
case 16:

{
//16位增強色
//一般是RGB各5bit
WORD* pxwd=(WORD*)bits;
for(i=0;i<pxcnt;i++)

{
pixels[i].rgbBlue=pxwd[i]&_16bitMask;
pixels[i].rgbGreen=(pxwd[i]>>5)&_16bitMask;
pixels[i].rgbRed=(pxwd[i]>>10)&_16bitMask;
pixels[i].rgbReserved=0;
}
}
break;
case 24:

{
//將三個字節的數據擴展為4字節的
for(i=0;i<pxcnt;i++)

{
pixels[i].rgbBlue=bits[i*3];
pixels[i].rgbGreen=bits[i*3+1];
pixels[i].rgbRed=bits[i*3+2];
pixels[i].rgbReserved=0;
}
}
}
free(bits);
if(index==NULL)
free(palette);
else
*index=palette;
}
else

{
//如果沒有調色板,則直接使用文件內的區域。
fread(pixels,1,infoheader->biSizeImage,file);
}

//Image.h
typedef struct _tTexImage


{
GLubyte* imageData;
GLuint width;
GLuint height;
GLuint bpp; //Image color depth in bits per pixel
GLuint texID;
GLuint imageType;
GLboolean bCompressed; //Compressed or Uncompressed


_tTexImage():imageData(NULL),texID(-1)
{}
}TexImage;

#pragma pack( pop )



class Image


{
public:
Image(void);
~Image(void);

public:

/**//** 加載TGA圖片 **/
BOOL loadTGA( TexImage* texture, LPCSTR filename );
static BOOL release( TexImage* texture );

/**//** 生成紋理 **/
void generateTexture( TexImage* texture, BOOL bMipmap = TRUE );

public:
BOOL loadBMP( TexImage* texture, LPCSTR fileName );
protected:
BOOL loadUncompressedTGA( TexImage* texture, FILE* file );
BOOL loadCompressedTGA( TexImage* texture, FILE* file );
};
//Image.cpp
....
//-----------------------------------------------------------------------
// 函數名 : Image::loadBMP
// 說明 : LoadBmp
// 返回 : BOOL
// 參數 : TexImage* texture
// 參數 : LPCSTR fileName
// 作者 : Teng
// 創建時間 : 2010-5-28 14:04:30
// 最后修改 : 2010-5-28
//-----------------------------------------------------------------------
BOOL Image::loadBMP( TexImage* texture , LPCSTR fileName )


{
FILE* file = fopen( fileName, "rb" );

if ( !file )
{
TRACE("Open file %s failed!\n", fileName );
return FALSE;
}

//位圖文件頭
BITMAPFILEHEADER header;

if ( sizeof(BITMAPFILEHEADER) != fread( &header, 1, sizeof(BITMAPFILEHEADER), file ) )
{
TRACE("Read bmp header failed!\n");
return FALSE;
}

//檢查頭結構體 "BM" 即0x4D42

if ( header.bfType != 0x4D42 )
{
return FALSE;
}

//位圖信息頭
BITMAPINFOHEADER info;

if ( sizeof(BITMAPINFOHEADER) != fread( &info, 1, sizeof(BITMAPINFOHEADER), file ) )
{
TRACE("Read bmp infomation failed!\n");
return FALSE;
}
texture->width = info.biWidth;
texture->height = info.biHeight;
texture->bpp = info.biBitCount;

/**//** 將指針移到數據開始位置 */
fseek( file, header.bfOffBits, SEEK_SET );

switch( texture->bpp )

{
case 24:
case 32:

{
int channel= 0;

if ( texture->bpp == 24 )
{
channel = 3;
texture->imageType = GL_RGB;

}else
{
channel = 4;
texture->imageType = GL_RGBA;
}
texture->imageData = new GLubyte[ texture->width * texture->height * channel ];
//圖像倒轉

for( int height = texture->height - 1; height >= 0 ; height-- )
{
GLubyte* pdest = texture->imageData + height * texture->width * channel;
fread( pdest, 1, texture->width * channel,file );

for( int i = 0; i < texture->width* channel; i+=channel )
{
pdest[ i ] ^= pdest[i+2] ^= pdest[i] ^= pdest[i+2];
}
}

//正常圖像

for( int h = 0; h < (int)texture->height; h++ )
{
GLubyte* pdest = texture->imageData + h * texture->width * channel;
fread( pdest, 1, texture->width * channel,file );

for( int i = 0; i < texture->width* channel; i+=channel )
{
pdest[ i ] ^= pdest[i+2] ^= pdest[i] ^= pdest[i+2]; //將BGR轉為RGB,BMP數據從左下角到右上角的方式存儲
}
}
}
break;
}


return TRUE;
}
...
別人寫的一個BMP加載的代碼,大同小異。

/**//** 裝載一個位圖文件 */

19 bool CBMPLoader::LoadBitmap(const char *file)


20
{


21 FILE *pFile = 0; /**//**< 文件指針 */

22


23 /**//** 創建位圖文件信息和位圖文件頭結構 */

24 BITMAPINFOHEADER bitmapInfoHeader;

25 BITMAPFILEHEADER header;

26


27 unsigned char textureColors = 0;/**//**< 用于將圖像顏色從BGR變換到RGB */

28


29 /**//** 打開文件,并檢查錯誤 */

30 pFile = fopen(file, "rb");

31 if(pFile == 0)

32 return false;

33


34 /**//** 讀入位圖文件頭信息 */

35 fread(&header, sizeof(BITMAPFILEHEADER), 1, pFile);

36


37 /**//** 檢查該文件是否為位圖文件 */

38 if(header.bfType != BITMAP_ID)


39
{


40 fclose(pFile); /**//**< 若不是位圖文件,則關閉文件并返回 */

41 return false;

42 }

43


44 /**//** 讀入位圖文件信息 */

45 fread(&bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, pFile);

46


47 /**//** 保存圖像的寬度和高度 */

48 imageWidth = bitmapInfoHeader.biWidth;

49 imageHeight = bitmapInfoHeader.biHeight;

50


51 /**//** 確保讀取數據的大小 */

52 if(bitmapInfoHeader.biSizeImage == 0)

53 bitmapInfoHeader.biSizeImage = bitmapInfoHeader.biWidth *

54 bitmapInfoHeader.biHeight * 3;

55


56 /**//** 將指針移到數據開始位置 */

57 fseek(pFile, header.bfOffBits, SEEK_SET);

58


59 /**//** 分配內存 */

60 image = new unsigned char[bitmapInfoHeader.biSizeImage];

61


62 /**//** 檢查內存分配是否成功 */


63 if(!image) /**//**< 若分配內存失敗則返回 */


64
{

65 delete[] image;

66 fclose(pFile);

67 return false;

68 }

69


70 /**//** 讀取圖像數據 */

71 fread(image, 1, bitmapInfoHeader.biSizeImage, pFile);

72


73 /**//** 將圖像顏色數據格式進行交換,由BGR轉換為RGB */

74 for(int index = 0; index < (int)bitmapInfoHeader.biSizeImage; index+=3)


75
{

76 textureColors = image[index];

77 image[index] = image[index + 2];

78 image[index + 2] = textureColors;

79 }

80


81 fclose(pFile); /**//**< 關閉文件 */


82 return true; /**//**< 成功返回 */

83 }

代碼Image.rar
源代碼下載
posted on 2010-05-28 14:14
風輕云淡 閱讀(1299)
評論(0) 編輯 收藏 引用 所屬分類:
圖像讀取