Bmp图片格式介绍

Bmp图片格式介绍

介绍

BMP是英文Bitmap位图)的简写,它是Windows操作系统中的标准图像文件格式,能够被多种Windows应用程序所支持。随着Windows操作系统的流行与丰富的Windows应用程序的开发,BMP位图格式理所当然地被广泛应用。这种格式的特点是包含的图像信息较丰富,几乎不进行压缩,但由此导致了它与生俱来的缺点–占用磁盘空间过大

文件数据结构

bmp 格式图片的文件头长度绝大多数都是 54 字节,其中包括 14 字节的 位图文件头(head)以及 40 字节的 DIB (Device Independent Bitmap) 位图信息数据头(BItmap Information Header)。

位图文件头(14 bytes)

地址(hex)字节长度(byte)描述
002固定头文件字段,内容为0x424D
024bmp文件大小(little endian)
062预留字段
082预留字段
0A4图片信息的开始位置

位图信息数据头(40bytes)

地址(hex)字节长度(byte)描述
0E4位图信息数据头的大小 40bytes
124图像宽度(little endian)
164图像高度(little endian)
1A2色彩平面的数量,默认为1
1C2每像素用多少bit表示
1E4图片采用的压缩方式,通常不压缩即BL_RGB,对应值0
224图片大小(原始位图数据大小)对于不压缩的图片,默认为0
264横向分辨率(像素/米)
2A4纵向分辨率(像素/米)
2E4调试板中颜色数量,默认为0
324重要颜色的数量,默认为0

原始位图数据 Raw Bitmap Data

拿最常见的 24BPP RGB (24 比特每像素,红绿蓝三通道) 位图来说,每种颜色需要 8 比特,或者说 1 字节,来存储。在二进制文件中,通常情况下,RGB 按照蓝、绿、红的顺序依次表示图片中的像素点,而 RGBA 则按照蓝、绿、红、透明的顺序(从左下开始,横向逐行向上扫描)。特殊时候,也会出现顺序与上述情况不同的特例,这时色彩顺序会写在 DIB Header 的 Bit Fields 中,以不同色彩通道的 Mask 的形式进行规定。由于 BI_BITFIELDS 也是一种压缩方式,而通常 BMP 不采用任何压缩方式,所以绝大多数时候,我们都是按照前面说的顺序进行排序。

地址(hex)字节长度(byte)描述(big endian)
36400 00 FF 00Red Channel bit mask
3A400 FF 00 00Green Channel bit mask
3E4FF 00 00 00Blue Channel bit mask
42400 00 00 FFAlpha Channel bit mask

主流的 CPU 每次从内存中读取并处理数据块(chunk),且通常为 32 比特(4 字节)。因此,为了提升读取效率,位图每行的数据(字节)都需要是 4 的倍数,字节对齐

Row_Size = (BitPerPixel * Image_Width + 31) / 32 * 4

每行的字节数等于:每像素比特数乘以图片宽度31 的和除以 32,并向下取整,最后乘以 4

Pix_Array_Size = Row_Size * Image_Height

原始位图数据大小等于:每行的字节数乘以图像高度(也就是总行数)

文件大小 = 原始位图数据大小 + 文件头大小

在这里插入图片描述

代码表示bitmap数据

BitMap Head

#pragma pack(1)
typedef struct {
    unsigned short bfType;      // "BM"
    unsigned int bfSize;        // 文件大小
    unsigned short bfReserved1; // 保留,必须设置为0
    unsigned short bfReserved2; // 保留,必须设置为0
    unsigned int bfOffBits;     // 从文件头到像素数据的偏移
} BitMapFileHeader;

BitMap Info Header

typedef struct{
    unsigned int biSize;        // 此结构体的大小
    int biWidth;                // 图像的宽
    int biHeight;               // 图像的高
    unsigned short biPlanes;    // 表示bmp图片的平面属,显然显示器只有一个平面,所以恒等于1
    unsigned short biBitCount;  // 一像素所占的位数,一般为24
    unsigned int biCompression; // 说明图象数据压缩的类型,0为不压缩。
    unsigned int biSizeImage;   // 像素数据所占大小, 这个值应该等于上面文件头结构中bfSize-bfOffBits
    int biXPelsPerMeter;        // 说明水平分辨率,用象素/米表示。一般为0
    int biYPelsPerMeter;        // 说明垂直分辨率,用象素/米表示。一般为0
    unsigned int biClrUsed;     // 说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。
    unsigned int biClrImportant;// 说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。
} BitMapInfoHeader;

rgb

// 24bit
typedef struct {
    unsigned char rgblue;
    unsigned char rgbgreen;		
    unsigned char rgbred;
    unsigned char rgbreserved;
} PixelInfo;

代码demo

读取bmp文件数据头
#ifndef _BMP_H_
#define _BMP_H_

#pragma pack(1)

typedef struct {
    unsigned short bfType;      // "BM"
    unsigned int bfSize;        // 文件大小
    unsigned short bfReserved1; // 保留,必须设置为0
    unsigned short bfReserved2; // 保留,必须设置为0
    unsigned int bfOffBits;     // 从文件头到像素数据的偏移
} BitMapFileHeader;

typedef struct{
    unsigned int biSize;        // 此结构体的大小
    int biWidth;                // 图像的宽
    int biHeight;               // 图像的高
    unsigned short biPlanes;    // 表示bmp图片的平面属,显然显示器只有一个平面,所以恒等于1
    unsigned short biBitCount;  // 一像素所占的位数,一般为24
    unsigned int biCompression; // 说明图象数据压缩的类型,0为不压缩。
    unsigned int biSizeImage;   // 像素数据所占大小, 这个值应该等于上面文件头结构中bfSize-bfOffBits
    int biXPelsPerMeter;        // 说明水平分辨率,用象素/米表示。一般为0
    int biYPelsPerMeter;        // 说明垂直分辨率,用象素/米表示。一般为0
    unsigned int biClrUsed;     // 说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。
    unsigned int biClrImportant;// 说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。
} BitMapInfoHeader;

// 24bit
typedef struct {
    unsigned char rgblue;
    unsigned char rgbgreen;		
    unsigned char rgbred;
    unsigned char rgbreserved;
} PixelInfo;

#endif

#include <stdio.h>
#include "bmp.h"

void show_bmp_file_head(BitMapFileHeader *data)
{
    printf("#########################################\n");
    printf("bfType %x\n", data->bfType);
    printf("bfSize %d\n", data->bfSize/1024);
    printf("bfOffBits %d\n", data->bfOffBits);
}

void show_bmp_info_head(BitMapInfoHeader *data)
{
    printf("#########################################\n");
    printf("biSize %d\n", data->biSize);
    printf("biWidth %d\n", data->biWidth);
    printf("biHeight %d\n", data->biHeight);
    printf("biPlanes %d\n", data->biPlanes);
    printf("biBitCount %d\n", data->biBitCount);
    printf("biCompression %d\n", data->biCompression);
    printf("biXPelsPerMeter %d\n", data->biXPelsPerMeter);
    printf("biYPelsPerMeter %d\n", data->biYPelsPerMeter);
    printf("biClrUsed %d\n", data->biClrUsed);
    printf("biClrImportant %d\n", data->biClrImportant);
}

void show_bmp_rgb(PixelInfo *data)
{
    printf("#########################################\n");
    printf("rgblue %2x\n", data->rgblue);
    printf("rgbgreen %2x\n", data->rgbgreen);
    printf("rgbred %2x\n", data->rgbred);
}

int main(int argc, char *argv[])
{
    FILE *fp = NULL;
    BitMapFileHeader    FileHead;
    BitMapInfoHeader    InfoHead;
    PixelInfo           rgbinfo;
    char *ptr = NULL;
    int i, j;
    
    fp = fopen(argv[1], "rb");
    if(fp == NULL)
    {
        perror("open bmp file error");
        return -1;
    }

    fread(&FileHead, sizeof(BitMapFileHeader), 1, fp);
    fread(&InfoHead, sizeof(BitMapInfoHeader), 1, fp);
    show_bmp_file_head(&FileHead);
    show_bmp_info_head(&InfoHead);
    show_bmp_rgb(&rgbinfo);
    
    ptr = (unsigned char *)malloc(FileHead.bfSize);
    if(ptr == NULL)
    {
        perror("malloc ptr fail\n");
        return 0;
    }
    for(i = 0; i <= InfoHead.biHeight; i++)
    {
        for(j = 0; j <= InfoHead.biWidth; j++)
        {
            fread(&rgbinfo, sizeof(PixelInfo), 1, fp);
            *ptr = 0xff << 24 | rgbinfo.rgbred << 16 |  rgbinfo.rgbgreen << 8 | rgbinfo.rgblue;
            memset(&rgbinfo, 0, sizeof(PixelInfo));
            ptr++;
            if((rgbinfo.rgbred == 255) && (rgbinfo.rgbgreen == 255) && (rgbinfo.rgblue == 255))
                printf(" ");
            else
                printf("#");
        }
        printf("\n");
    } 
    
    fclose(fp);
    return 0;
}
lin@u-android:~/lin/workspace/demo_project/bmp$ gcc -o bmp_test show_bmp_head.c 
lin@u-android:~/lin/workspace/demo_project/bmp$ ./bmp_test ./test.bmp 
#########################################
bfType 4d42
bfSize 459
bfOffBits 54
#########################################
biSize 40
biWidth 507
biHeight 309
biPlanes 1
biBitCount 24
biCompression 0
biXPelsPerMeter 0
biYPelsPerMeter 0
biClrUsed 0
biClrImportant 0
  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值