本文主要完成两个功能YUV->RGB 文件格式转换 ,RGB->YUV文件格式的转换
原理上就一个难点,双线性过滤,如下图所示:
1.用到3个函数
2.实现的步骤
3.示例代码:
3.1YUV->RGB
3.2RGB->YUV
1、YUV->RGB 文件格式转换 ,RGB->YUV文件格式的转换用到3个主要的函数:
1.1.初始化:
1.2缩放:
1.3文件操作 #include <fstream>
fstream ifs;fstream ofs;
1.3.1 ifs.open("file.yuv",ios::binary) 打开或者新建
1.3.2 ifs.read(char* c, datasize) 读
1.3.3 ifs.gcount()==0 读到结尾处
1.3.4 ofs.write(char* c,datasize) 写
1.3.5 ifs.close(),ofs.close() 关闭/
2 步骤:
2.1 打开文件
2.2 读取文件
2.3 初始化
2.4 转换
2.5 关闭文件
在实现之前要有文件名定义和数据空间的分配工作:
YUV是平面存储 YYYY UU VV
RGB是交叉存储 rgba
#define YUV_FILE "400_300_25.yuv"
#define RGBA_FILE "800_600_25.rgba"
//设定文件宽、高
int width = 400;
int height = 300;
int rgb_width = 800;
int rgb_height = 600;
//分配数据空间 new delete
// YUV420P 平面存储 yyyy uu vv
unsigned char* yuv[3] = { 0 };
int yuv_linesize[3] = { width,width / 2,width / 2 }; //YUV 每行的linesize
yuv[0] = new unsigned char[width * height]; //Y
yuv[1] = new unsigned char[width * height / 4]; //U
yuv[2] = new unsigned char[width * height / 4]; //V
//RGBA 交叉存储 rgba rgba
unsigned char* rgba = new unsigned char[rgb_width * rgb_height * 4];
int rgba_linesize = rgb_width * 4;
3.示例代码
3.1.YUV->RGB
//1.打开文件 ifs.open ofs.open
ifstream ifs;
ifs.open(YUV_FILE, ios::binary);
ofstream ofs;
ofs.open(RGBA_FILE, ios::binary);
SwsContext* yuv2rgb = nullptr;
for (int i = 0; i < 10; i++)
{
//1.2.读取YUV帧 ifs.gcount()读到结尾
ifs.read((char*)yuv[0], width * height);
ifs.read((char*)yuv[1], width * height / 4);
ifs.read((char*)yuv[2], width * height / 4);
if (ifs.gcount() == 0)break;
//1.3.初始化上下文
yuv2rgb = sws_getCachedContext(
yuv2rgb, //转换上下文,NULL新创建,非NULL判断与现有参数是否一致,
//一致直接返回,不一致先清理当前然后再创建
width, height, //输入宽高
AV_PIX_FMT_YUV420P, //输入像素格式
rgb_width, rgb_height, //输出的宽高
AV_PIX_FMT_RGBA, //输出的像素格式
SWS_BILINEAR, //选择支持变化的算法,双线性插值
0, 0, 0 //过滤器参数
);
//1.4转换函数 re 输出的高度
unsigned char* data[1];
data[0] = rgba;
int lines[1] = { rgba_linesize };
int re = sws_scale(yuv2rgb,
yuv, //输入数据
yuv_linesize, //输入数据行字节数
0,
height, //输入高度
data, //输出数据
lines
);
cout << re << " " << flush;
ofs.write((char*)rgba, rgb_width * rgb_height * 4);
}
ifs.close();
ofs.close();
3.2.RGB->YUV
//2.1 打开文件
ifs.open(YUV_FILE, ios::binary);
ifs.open(RGBA_FILE, ios::binary);
SwsContext* rgb2yuv = nullptr;
for (;;)
{
//2.2 读取RGB
ifs.read((char*)rgba, rgb_width * rgb_height * 4);
if (ifs.gcount() == 0)break;
//2.3 初始化
rgb2yuv = sws_getCachedContext(
rgb2yuv, //转换上下文,NULL新创建,非NULL判断与现有参数是否一致,
//一致直接返回,不一致先清理当前然后再创建
rgb_width, rgb_height, //输入宽高
AV_PIX_FMT_RGBA, //输入像素格式
width, height, //输出的宽高
AV_PIX_FMT_YUV420P, //输出的像素格式
SWS_BILINEAR, //选择支持变化的算法,双线性插值
0, 0, 0 //过滤器参数
);
//2.4 转换 sws_scale
unsigned char* data[1];
data[0] = rgba;
int lines[1] = { rgba_linesize };
int re = sws_scale(rgb2yuv,
data, //输入数据
lines, //输入数据行字节数
0,
rgb_height, //输入高度
yuv, //输出数据
yuv_linesize //输出数据
);
}
//1.2.2 释放空间
delete yuv[0];
delete yuv[1];
delete yuv[2];
delete rgba;