【音视频系列】RGB24数据格式及BMP文件格式以及存储方式

发布时间 2023-08-22 14:44:37作者: DoubleLi

RGB24是表明图像以RGB三原色,每个像素点3个字节表示的一种图像存储格式

  注意:在内存中RGB各分量的排列顺序为:BGR BGR BGR 

先用ffmpeg生成一个RGB24的图片,命令如下:

  ffmpeg -i test.jpg -pix_fmt rgb24 test.rgb

生成后下面用C++代码拆分RGB24的三原色并保存:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void read_split_rgbfile(const char* file, int width, int height, int frames) {
    FILE* rgbFp = fopen(file, "rb+");
    FILE* rFp = fopen("e:\\test_r.y""wb+");
    FILE* gFp = fopen("e:\\test_g.y""wb+");
    FILE* bFp = fopen("e:\\test_b.y""wb+");
 
    int size = width * height;
    unsigned char * buf = (unsigned char*)malloc(size * 3);
    unsigned char * rbuf = (unsigned char*)malloc(size);
    unsigned char * gbuf = (unsigned char*)malloc(size);
    unsigned char * bbuf = (unsigned char*)malloc(size);
 
    int ridx, gidx, bidx;
    ridx = gidx = bidx = 0;
    for (int i = 0; i < frames; i++)
    {
        fread(buf, 1, size * 3, rgbFp);
        for (int rgbidx = 0; rgbidx < size * 3; rgbidx = rgbidx + 3)
        {
            rbuf[ridx++] = buf[rgbidx];
            gbuf[gidx++] = buf[rgbidx + 1];
            bbuf[bidx++] = buf[rgbidx + 2];
        }
        fwrite(rbuf, 1, size, rFp);
        fwrite(gbuf, 1, size, gFp);
        fwrite(bbuf, 1, size, bFp);
    }
    free(buf);
    free(rbuf);
    free(gbuf);
    free(bbuf);
    fclose(rgbFp);
    fclose(rFp);
    fclose(gFp);
    fclose(bFp);
}

用YUVPlayer使用Y通道分别查看R,G,B三原色文件,如果均能显示即表示生成没有问题

  由此可以学习RGB三原色在文件中的存储方式

 

RGB24转储为BMP文件

BMP文件格式为:

  BMP文件头+BMP文件信息头+RGB三原色(注意:此时存储序列为BGRBGRBGR.....)

BMP文件头如下:

1
2
3
4
5
6
7
8
typedef struct tagBITMAPFILEHEADER
{
    UINT16 bfType;
    DWORD bfSize;
    UINT16 bfReserved1;
    UINT16 bfReserved2;
    DWORD bfOffBits;
} BITMAPFILEHEADER;

  

 

BMP文件信息头如下:

  

 

 调色板可略

使用C++代码将RGB数据转储为BMP文件代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
typedef struct
{
    long imageSize;
    long blank;
    long startPos;
}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;
void muxer_rgb24_to_bmp(const char* rgbfile, int width, int height, const char * bmpfile) {
    FILE* rgbFp = fopen(rgbfile, "rb+");
    FILE* bmpFp = fopen(bmpfile, "wb+");
    int size = width * height;
    char bmpType[] = { 'B','M' };
    BMPHead bHead = { 0 };
    INFOHead bIHead = { 0 };
    int head_length = sizeof(bmpType) + sizeof(BMPHead) + sizeof(INFOHead);
    bHead.imageSize = size * 3 + head_length;
    bHead.startPos = head_length;
 
    bIHead.length = sizeof(INFOHead);
    bIHead.width = width;
    bIHead.height = -height; //注意此处的高度为负
 
    bIHead.colorPlane = 1;
    bIHead.bitColor = 24;
    bIHead.realSize = size * 3;
    fwrite(bmpType, 1, sizeof(bmpType), bmpFp);
    fwrite(&bHead, 1, sizeof(BMPHead), bmpFp);
    fwrite(&bIHead, 1, sizeof(INFOHead), bmpFp);
 
    unsigned char* rgbBuf = (unsigned char*)malloc(size * 3);
    fread(rgbBuf, 1, size * 3, rgbFp);
    for (int i=0;i <size*3;i+=3)  //调整R和B的顺序
    {
        int tmp = rgbBuf[i];
        rgbBuf[i] = rgbBuf[i + 2];
        rgbBuf[i + 2] = tmp;
    }
    fwrite(rgbBuf, 1, size * 3, bmpFp);
    free(rgbBuf);
    fclose(bmpFp);
    fclose(rgbFp);
}

  输出文件为BMP文件,可以直接查看生成是否正确