基础篇_3.图像编码之Bmp

学习整理的相关章节链接:
基础篇_1.音视频学习框架
基础篇_2. 颜色空间模型 RBG、YUV、HSV
基础篇_3.图像编码之Bmp
基础篇_4.音频基础概念
基础篇_5.音频数据采集
基础篇_6.音频编码PCM
基础篇_7.音频编码WAV
基础篇_8.音频编码MP3\AAC

BMP(全称Bitmap)是Windows操作系统中的标准图像文件格式,可以分成两类:设备有向量相关位图(DDB)和设备无向量关位图(DIB),使用非常广。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BMP文件所占用的空间很大。BMP文件的图像深度可选lbit、4bit、8bit及24bit。BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。由于BMP文件格式是Windows环境中交换与图有关的数据的一种标准,因此在Windows环境中运行的图形图像软件都支持BMP图像格式。

格式组成

典型的BMP图像文件由四部分组成:

1:位图文件头数据结构,它包含BMP图像文件的类型、显示内容等信息;

typedef  struct  tagBITMAPFILEHEADER
{ 
    unsigned short int  bfType;       //位图文件的类型,必须为BM 
    unsigned long       bfSize;       //文件大小,以字节为单位
    unsigned short int  bfReserverd1; //位图文件保留字,必须为0 
    unsigned short int  bfReserverd2; //位图文件保留字,必须为0 
    unsigned long       bfbfOffBits;  //位图文件头到数据的偏移量,以字节为单位
}BITMAPFILEHEADER; 

2:位图信息头数据结构,它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息;

typedef  struct  tagBITMAPINFOHEADER 
{ 
    long biSize;                        //该结构大小,字节为单位
    long  biWidth;                      //图形宽度以象素为单位
    long  biHeight;                     //图形高度以象素为单位
    short int  biPlanes;                //目标设备的级别,必须为1 
    short int  biBitcount;              //每个像素所需的位数,必须是1(双色)
                                        //4(16色),8(256色)16(高彩色)或24(真彩色)之一
    short int  biCompression;           //位图的压缩类型
    long  biSizeImage;                  //位图的大小,以字节为单位
    long  biXPelsPermeter;              //位图水平分辨率,每米像素数
    long  biYPelsPermeter;              //位图垂直分辨率,每米像素数
    long  biClrUsed;                    //位图实际使用的颜色表中的颜色数
    long  biClrImportant;             //位图显示过程中重要的颜色数
}BITMAPINFOHEADER;

3:调色板,这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图(24位的BMP)就不需要调色板;

typedef struct tagRGBQUAD{
    unsigned long bulrgbBlue;    // 蓝色的亮度(0~255)
    unsigned long bulrgbGreen;   // 绿色的亮度(0~255)
    unsigned long bulrgbRed;     // 红色的亮度(0~255)
    unsigned long bulrgbReserved;    // 保留,必须位0
}RGBQUAD;

//位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:
typedef struct tagBITMAPINFO{
    BITMAPINFOHEADER bmiHeader;//位图信息头
    RGBQUAD bmiColors[1];//颜色表
} BITMAPINFO;

4:位图数据,这部分的内容根据BMP位图使用的位数不同而不同,在24位图中直接使用RGB,而其他的小于24位的使用调色板中颜色索引值。

5:将RGB24格式像素数据封装为BMP图像:
BMP图像内部实际上存储的就是RGB数据。本程序实现了对RGB像素数据的封装处理。通过本程序中的函数,可以将RGB数据封装成为一张BMP图像

/**

 * Convert RGB24 file to BMP file
 * @param rgb24path    Location of input RGB file.
 * @param width        Width of input RGB file.
 * @param height       Height of input RGB file.
 * @param url_out      Location of Output BMP file.
 */

int simplest_rgb24_to_bmp(const char *rgb24path,int width,int height,const char *bmppath){
    typedef struct 
    {  
        long imageSize;
        long blank;
        long startPosition;
    }BmpHead;

    typedef struct
    {
        long  Length;
        long  width;
        long  height;
        unsigned short  colorPlane;
        unsigned short  bitColor;
        long  zipFormat;
        long  realSize;
        long  xPels;
        long  yPels;
        long  colorUse;
        long  colorImportant;
    }InfoHead;

    int i=0,j=0;
    BmpHead m_BMPHeader={0};
    InfoHead  m_BMPInfoHeader={0};
    char bfType[2]={'B','M'};
    int header_size=sizeof(bfType)+sizeof(BmpHead)+sizeof(InfoHead);
    unsigned char *rgb24_buffer=NULL;
    FILE *fp_rgb24=NULL,*fp_bmp=NULL;
 
    if((fp_rgb24=fopen(rgb24path,"rb"))==NULL){
        printf("Error: Cannot open input RGB24 file.\n");
        return -1;
    }

    if((fp_bmp=fopen(bmppath,"wb"))==NULL){
        printf("Error: Cannot open output BMP file.\n");
        return -1;
    }

    rgb24_buffer=(unsigned char *)malloc(width*height*3);
    fread(rgb24_buffer,1,width*height*3,fp_rgb24);

    m_BMPHeader.imageSize=3*width*height+header_size;
    m_BMPHeader.startPosition=header_size;

    m_BMPInfoHeader.Length=sizeof(InfoHead); 
    m_BMPInfoHeader.width=width;

    //BMP storage pixel data in opposite direction of Y-axis (from bottom to top).
    m_BMPInfoHeader.height=-height;
    m_BMPInfoHeader.colorPlane=1;
    m_BMPInfoHeader.bitColor=24;
    m_BMPInfoHeader.realSize=3*width*height;
    fwrite(bfType,1,sizeof(bfType),fp_bmp);
    fwrite(&m_BMPHeader,1,sizeof(m_BMPHeader),fp_bmp);
    fwrite(&m_BMPInfoHeader,1,sizeof(m_BMPInfoHeader),fp_bmp);

    //BMP save R1|G1|B1,R2|G2|B2 as B1|G1|R1,B2|G2|R2
    //It saves pixel data in Little Endian
    //So we change 'R' and 'B'
    for(j =0;j

部分内容摘自雷神博客

你可能感兴趣的:(基础篇_3.图像编码之Bmp)