音视频数据处理入门:rgb转bmp

BMP图像内部实际存储的是RGB数据,我们通过添加bmp头部信息,调整RGB分量存储顺序,可以将RGB数据封装得到bmp图像。


1、BMP文件格式

BITMAPFILEHEADER + BITMAPINFOHEADER + RGB像素数据

bmp头部信息:
位图文件头(14字节):{‘B’,‘M’} + fsize + blank + offset
位图信息头(40字节):信息头大小,图像宽高、色深,压缩方式,图像数据大小,,,

2、具体的头部信息和转换过程

typedef struct {
    int imageSize;  // 图像文件大小
    int blank;      // 两个保留字合并而来,全为0
    int offset;     // 图像数据的地址
} bmpHead;

typedef struct {
    int Length;     // 结构体大小
    int width;      // 分辨率宽度    
    int height;     // 分辨率高度
    unsigned short colorPlane;  // 目标设备的级别,必须为1
    unsigned short bitColor;    // 颜色深度,即每个像素所需要位数
    int compression;// 压缩方式,0表示不压缩
    int realSize;   // 图像数据大小
    int xPels;      // 水平分辨率,单位像素/m
    int yPels;      // 垂直分辨率
    int colorUse;   // bmp图像使用的颜色,0表示全部颜色
    int colorImportant;         // 重要的颜色数,0时所有颜色都重要
} infoHead;


#define swap(a,b) {unsigned char t = a; a = b; b = t;}
// BMP采用小端存储方式,RGB分量存储顺序为BGR
void rgb24_to_bmp(const char *rgbfile, int w, int h, const char *bmpfile) {
    FILE *frgb = fopen(rgbfile, "r");
    FILE *fbmp = fopen(bmpfile, "w+"); 
    
    int rgbsize = w*h*3;
    unsigned char rgbbuf[rgbsize];

    // 填充Bmp文件头和信息头
    char bmpfileType[2] = {'B', 'M'};
    int headersize = sizeof(bmpfileType) + sizeof(bmpHead) + sizeof(infoHead);
    bmpHead bmpHeader;
    bmpHeader.imageSize = headersize + rgbsize;
    bmpHeader.blank = 0;
    bmpHeader.offset = headersize;


    infoHead infoHeader;
    infoHeader.Length = sizeof(infoHead);
    infoHeader.width = w;
    infoHeader.height = -h;    // bmp从底到顶加载像素数据 
    infoHeader.colorPlane = 1;
    infoHeader.bitColor = 24;
    infoHeader.compression = 0;
    infoHeader.realSize = rgbsize;  
    infoHeader.colorUse = 0;
    infoHeader.colorImportant = 0;

    fwrite(bmpfileType, 1, sizeof(bmpfileType), fbmp);
    fwrite(&bmpHeader, 1, sizeof(bmpHeader), fbmp);
    fwrite(&infoHeader, 1, sizeof(infoHeader), fbmp);


    // 调整rgb分量存储顺序
    fread(rgbbuf, 1, rgbsize, frgb);
    for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) {
            int start = (i*w + j)*3;
            swap(rgbbuf[start], rgbbuf[start+2]);
        }
    }
    // 填充图像数据
    fwrite(rgbbuf, 1, rgbsize, fbmp);

    fclose(frgb); 
    fclose(fbmp);
}

函数调用:rgb24_to_bmp("rgbtest.rgb", 352, 288, "output_bmp.bmp");


3、代码中有几个要注意的点:

①BMP采用的是小端存储方式,要将RGB分量存储顺序调整为BRG。

②bmp从底到顶加载像素数据,infoHeader.height = -h。

③xPels和yPels是现实世界中每米包含的像素数,不需要关心。


4、转换结果(bmp图像可以用普通的看图软件打开):

image-20210426224741177
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值