读取BMP主要分为读取
1. //位图文件头
BITMAPFILEHEADER header;
2.. //位图信息头
BITMAPINFOHEADER info;
3.读取数据
BMP的数据格式是BGR,所以我们要转换为RGB格式,同时注意,BMP图像中存储的数据是从左下角开始存储的,到右上角结束,也就是最后一行是正常的第一行,倒是第二行是正常的第二行...
我们可以根据这些作出一些效果,比如翻转etc.
//图像倒转
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
for( int height = texture->height - 1; height >= 0 ; height-- )
{
GLubyte* pdest = texture->imageData + height * texture->width * channel;
fread( pdest, 1, texture->width * channel,file );
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for( int i = 0; i < texture->width* channel; i+=channel )
{
pdest[ i ] ^= pdest[i+2] ^= pdest[i] ^= pdest[i+2];
}
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
//正常图像
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
for( int h = 0; h < (int)texture->height; h++ )
{
GLubyte* pdest = texture->imageData + h * texture->width * channel;
fread( pdest, 1, texture->width * channel,file );
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
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)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
case 1:
case 2:
case 4:
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
for(i=0;i<pxcnt;i++)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
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:
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
for(i=0;i<pxcnt;i++)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
DWORD px=bits[i];//取得某一个位置的像素
if(px<infoheader->biClrUsed)//出于安全问题,限制色彩范围。
pixels[i]=palette[px];
else
pixels[i]=undefinedQuad;//超出调色板范围,
}
}
break;
case 16:
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//16位增强色
//一般是RGB各5bit
WORD* pxwd=(WORD*)bits;
for(i=0;i<pxcnt;i++)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
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:
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//将三个字节的数据扩展为4字节的
for(i=0;i<pxcnt;i++)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
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
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
//如果没有调色板,则直接使用文件内的区域。
fread(pixels,1,infoheader->biSizeImage,file);
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
//Image.h
typedef struct _tTexImage
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
GLubyte* imageData;
GLuint width;
GLuint height;
GLuint bpp; //Image color depth in bits per pixel
GLuint texID;
GLuint imageType;
GLboolean bCompressed; //Compressed or Uncompressed
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
_tTexImage():imageData(NULL),texID(-1)
{}
}TexImage;
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#pragma pack( pop )
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
class Image
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
public:
Image(void);
~Image(void);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
public:
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//** 加载TGA图片 **/
BOOL loadTGA( TexImage* texture, LPCSTR filename );
static BOOL release( TexImage* texture );
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//** 生成纹理 **/
void generateTexture( TexImage* texture, BOOL bMipmap = TRUE );
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
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 )
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif)
{
FILE* file = fopen( fileName, "rb" );
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if ( !file )
{
TRACE("Open file %s failed!\n", fileName );
return FALSE;
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
//位图文件头
BITMAPFILEHEADER header;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if ( sizeof(BITMAPFILEHEADER) != fread( &header, 1, sizeof(BITMAPFILEHEADER), file ) )
{
TRACE("Read bmp header failed!\n");
return FALSE;
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
//检查头结构体 "BM" 即0x4D42
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if ( header.bfType != 0x4D42 )
{
return FALSE;
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
//位图信息头
BITMAPINFOHEADER info;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
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;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//** 将指针移到数据开始位置 */
fseek( file, header.bfOffBits, SEEK_SET );
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
switch( texture->bpp )
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
case 24:
case 32:
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
int channel= 0;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if ( texture->bpp == 24 )
{
channel = 3;
texture->imageType = GL_RGB;
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
}else
{
channel = 4;
texture->imageType = GL_RGBA;
}
texture->imageData = new GLubyte[ texture->width * texture->height * channel ];
//图像倒转
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for( int height = texture->height - 1; height >= 0 ; height-- )
{
GLubyte* pdest = texture->imageData + height * texture->width * channel;
fread( pdest, 1, texture->width * channel,file );
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for( int i = 0; i < texture->width* channel; i+=channel )
{
pdest[ i ] ^= pdest[i+2] ^= pdest[i] ^= pdest[i+2];
}
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
//正常图像
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for( int h = 0; h < (int)texture->height; h++ )
{
GLubyte* pdest = texture->imageData + h * texture->width * channel;
fread( pdest, 1, texture->width * channel,file );
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for( int i = 0; i < texture->width* channel; i+=channel )
{
pdest[ i ] ^= pdest[i+2] ^= pdest[i] ^= pdest[i+2]; //将BGR转为RGB,BMP数据从左下角到右上角的方式存储
}
}
}
break;
}
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
return TRUE;
}
...
别人写的一个BMP加载的代码,大同小异。
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
/**//** 装载一个位图文件 */
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
19 bool CBMPLoader::LoadBitmap(const char *file)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
20
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
21 FILE *pFile = 0; /**//**< 文件指针 */
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
22
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
23 /**//** 创建位图文件信息和位图文件头结构 */
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
24 BITMAPINFOHEADER bitmapInfoHeader;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
25 BITMAPFILEHEADER header;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
26
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
27 unsigned char textureColors = 0;/**//**< 用于将图像颜色从BGR变换到RGB */
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
28
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
29 /**//** 打开文件,并检查错误 */
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
30 pFile = fopen(file, "rb");
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
31 if(pFile == 0)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
32 return false;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
33
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
34 /**//** 读入位图文件头信息 */
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
35 fread(&header, sizeof(BITMAPFILEHEADER), 1, pFile);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
36
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
37 /**//** 检查该文件是否为位图文件 */
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
38 if(header.bfType != BITMAP_ID)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
39
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
40 fclose(pFile); /**//**< 若不是位图文件,则关闭文件并返回 */
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
41 return false;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
42 }
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
43
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
44 /**//** 读入位图文件信息 */
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
45 fread(&bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, pFile);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
46
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
47 /**//** 保存图像的宽度和高度 */
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
48 imageWidth = bitmapInfoHeader.biWidth;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
49 imageHeight = bitmapInfoHeader.biHeight;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
50
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
51 /**//** 确保读取数据的大小 */
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
52 if(bitmapInfoHeader.biSizeImage == 0)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
53 bitmapInfoHeader.biSizeImage = bitmapInfoHeader.biWidth *
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
54 bitmapInfoHeader.biHeight * 3;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
55
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
56 /**//** 将指针移到数据开始位置 */
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
57 fseek(pFile, header.bfOffBits, SEEK_SET);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
58
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
59 /**//** 分配内存 */
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
60 image = new unsigned char[bitmapInfoHeader.biSizeImage];
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
61
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
62 /**//** 检查内存分配是否成功 */
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
63 if(!image) /**//**< 若分配内存失败则返回 */
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
64
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
65 delete[] image;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
66 fclose(pFile);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
67 return false;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
68 }
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
69
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
70 /**//** 读取图像数据 */
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
71 fread(image, 1, bitmapInfoHeader.biSizeImage, pFile);
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
72
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
73 /**//** 将图像颜色数据格式进行交换,由BGR转换为RGB */
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
74 for(int index = 0; index < (int)bitmapInfoHeader.biSizeImage; index+=3)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
75
{
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
76 textureColors = image[index];
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
77 image[index] = image[index + 2];
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
78 image[index + 2] = textureColors;
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
79 }
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
80
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
81 fclose(pFile); /**//**< 关闭文件 */
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
82 return true; /**//**< 成功返回 */
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
83 }
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
代码Image.rar
源代码下载
posted on 2010-05-28 14:14
风轻云淡 阅读(1272)
评论(0) 编辑 收藏 引用 所属分类:
图像读取