我正在尝试读取BMP文件的标题,然后显示它的内容。
struct BMP *bmp;
bmp = (struct BMP*)malloc(sizeof(struct BMP));
if(bmp)
{
fread(bmp,sizeof(struct BMP),1,bmpFile); //This does not work for me
//Then we display the contents
printf("#######CABECALHO DE UM ARQUIVO .BMP (BITMAP)#########\n");
printf("\n");
printf("Tipo de Arquivo (2 bytes): %c%c\n", bmp->id[0],bmp->id[1]);
printf("Tamanho do arquivo (4 bytes): %d Kb\n",bmp->filesize/1024);
printf("Reservado1 (2 bytes): %x\n",bmp->reserved[0]);
printf("Reservado2 (2 bytes): %x\n",bmp->reserved[1]);
printf("Tamanho do Cabecalho BMP: %d\n",bmp->headersize);
printf("Tamanho do Info Header (4 bytes): %d\n", bmp->infosize);
printf("Largura: (4 bytes): %d\n", bmp->width);
printf("Altura: (4 bytes): %d\n", bmp->height);
printf("Plane: (2 bytes): %x\n", bmp->plane);
printf("Bits por Pixel: (2 bytes): %x\n", bmp->bits);
printf("Compressao: (4 bytes): %d\n", bmp->compression);
printf("Tamanho da Imagem: (4 bytes): %d\n", bmp->imagesize/1024);
printf("X: (4 bytes): %d\n", bmp->x);
printf("Y: (4 bytes): %d\n", bmp->y);
printf("Nro de Cores : (4 bytes): %d\n", bmp->clrUsed);
printf("Nro de Cores Importantes : (4 bytes): %d\n", bmp->clrImportant);
printf("\n");
printf("#######FIM DO CABECALHO TOTAL DE 50 BYTES#########");
}
然而,它向我显示的唯一准确信息是前2个字节,其他所有值都不正确。
如果不是阅读整个结构
struct fread(bmp,sizeof(struct BMP),1,bmpFile);
我一次读取每个元素
fread(&bmp->id[0],sizeof(char),1,bmpFile);
fread(&bmp->id[1],sizeof(char),1,bmpFile);
fread(&bmp->filesize,sizeof(int),1,bmpFile);
fread(&bmp->reserved[0],sizeof(short),1,bmpFile);
fread(&bmp->reserved[1],sizeof(short),1,bmpFile);
fread(&bmp->headersize,sizeof(int),1,bmpFile);
fread(&bmp->infosize,sizeof(int),1,bmpFile);
fread(&bmp->width,sizeof(int),1,bmpFile);
fread(&bmp->height,sizeof(int),1,bmpFile);
fread(&bmp->plane,sizeof(short),1,bmpFile);
fread(&bmp->bits,sizeof(short),1,bmpFile);
fread(&bmp->compression,sizeof(int),1,bmpFile);
fread(&bmp->imagesize,sizeof(int),1,bmpFile);
fread(&bmp->x,sizeof(int),1,bmpFile);
fread(&bmp->y,sizeof(int),1,bmpFile);
fread(&bmp->clrUsed,sizeof(int),1,bmpFile);
fread(&bmp->clrImportant,sizeof(int),1,bmpFile);
然后所有值都正确显示... 所以我的问题是,当我一次读完整个结构时,为什么会发生不同的事情。
答案 0 :(得分:3)
可能是因为结构中存在内部填充,原始尝试是一种使用结构进行二进制I / O的非常糟糕且不安全的方法。
最好将众所周知的 bytes 加载到字节缓冲区中,然后解码每个字段并将其复制到内存中的结构中。
答案 1 :(得分:2)
问题出在你的结构BMP中,为什么不使用现成的定义,例如WinGDI.h中的那个
#pragma pack(push,1)
typedef struct tagBITMAPINFOHEADER{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;
#pragma pack(pop)
答案 2 :(得分:1)
那是因为结构是填充的。这意味着结构的大小将不等于结构的每个单独元素的大小的总和。这样做是为了align the bytes以提高效果。
C11 standard的第6.2.6.1节说:
当值存储在结构或联合类型的对象中时,包括在成员中 object,对象表示的字节,对应于任何填充字节 未具体的价值观。
简而言之,结构的填充是未指定的行为。这意味着任何实现都可以做任何想做的事情,而无需记录它。
答案 3 :(得分:0)
如果你想让它工作,即使你认为读取整个结构是不正确的,在定义你的结构时你应该非常小心,以便完全控制打击垫。
你的结构应该看起来像这样(如果你有32位平台)。
struct BMP
{
unsigned char id[];
unsigned short filesize_1;
/* here we need to control the pads to make sure it will fit to our platform.
/ also, the order of msb and lsb may change according to the platform. */
unsigned short filesize_2; // Now start a new int.
...
}
以后需要操纵数据才能获得正确的值。
但请记住,这是平台依赖的,通常不值得痛苦。