如何在 C 中读取 BMP 文件?
How to read BMP file in C?
我正在查询BMP的基本信息。为此,我为文件头构建了一个结构,为图像头构建了另一个结构。参考一个 BMP table 的值(http://www.dragonwins.com/domains/getteched/bmp/bmpfileformat.htm),我读取了值并按照指定进行了验证。但是只有bfType读对了,其他值都填错了信息。 在我的电脑上,sizeof(int) = 4
结构:
typedef struct BmpFileHeader {
char bfType[2];
unsigned int bfSize;
unsigned short int __bfReserved1;
unsigned short int __bfReserved2;
unsigned long int bfOffBits;
} BMPFILEHEADER;
typedef struct BmpImageHeader {
unsigned int biSize;
int biWidth;
int biHeight;
unsigned short int biPlanes;
unsigned short int biBitCount;
unsigned int biCompression;
unsigned int biSizeImage;
int biXPelsPerMeter;
int biYPelPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
} BMPIMAGEHEADER;
打印函数:
void printFileHeader(BMPFILEHEADER fileHeader) {
printf("\nType: %c%c.\n", fileHeader.bfType[0],fileHeader.bfType[1]);
printf("Size: %d.\n", fileHeader.bfSize);
printf("Verify (Must be 0 0): %d %d.\n");
printf("Offset : %d.\n", fileHeader.bfOffBits);
};
void printImageHeader(BMPIMAGEHEADER imageHeader) {
printf("\nSize of header: %d.\n", imageHeader.biSize);
printf("Width: %d.\n", imageHeader.biWidth);
printf("Height: %d.\n", imageHeader.biHeight);
printf("Color Planes: %d.\n", imageHeader.biPlanes);
printf("Bits per Pixel: %d.\n", imageHeader.biBitCount);
printf("Compression: %d.\n", imageHeader.biCompression);
printf("Image size: %d.\n", imageHeader.biSizeImage);
printf("Preferred resolution in pixels per meter (X-Y): %d-%d.\n", imageHeader.biXPelsPerMeter, imageHeader.biYPelPerMeter);
printf("Number color map: %d.\n", imageHeader.biClrUsed);
printf("Number of significant colors: %d.\n", imageHeader.biClrImportant);
}
主要功能:
int main() {
FILE *image;
BMPFILEHEADER header;
BMPIMAGEHEADER imageHeader;
image = fopen("test.bmp", "rb");
if(!image) {
printf("Could not open the file %s.", "test.bmp");
fclose(image);
return 1;
}
fread(&header, sizeof(BMPFILEHEADER), 1,image);
printf("File header information:");
printFileHeader(header);
if(header.bfType[0] != 'B' || header.bfType[1] != 'M') {
printf("The file %s is not a valid BMP.", "test.bmp");
return 1;
}
fread(&imageHeader, sizeof(BMPIMAGEHEADER), 1, image);
printf("\nImage header information:");
printImageHeader(imageHeader);
if(imageHeader.biSize != 40 || imageHeader.biCompression != 0 || imageHeader.biBitCount != 24) {
printf("The file %s is not a valid BMP.", "test.bmp");
fclose(image);
return 1;
}
fclose(image);
return 0;
}
结构打包和对齐填充是实现定义的,字节顺序是平台定义的。
如果您平台的字节顺序与为 BMP (little-endian) 定义的字节顺序相同,那么您可以使用您的工具链支持的任何编译器扩展来进行结构打包。例如在 GCC 中:
typedef struct BmpFileHeader {
char bfType[2];
unsigned int bfSize;
unsigned short int __bfReserved1;
unsigned short int __bfReserved2;
unsigned long int bfOffBits;
} __attribute__ ((packed)) BMPFILEHEADER;
typedef struct BmpImageHeader {
unsigned int biSize;
int biWidth;
int biHeight;
unsigned short int biPlanes;
unsigned short int biBitCount;
unsigned int biCompression;
unsigned int biSizeImage;
int biXPelsPerMeter;
int biYPelPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
} __attribute__ ((packed)) BMPIMAGEHEADER;
对于整数值,BMP 的字节顺序是 little-endian;所以对于 x86 和大多数 ARM 平台,你可能不需要担心 byte-order。像素字节顺序有点不那么直接。
然而,对于真正可移植的解决方案,您必须读取数据 byte-by-byte 并单独加载结构的每个成员 - 所谓的 反序列化.
您还可以通过使用 stdint.h
数据类型 uint8_t
、uint16_t
、uint32_t
、[= 来确保符合 header 结构15=]等
我正在查询BMP的基本信息。为此,我为文件头构建了一个结构,为图像头构建了另一个结构。参考一个 BMP table 的值(http://www.dragonwins.com/domains/getteched/bmp/bmpfileformat.htm),我读取了值并按照指定进行了验证。但是只有bfType读对了,其他值都填错了信息。 在我的电脑上,sizeof(int) = 4
结构:
typedef struct BmpFileHeader {
char bfType[2];
unsigned int bfSize;
unsigned short int __bfReserved1;
unsigned short int __bfReserved2;
unsigned long int bfOffBits;
} BMPFILEHEADER;
typedef struct BmpImageHeader {
unsigned int biSize;
int biWidth;
int biHeight;
unsigned short int biPlanes;
unsigned short int biBitCount;
unsigned int biCompression;
unsigned int biSizeImage;
int biXPelsPerMeter;
int biYPelPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
} BMPIMAGEHEADER;
打印函数:
void printFileHeader(BMPFILEHEADER fileHeader) {
printf("\nType: %c%c.\n", fileHeader.bfType[0],fileHeader.bfType[1]);
printf("Size: %d.\n", fileHeader.bfSize);
printf("Verify (Must be 0 0): %d %d.\n");
printf("Offset : %d.\n", fileHeader.bfOffBits);
};
void printImageHeader(BMPIMAGEHEADER imageHeader) {
printf("\nSize of header: %d.\n", imageHeader.biSize);
printf("Width: %d.\n", imageHeader.biWidth);
printf("Height: %d.\n", imageHeader.biHeight);
printf("Color Planes: %d.\n", imageHeader.biPlanes);
printf("Bits per Pixel: %d.\n", imageHeader.biBitCount);
printf("Compression: %d.\n", imageHeader.biCompression);
printf("Image size: %d.\n", imageHeader.biSizeImage);
printf("Preferred resolution in pixels per meter (X-Y): %d-%d.\n", imageHeader.biXPelsPerMeter, imageHeader.biYPelPerMeter);
printf("Number color map: %d.\n", imageHeader.biClrUsed);
printf("Number of significant colors: %d.\n", imageHeader.biClrImportant);
}
主要功能:
int main() {
FILE *image;
BMPFILEHEADER header;
BMPIMAGEHEADER imageHeader;
image = fopen("test.bmp", "rb");
if(!image) {
printf("Could not open the file %s.", "test.bmp");
fclose(image);
return 1;
}
fread(&header, sizeof(BMPFILEHEADER), 1,image);
printf("File header information:");
printFileHeader(header);
if(header.bfType[0] != 'B' || header.bfType[1] != 'M') {
printf("The file %s is not a valid BMP.", "test.bmp");
return 1;
}
fread(&imageHeader, sizeof(BMPIMAGEHEADER), 1, image);
printf("\nImage header information:");
printImageHeader(imageHeader);
if(imageHeader.biSize != 40 || imageHeader.biCompression != 0 || imageHeader.biBitCount != 24) {
printf("The file %s is not a valid BMP.", "test.bmp");
fclose(image);
return 1;
}
fclose(image);
return 0;
}
结构打包和对齐填充是实现定义的,字节顺序是平台定义的。
如果您平台的字节顺序与为 BMP (little-endian) 定义的字节顺序相同,那么您可以使用您的工具链支持的任何编译器扩展来进行结构打包。例如在 GCC 中:
typedef struct BmpFileHeader {
char bfType[2];
unsigned int bfSize;
unsigned short int __bfReserved1;
unsigned short int __bfReserved2;
unsigned long int bfOffBits;
} __attribute__ ((packed)) BMPFILEHEADER;
typedef struct BmpImageHeader {
unsigned int biSize;
int biWidth;
int biHeight;
unsigned short int biPlanes;
unsigned short int biBitCount;
unsigned int biCompression;
unsigned int biSizeImage;
int biXPelsPerMeter;
int biYPelPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
} __attribute__ ((packed)) BMPIMAGEHEADER;
对于整数值,BMP 的字节顺序是 little-endian;所以对于 x86 和大多数 ARM 平台,你可能不需要担心 byte-order。像素字节顺序有点不那么直接。
然而,对于真正可移植的解决方案,您必须读取数据 byte-by-byte 并单独加载结构的每个成员 - 所谓的 反序列化.
您还可以通过使用 stdint.h
数据类型 uint8_t
、uint16_t
、uint32_t
、[= 来确保符合 header 结构15=]等