帮忙看一下这个小程序。
#include "stdio.h "
#include "conio.h "
#include "stdlib.h "
void main()
{
/* BMP文件头 */
typedef struct
{
unsigned short bfType; /* 文件类型 */
unsigned long bfSize; /* 文件大小 */
unsigned short bfReserved1; /* 保留位 */
unsigned short bfReserved2; /* 保留位 */
unsigned long bfOffBits; /* 数据偏移位置 */
} HEAD;
/* BMP信息头 */
typedef struct
{
unsigned long biSize; /* 此结构大小 */
long biWidth; /* 图像宽度 */
long biHeight; /* 图像高度 */
unsigned short biPlanes; /* 调色板数量 */
unsigned short biBitCount; /* 每个象素对应的位数,24:24位图,32:带alpha通道的24位图 */
unsigned long biCompression; /* 压缩 */
unsigned long biSizeImage; /* 图像大小 */
long biXPelsPerMeter;/* 横向分辨率 */
long biYPelsPerMeter;/* 纵向分辨率 */
unsigned long biClrUsed; /* 颜色使用数 */
unsigned long biClrImportant; /* 重要颜色数 */
}BMPINFOHEADER;
FILE *file ;
HEAD bmpFile;
BMPINFOHEADER bmpInfo;
/* 打开文件 */
file = fopen( "LENNA.BMP ", "rb ");
if (file== NULL)
{
printf( " openning error\n ");
}
/* 读入文件头 */
fread(&bmpFile, sizeof(HEAD)-2,1, file);
if (bmpFile.bfType != 0x4D42)
{
printf( " reading error!!! ");
}
printf( "%x\n ",bmpFile.bfType); /* 验证文件类型 */
printf( "%ld\n ",bmpFile.bfSize);
printf( "%ld\n ",bmpFile.bfOffBits);
/* 读信息头 */
fread(&bmpInfo, sizeof(BMPINFOHEADER), 1, file);
printf( "%ld\n ",bmpInfo.biSizeImage);
printf( "%d\n ",bmpInfo.biWidth);
printf( "%d\n ",bmpInfo.biHeight);
printf( "%d\n ",bmpInfo.biBitCount);
}
就是读一个位图的信息,我读的是一个512*512的灰度图象。
结果是:
4d42
4
-859045888
0
512
512
8
printf( "%ld\n ",bmpFile.bfSize);
printf( "%ld\n ",bmpFile.bfOffBits);
printf( "%ld\n ",bmpInfo.biSizeImage);
这三个怎么读的数据不对啊??是什么原因?
[解决办法]
编译器一般会对结构成员进行对齐,所以你定义的结构大小不一定正好和bmp文件头的结构大小一致,导致读文件错位。
不信你可以试试输出sizeof(HEAD),肯定不等于14个字节(bmp头14个字节是文件头)
你可以通过强制编译器按字节对齐来解决这个问题。
#pragma pack(1)
[解决办法]
你知道编译器对HEAD是怎么对齐的吗?
如果按4字节对齐
typedef struct
{
unsigned short bfType; // 4个字节
unsigned long bfSize; // 4个字节
unsigned short bfReserved1; // 下面两个short合成一个4字节
unsigned short bfReserved2;
unsigned long bfOffBits; // 4个字节
} HEAD;
你即使sizeof(HEAD)-2也没用,bfSize本来就和文件里数据错位啦,后面都错位啦
你为什么就不试试
#pragma pack(1)
呢
[解决办法]
程序要有移植性,可以这样写你的程序:
#include "stdio.h "
#include "conio.h "
#include "stdlib.h "
/* BMP文件头 */
typedef struct
{
unsigned short bfType; /* 文件类型 */
unsigned long bfSize; /* 文件大小 */
unsigned short bfReserved1; /* 保留位 */
unsigned short bfReserved2; /* 保留位 */
unsigned long bfOffBits; /* 数据偏移位置 */
} HEAD;
/* BMP信息头 */
typedef struct
{
unsigned long biSize; /* 此结构大小 */
long biWidth; /* 图像宽度 */
long biHeight; /* 图像高度 */
unsigned short biPlanes; /* 调色板数量 */
unsigned short biBitCount; /* 每个象素对应的位数,24:24位图,32:带alpha通道的24位图 */
unsigned long biCompression; /* 压缩 */
unsigned long biSizeImage; /* 图像大小 */
long biXPelsPerMeter;/* 横向分辨率 */
long biYPelsPerMeter;/* 纵向分辨率 */
unsigned long biClrUsed; /* 颜色使用数 */
unsigned long biClrImportant; /* 重要颜色数 */
}BMPINFOHEADER;
int readChar( FILE *f ) {
unsigned char ch;
if( fread( &ch, 1, 1, f ) != 1 )
return -1;
int r = ch;
return r & 0x0ff;
}
int readInt16( FILE *f ) {
int b_1 = readChar( f );
int b_2 = readChar( f );
if( b_2 < 0 ) return -1;
return b_2 < < 8 | b_1;
}
int readInt32( FILE *f ) {
int b_1 = readChar( f );
int b_2 = readChar( f );
int b_3 = readChar( f );
int b_4 = readChar( f );
if( b_4 < 0 ) {
printf( "error ");
exit( -1 );
return -1;
}
return (b_4 < < 24) | (b_3 < < 16) | (b_2 < < 8) | b_1;
}
void readHeader(FILE *f, HEAD* pHead ) {
pHead-> bfType = (unsigned short)readInt16( f );
pHead-> bfSize = (unsigned long)readInt32( f );
pHead-> bfReserved1 = (unsigned short)readInt16( f );
pHead-> bfReserved2 = (unsigned short)readInt16( f );
pHead-> bfOffBits = (unsigned long)readInt32( f );
}
void readInfoHeader(FILE *f, BMPINFOHEADER* pHead ) {
pHead-> biSize = (unsigned long)readInt32( f );
pHead-> biWidth = (long)readInt32( f );
pHead-> biHeight = (long)readInt32( f );
pHead-> biPlanes = (unsigned short)readInt16( f );
pHead-> biBitCount = (unsigned short)readInt16( f );
pHead-> biCompression = (unsigned long)readInt32( f );
pHead-> biSizeImage = (unsigned long)readInt32( f );
pHead-> biXPelsPerMeter = (long)readInt32( f );
pHead-> biYPelsPerMeter = (long)readInt32( f );
pHead-> biClrUsed = (unsigned long)readInt32( f );
pHead-> biClrImportant = (unsigned long)readInt32( f );
}
int main( int argc, char** argv )
{
FILE *file ;
HEAD bmpFile;
BMPINFOHEADER bmpInfo;
/* 打开文件 */
file = fopen( argv[1], "rb ");
if (file== NULL)
{
printf( " openning error\n ");
}
/* 读入文件头 */
//fread(&bmpFile, sizeof(HEAD)-2,1, file);
readHeader( file, &bmpFile);
if (bmpFile.bfType != 0x4D42)
{
printf( " reading error!!! ");
}
printf( "%x\n ",bmpFile.bfType); /* 验证文件类型 */
printf( "%ld\n ",bmpFile.bfSize);
printf( "%ld\n ",bmpFile.bfOffBits);
/* 读信息头 */
//fread(&bmpInfo, sizeof(BMPINFOHEADER), 1, file);
readInfoHeader( file, &bmpInfo );
printf( "%ld\n ",bmpInfo.biSizeImage);
printf( "%d\n ",bmpInfo.biWidth);
printf( "%d\n ",bmpInfo.biHeight);
printf( "%d\n ",bmpInfo.biBitCount);
return 0;
}