背景:
读取BMP文件的数据,并将数据存储到申请到的data buffer中。
问题:
BMP格式中的biSizeImage 字段指示后面的data的总长度,只需要按照这个长度读取data 就可以了;但是读取的图片始终是少一部分;如下图;
程序代码:
typedef unsigned long DWORD; // 四个字节
typedef int BOOL;
typedef unsigned char BYTE; // 一个字节
typedef unsigned short WORD; // 一个字节
// 位图信息头结构体定义
typedef struct tagBITMAPINFOHEADER
{
WORD bfType; // 两个字节
DWORD bfileSize;
DWORD bfReserved;
DWORD bOffBits;
DWORD biSize; // 4个字节
long biWidth; // 4个字节
long biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
long biXPelsPerMeter;
long biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} __attribute__((packed)) BITMAPINFOHEADER, *PBITMAPINFOHEADER; // 字节对齐
typedef struct
{
BITMAPINFOHEADER header; // 信息头
char *data; // 图像数据
} bmp_t;
int main(void)
{
char *InputName, *OutputName; // 输入输出图像文件名变量
FILE *InputFile, *OutputFile; // 输入输出图像文件
bmp_t *bmp = NULL, *blur = NULL;
InputName = "test06.bmp";
OutputName = "output.bmp";
if (!(InputFile = fopen(InputName, "b"))) // 图像文件打开函数,打不开返回,提示找不到文件
{
printf("File not found\n");
return 1;
}
bmp = bmp_open(InputFile); // 图像文件读取操作,前面必须有打开的操作才能读取文件数据
fclose(InputFile); // 关闭文件
... ...
};
bmp_t *bmp_open(FILE *f)
{
bmp_t *bmp;
bmp = (bmp_t *)malloc(sizeof(bmp_t));
bmp->data = NULL;
size_t num = 0;
if (num = fread(&(bmp->header), sizeof(BITMAPINFOHEADER), 1, f))
{
bmp->data = (char *)malloc(bmp->header.biSizeImage + 54 );
memset(bmp->data, 0, bmp->header.biSizeImage);
//lseek(f,0,SEEK_SET);
num = fread(bmp->data, bmp->header.biSizeImage, 1, f);// 问题:始终没有读取到指定长度的数据
if (feof(f))
{
printf("文件已到达末尾。\n");
}
else if (ferror(f))
{
printf("读取错误发生。\n");
// 清除错误状态
clearerr(f);
}
else if (num == 0 && !feof(f))
{
printf("未知错误, fread返回0。\n");
}
if (num)
printf("\n图像读取成功\n");
printf("===> num %d\n", num); // 问题: num 一直返回为0!!!!!
printf("sizeof(BITMAPINFOHEADER) %d\n", sizeof(BITMAPINFOHEADER));
printf("Width: %ld\n", bmp->header.biWidth);
printf("Height: %ld\n", bmp->header.biHeight);
printf("BitCount: %d\n\n", (int)bmp->header.biBitCount);
printf("biSizeImage: %x\n\n", (int)bmp->header.biSizeImage);
return bmp;
}
fprintf(stderr, "Error reading file");
bmp_free(bmp);
return NULL;
}
原因:
文件的打开是以“r” 的模式打开,需要以“rb” 模式打开二进制文件。
if (!(InputFile = fopen(InputName, "rb"))) // 图像文件打开函数,打不开返回,提示找不到文件
{
printf("File not found\n");
return 1;
}
注意事项:
为啥我读取长度没有达到文件data的长度,图片的上半部分会出现数据缺失问题,而不是下半部分出现缺失?原因是BMP格式的文件是从左往右,从下到上扫描的,所以data offset比较小的地方数据是存在图片的下半部分。