目录
BMP 文件简介
BMP 文件格式
位图头
位图信息
调色板
位图数据
C 语言代码
获取文件大小
获取文件尺寸
获取文件偏移量
读取文件数据示例
一个问题
完整程序
BMP 文件简介
BMP(全称 Bitmap)是 Windows 操作系统中的标准图像文件格式, 可以分成两类: 设备有向量相关位图 (DDB) 和设备无向量相关位图(DIB), 使用非常广. 它采用位映射存储格式, 除了图像深度可选以外, 不采用其他任何压缩, 因此, BMP 文件所占用的空间很大. BMP 文件的图像深度可选 lbit,4bit,8bit 及 24bit.BMP 文件存储数据时, 图像的扫描方式是按从左到右, 从下到上的顺序. 由于 BMP 文件格式是 Windows 环境中交换与图有关的数据的一种标准, 因此在 Windows 环境中运行的图形图像软件都支持 BMP 图像格式.
BMP 文件格式
BMP 文件主要有四部分组成, 位图头, 位图信息, 调色板, 位图数据.
位图头
保存文件的总体信息
字节 #0-1 保存位图文件的标识符, 用于标识 BMP 和 DIB 文件的魔数, 一般为 0x42 0x4D, 即 ASCII 的 BM. 以下为可能的取值:
BM - Windows 3.1x, 95, NT, ... etc.
- BA - OS/2 struct Bitmap Array
- CI - OS/2 struct Color Icon
- CP - OS/2 const Color Pointer
- IC - OS/2 struct Icon
- PT - OS/2 Pointer
字节 #2-5 使用一个 dword 保存位图文件大小.
字节 #6-9 是保留部分, 留做以后的扩展使用, 对实际的解码格式没有影响.
字节 #10-13 保存位图数据位置的地址偏移, 也就是起始地址.
位图信息
这部分告诉应用程序图像的详细信息, 在屏幕上显示图像将会使用这些信息
字节 #14-17 定义以下用来描述影像的区块 (BitmapInfoHeader) 的大小.
字节 #18-21 保存位图宽度(以像素个数表示).
字节 #22-25 保存位图高度(以像素个数表示).
字节 #26-27 保存所用彩色位面的个数. 不经常使用.
字节 #28-29 保存每个像素的位数, 它是图像的颜色深度. 常用值是 1,4,8(灰阶)和 24(彩色).
字节 #30-33 定义所用的压缩算法. 允许的值是 0,1,2,3,4,5.
0 - 没有压缩(也用 BI_RGB 表示)
1 - 行程长度编码 8 位 / 像素(也用 BI_RLE8 表示)
2 - 行程长度编码 4 位 / 像素(也用 BI_RLE4 表示)
3 - Bit field(也用 BI_BITFIELDS 表示)
4 - JPEG 图像(也用 BI_JPEG 表示)
5 - PNG 图像(也用 BI_PNG 表示)
调色板
暂时不做介绍
位图数据
在典型的 24 位位图下, 一个像素由 24bit, 即 3 个字节 (R\G\B) 组成.
C 语言代码
获取文件大小
- int getBmpFileSize(FILE * fpbmp)
- {
- int size = 0;
- fseek(fpbmp, 2, SEEK_SET);
- fread(&size, sizeof(char), 4, fpbmp);
- return size;
- }
获取文件尺寸
- int getBmpWidth(FILE* fpbmp)
- {
- int width = 0;
- fseek(fpbmp, 18L, SEEK_SET);
- fread(&width, sizeof(char), 4, fpbmp);
- return width;
- }
- int getBmpHeight( FILE* fpbmp )
- {
- int height = 0;
- fseek(fpbmp, 22L, SEEK_SET);
- fread(&height, sizeof(char), 4, fpbmp);
- return height;
- }
获取文件偏移量
- int getOffset(FILE * fpbmp)
- {
- int offset = 0;
- fseek(fpbmp, 10L, SEEK_SET);
- fread(&offset, sizeof(char), 4, fpbmp);
- return offset;
- }
读取文件数据示例
对于一个 3*3 的 BMP 文件, 三行分别是纯色的 RGB 分量
- int readBmpData( FILE* fpbmp )
- {
- int i = 0, j = 0;
- int offset = getOffset(fpbmp);
- int width = getBmpWidth(fpbmp);
- int height = getBmpHeight(fpbmp);
- unsigned char * pix = NULL;
- //one pix have 3 byte data( R G B )
- pix = malloc( 4 * sizeof( unsigned char ) );
- fseek(fpbmp, offset, SEEK_SET); // Jump to data part
- for( i = 0; i <height; i++ )
- {
- for( j = 0; j < width; j++ )
- {
- fread(pix, 3, 1, fpbmp);
- printf("(=,=,=)",pix[0],pix[1],pix[2]);
- }
- /*printf(",");
- for(;(j)%4!=0;j++)
- {
- fread(pix, 3, 1, fpbmp);
- printf("(=,=,=)",pix[0],pix[1],pix[2]);
- }*/
- printf("\n");
- }
- return 0;
- }
一个问题
等等, 头部 54 字节, 图像 9 个像素 = 27 字节, 加起来一共 81 字节, 可是文件有 90 字节啊! 剩下的 4 个字节呢?
不妨把注释部分取消注释试一下!
原来, Windows 里每行不足 4 字节的整数倍, 会自动补 0! 所以三行多出了 3 个像素 = 9 字节
完整程序
- #include <stdio.h>
- int getBmpWidth(FILE* fpbmp);
- int getBmpHeight( FILE* fpbmp );
- int getBmpFileSize(FILE * fpbmp);
- int getBmpPixBits(FILE * fpbmp);
- int getOffset(FILE * fpbmp);
- int readBmpData( FILE* fpbmp );
- int main()
- {
- FILE * fp_read ;
- fp_read = fopen("test.bmp","rb");
- if(fp_read == NULL)
- {
- printf("文件打开失败 \ r\n");
- return 0;
- }
- printf("图像宽度:%d\n",getBmpWidth(fp_read));
- printf("图像高度:%d\n",getBmpHeight(fp_read));
- printf("文件大小:%d 字节 \ n",getBmpFileSize(fp_read));
- printf("像素位数:%d\n",getBmpPixBits(fp_read));
- printf("偏移:%d\n",getOffset(fp_read));
- readBmpData(fp_read);
- return 0;
- }
- int readBmpData( FILE* fpbmp )
- {
- int i = 0, j = 0;
- int offset = getOffset(fpbmp);
- int width = getBmpWidth(fpbmp);
- int height = getBmpHeight(fpbmp);
- unsigned char * pix = NULL;
- //one pix have 3 byte data( R G B )
- pix = malloc( 4 * sizeof( unsigned char ) );
- fseek(fpbmp, offset, SEEK_SET); // Jump to data part
- for( i = 0; i < height; i++ )
- {
- for( j = 0; j < width; j++ )
- {
- fread(pix, 3, 1, fpbmp);
- printf("(=,=,=)",pix[0],pix[1],pix[2]);
- }
- printf(",");
- for(;(j)%4!=0;j++)
- {
- fread(pix, 3, 1, fpbmp);
- printf("(=,=,=)",pix[0],pix[1],pix[2]);
- }
- printf("\n");
- }
- return 0;
- }
- // 获取像素位数
- int getBmpPixBits(FILE * fpbmp)
- {
- int bits = 0;
- fseek(fpbmp, 28, SEEK_SET);
- fread(&bits, sizeof(char), 2, fpbmp);
- return bits;
- }
- int getBmpFileSize(FILE * fpbmp)
- {
- int size = 0;
- fseek(fpbmp, 2, SEEK_SET);
- fread(&size, sizeof(char), 4, fpbmp);
- return size;
- }
- int getBmpWidth(FILE* fpbmp)
- {
- int width = 0;
- fseek(fpbmp, 18L, SEEK_SET);
- fread(&width, sizeof(char), 4, fpbmp);
- return width;
- }
- int getBmpHeight( FILE* fpbmp )
- {
- int height = 0;
- fseek(fpbmp, 22L, SEEK_SET);
- fread(&height, sizeof(char), 4, fpbmp);
- return height;
- }
- int getOffset(FILE * fpbmp)
- {
- int offset = 0;
- fseek(fpbmp, 10L, SEEK_SET);
- fread(&offset, sizeof(char), 4, fpbmp);
- return offset;
- }
来源: http://www.bubuko.com/infodetail-2976318.html