//BMP 头
typedef struct
{
char id[2]; //bmp 文件标志 "BM"
unsigned long fileSize; //文件大小
unsigned long reserved0;
unsigned long bitmapDataOffset;
unsigned long bitmapHeaderSize;
unsigned long width; //图像宽度
unsigned long height; //图像高度
unsigned short planes;
unsigned short bitsPerPixel; //每个像素站多少位
unsigned long compression; //是否压缩
unsigned long bitmapDataSize;
unsigned long hRes;
unsigned long vRes;
unsigned long colors;
unsigned long importantColors;
unsigned char palette[256][4]; //调色板数据,24位及以上像素没有该数据
} BMPHeader_t;
long GetFileSize(FILE* f)
{
long pos = ftell(f);
fseek(f,0,SEEK_END);
long len = ftell(f);
fseek(f,pos,SEEK_SET);
return len;
}
void __stdcall Com_Error(const char *fmt, ... )
{
char com_errorMessage[4096];
va_list argptr;
va_start (argptr,fmt);
vsprintf (com_errorMessage,fmt,argptr);
va_end (argptr);
MessageBox(NULL,com_errorMessage,"错误提示",MB_ICONERROR);
}
//*pic 返回 RGBA 类型像素数据,width 返回修正后的宽度,height返回高度
// name 输入的文件名称
bool LoadBMP( const char *name, byte **pic, int *width, int *height )
{
int columns, rows, numPixels;
byte *pixbuf;
int row, column;
byte *buf_p;
byte *buffer;
int length;
BMPHeader_t bmpHeader;
byte *bmpRGBA;
*pic = NULL;
// load the file
FILE* pfile = fopen(name,"rb");
if(pfile == NULL)
{
Com_Error( "LoadBMP: Load BMP files failed (%s)/n", name );
return false;
}
length = GetFileSize(pfile);
buffer = (byte*) malloc(length*sizeof(byte));
fread(buffer,1,length,pfile);
if (!buffer)
{
Com_Error( "LoadBMP: Memory alloc failed (%s)/n", name );
return false;
}
buf_p = buffer;
bmpHeader.id[0] = *buf_p++;
bmpHeader.id[1] = *buf_p++;
bmpHeader.fileSize = ( * ( long * ) buf_p );
buf_p += 4;
bmpHeader.reserved0 = ( * ( long * ) buf_p );
buf_p += 4;
bmpHeader.bitmapDataOffset = ( * ( long * ) buf_p );
buf_p += 4;
bmpHeader.bitmapHeaderSize = ( * ( long * ) buf_p );
buf_p += 4;
bmpHeader.width = ( * ( long * ) buf_p );
buf_p += 4;
bmpHeader.height = ( * ( long * ) buf_p );
buf_p += 4;
bmpHeader.planes = ( * ( short * ) buf_p );
buf_p += 2;
bmpHeader.bitsPerPixel = ( * ( short * ) buf_p );
buf_p += 2;
bmpHeader.compression = ( * ( long * ) buf_p );
buf_p += 4;
bmpHeader.bitmapDataSize = ( * ( long * ) buf_p );
buf_p += 4;
bmpHeader.hRes = ( * ( long * ) buf_p );
buf_p += 4;
bmpHeader.vRes = ( * ( long * ) buf_p );
buf_p += 4;
bmpHeader.colors = ( * ( long * ) buf_p );
buf_p += 4;
bmpHeader.importantColors = ( * ( long * ) buf_p );
buf_p += 4;
memcpy( bmpHeader.palette, buf_p, sizeof( bmpHeader.palette ) );
if ( bmpHeader.bitsPerPixel == 8 )
buf_p += 1024;
if ( bmpHeader.id[0] != 'B' && bmpHeader.id[1] != 'M' )
{
Com_Error( "LoadBMP: only Windows-style BMP files supported (%s)/n", name );
return false;
}
if ( bmpHeader.fileSize != length )
{
Com_Error("LoadBMP: header size does not match file size (%d vs. %d) (%s)/n", bmpHeader.fileSize, length, name );
return false;
}
if ( bmpHeader.compression != 0 )
{
Com_Error("LoadBMP: only uncompressed BMP files supported (%s)/n", name );
return false;
}
if ( bmpHeader.bitsPerPixel < 8 )
{
Com_Error("LoadBMP: monochrome and 4-bit BMP files not supported (%s)/n", name );
return false;
}
columns = bmpHeader.width;
rows = bmpHeader.height;
if(bmpHeader.bitsPerPixel == 24 )
{
if( (columns & 3) != 0) //检查宽度是否为4倍数
columns = (columns & ~3) + 4; //修正位图宽度值,对齐到4的倍数,不然图像会变形
}
if ( rows < 0 )
rows = -rows;
numPixels = columns * rows;
if ( width )
*width = columns;
if ( height )
*height = rows;
bmpRGBA = (byte*)malloc( numPixels * 4 );
*pic = bmpRGBA;
buf_p = buffer+54;
for ( row = rows-1; row >= 0; row--)
{
pixbuf = bmpRGBA + row*columns*4;
for ( column = 0; column < columns; column++ )
{
unsigned char red, green, blue, alpha;
int palIndex;
unsigned short shortPixel;
switch ( bmpHeader.bitsPerPixel )
{
case 8:
palIndex = *buf_p++;
*pixbuf++ = bmpHeader.palette[palIndex][2];
*pixbuf++ = bmpHeader.palette[palIndex][1];
*pixbuf++ = bmpHeader.palette[palIndex][0];
*pixbuf++ = 0xff;
break;
case 16:
shortPixel = * ( unsigned short * ) pixbuf;
pixbuf += 2;
*pixbuf++ = ( shortPixel & ( 31 << 10 ) ) >> 7;
*pixbuf++ = ( shortPixel & ( 31 << 5 ) ) >> 2;
*pixbuf++ = ( shortPixel & ( 31 ) ) << 3;
*pixbuf++ = 0xff;
break;
case 24:
blue = *buf_p++;
green = *buf_p++;
red = *buf_p++;
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = 255;
break;
case 32:
blue = *buf_p++;
green = *buf_p++;
red = *buf_p++;
alpha = *buf_p++;
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alpha;
break;
default:
Com_Error("LoadBMP: illegal pixel_size '%d' in file '%s'/n", bmpHeader.bitsPerPixel, name );
return false;
}
}
}
free(buffer);
fclose(pfile);
return true;
}
//注意bmp文件是由左到右, 由下到上的循序存储的像素.每个像素颜色顺序为B G R (A)
//BMP的行象素是4字节对齐的,不足的补0,比如有个图像每行宽度是63象素,
//BMP文件存储时会每行存储64个字节,最后一个字节用0补齐
void CDlg::OnPaint() //测试图像
{
CPaintDC dc(this);
static byte* pic = NULL;
static int w,h;
if(pic == NULL)
{
char spath[MAX_PATH];
_getcwd(spath, 200);
strcat(spath,"//res//b0000.bmp");
LoadBMP(spath,&pic,&w,&h);
}
int i,j;
for(j=0;j
for(i=0;i
SetPixel(dc,i,j,RGB(pic[0],pic[1],pic[2]));
pic += 4;
}
}
}