BMP 序列转 YUV 文件

BMP 序列转 YUV 文件1.实现思路工具:c语言整体思路1。打开并读入BMP文件、定义变量,开辟存储空间。BMP文件中首先被读入的应该是文件头和信息头,读入之后才能根据其中给出的关于位图的宽高、bit数等信息进行开辟空间等操作。在本实验中,定义两个指针:BITMAPFILEHEADER File_header; BITMAPINFOHEADER Info_header; 分别用来获取文件头和信息头的数据。注意,这两种类型需要加<windows.h>头文件。2.提取出RGB数据,写入
摘要由CSDN通过智能技术生成

BMP 序列转 YUV 文件

1.实现思路

工具:c语言

整体思路

1。打开并读入BMP文件、定义变量,开辟存储空间。BMP文件中首先被读入的应该是文件头和信息头,读入之后才能根据其中给出的关于位图的宽高、bit数等信息进行开辟空间等操作。在本实验中,定义两个指针:BITMAPFILEHEADER File_header; BITMAPINFOHEADER Info_header; 分别用来获取文件头和信息头的数据。注意,这两种类型需要加<windows.h>头文件。
2.提取出RGB数据,写入缓冲区。不同bit的文件不同处理。24bit图可以直接取图片数据;16bit比较复杂,需要取像素数据转换成8bit彩色分量后再写入rgbBuf;8bit,4bit,1bit均需要构造调色板。需要注意的是图像数据需要倒置。
3.调用“RGB2YUV.h”函数实现转换,并写入新的YUV文件。生成视频时可以循环写入,每张图片素材30帧。打开方式“wb+”可以下次继续写入。
4.释放缓冲区,关闭文件。

bmp2rgb

1.读取BMP文件,得到RGB数据:判断是否为BMP文件;判断文件是否可读出;要保证BMP图像的长必须是4的倍数,宽必须是2的倍数
2.通过信息头得到有效位图数据在BMP图像中的位置,进而对有效数据进行读取
3.BMP规定:位图数据自左向右、自下向上依次存放。因此注意。Index_Data是直接从BMP文件中读取的数据倒序存放的buffer,需要变为正序的,即Data
4.得到的Data并不一定是RGB数据,因为BMP有位深的类别。24位BMP,位图有效数据就是RGB,而16位、8位、4位、2位、1位的BMP则需要位操作,从DATA数据中“解析”出RGB数据,具体方法见下图与注释

rgb2yuv

公式:
Y=0.2990R+0.5870G+0.1140B
R-Y=0.7010R-0.5870G-0.1140B
B-Y=-0.2990R-0.5870G+0.8860B

U=-0.1684R-0.3316G+0.5B
V=0.5R-0.4187G-0.0813B

2.实验内容

程序实现

bmp2yuv.h

#ifndef BMP2YUV_H_
#define BMP2YUV_H_

//定义掩码组
typedef struct bit32Mask
{
   
    unsigned int rgbRed;
    unsigned int rgbGreen;
    unsigned int rgbBlue;
    unsigned int reserved;
}Mas32;
typedef struct bit16Mask
{
   
    unsigned int rgbRed;
    unsigned int rgbGreen;
    unsigned int rgbBlue;
}Mas16;

int BMP2RGB32bit(int bitcount, int x_dim, int y_dim, void* bmpbuf, void* rgbbuf, void* mask);
int BMP2RGB24bit(int bitcount, int x_dim, int y_dim, void* bmpbuf, void* rgbbuf);
int BMP2RGB16bit(int bitcount, int x_dim, int y_dim, void* bmpbuf, void* rgbbuf, void* mask);
int BMP2RGBNOT24bit(int bitcount, int x_dim, int y_dim, void* bmpbuf, void* rgbbuf, void* pRGB);
int RGB2YUV(int x_dim, int y_dim, void* bmp, void* y_out, void* u_out, void* v_out, int flip);
void InitLookupTable();
void adjust(unsigned char* b, unsigned char* g, unsigned char* r, unsigned char* y, unsigned char* u, unsigned char* v);
#endif

rgb2yuv.h

#include "stdlib.h"
#include "bmp2yuv.h"

static float RGBYUV02990[256], RGBYUV05870[256], RGBYUV01140[256];
static float RGBYUV01684[256], RGBYUV03316[256];
static float RGBYUV04187[256], RGBYUV00813[256];

int RGB2YUV(int x_dim, int y_dim, void* bmp, void* y_out, void* u_out, void* v_out, int flip)
{
   
    static int init_done = 0;

    long i, j, size;
    unsigned char* r, * g, * b;
    unsigned char* y, * u, * v;
    unsigned char* pu1, * pu2, * pv1, * pv2, * psu, * psv;
    unsigned char* y_buffer, * u_buffer, * v_buffer;
    unsigned char* sub_u_buf, * sub_v_buf;

    if (init_done == 0)
    {
   
        InitLookupTable();
        init_done = 1;
    }

    // 检查x_dim 和 y_dim 是否可被2整除
    if ((x_dim % 2) || (y_dim % 2)) return 1;
    size = x_dim * y_dim;

    //分配缓存
    y_buffer = (unsigned char*)y_out;
    sub_u_buf = (unsigned char*)u_out;
    sub_v_buf = (unsigned char*)v_out;
    u_buffer = (unsigned char*)malloc(size * sizeof(unsigned char));
    v_buffer = (unsigned char*)malloc(size * sizeof(unsigned char));
    if (!(u_buffer && v_buffer))
    {
   
        if (u_buffer) free(u_buffer);
        if (v_buffer) free(v_buffer);
        return 2;
    }

    b = (unsigned char*)bmp;
    y = y_buffer;
    u = u_buffer;
    v = v_buffer;

    //将RGB转为YUV
    if (!flip)
    {
   
        for (j = 0; j < y_dim; j++)
        {
   
            y = y_buffer + (y_dim - j - 1) * x_dim;
            u = u_buffer + (y_dim - j - 1) * x_dim;
            v = v_buffer + (y_dim - j - 1) * x_dim;

            for (i = 0; i < x_dim; i++) {
   
                g = b + 1;
                r = b + 2;
                adjust(b, g, r, y, u, v);
                b += 3;
                y++;
                u++;
                v++;
            }
        }
    }
    else {
   
        for (i = 0; i < size; i++)
        {
   
            g = b + 1;
            r = b + 2;
            adjust(b, g, r, y, u, v);
            b += 3;
            y++;
            u++;
            v++;
        }
    }
    // 对 UV 二次抽样
    for (j = 0; j < y_dim / 2; j++)
    {
   
        psu = sub_u_buf + j * x_dim / 2;
        psv = sub_v_buf + j * x_dim / 2;
        pu1 = u_buffer + 2 * j * x_dim;
        pu2 = u
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值