FFmpeg 像素格式和尺寸转换函数
双线性过滤(Bilinear_filtering)
代码
test_sws_scale.cpp
#include <iostream> #include <fstream> extern "C" { #include
"libswscale/swscale.h" } #pragma comment(lib, "swscale.lib") #define YUVFILE
"400_300_25.yuv" #define RGBAFILE "800_600_25.rgba" using namespace std; int
main() { ifstream ifs; ofstream ofs; const int yuv_width = 400; const int
yuv_height = 300; const int rgba_width = 800; const int rgba_height = 600;
unsigned char* yuv[3] = { 0 }; SwsContext* yuv2rgba = nullptr; SwsContext*
rgba2yuv = nullptr; int yuv_linesize[3] = { yuv_width , yuv_width / 2,
yuv_width / 2 }; unsigned char* rgba = nullptr; int rgba_linesize = rgba_width
* 4; int slice_height = 0; yuv[0] = new unsigned char[yuv_width * yuv_height];
// Y yuv[1] = new unsigned char[yuv_width * yuv_height / 4]; // U yuv[2] = new
unsigned char[yuv_width * yuv_height / 4]; // V rgba = new unsigned
char[rgba_width * rgba_height * 4]; ifs.open(YUVFILE, ios::in | ios::binary);
if (!ifs) { cerr << "open " << YUVFILE << " failed" << endl; return -1; }
ofs.open(RGBAFILE, ios::out | ios::binary); if (!ofs) { cerr << "open " <<
RGBAFILE << " failed" << endl; return -1; } /* YUV420P 转 RGBA */ for (int i =
0; i < 10; i++) // 读取10帧数据 { /* 读取一帧的 YUV 数据 */ ifs.read((char*)yuv[0],
yuv_width * yuv_height); ifs.read((char*)yuv[1], yuv_width * yuv_height / 4);
ifs.read((char*)yuv[2], yuv_width * yuv_height / 4); /* 文件已经读完 */ if
(ifs.gcount() == 0) { break; } /* YUV转RGBA 上下文件创建和获取 */ yuv2rgba =
sws_getCachedContext( yuv2rgba, // 转换上下文,NULL新创建,非NULL判断与现有参数是否一致, //
一致直接返回,不一致先清理当前然后再创建 yuv_width, yuv_height, // 输入宽高 AV_PIX_FMT_YUV420P, //
输入像素格式 rgba_width, rgba_height, // 输出的宽高 AV_PIX_FMT_RGBA, // 输出的像素格式
SWS_BILINEAR, // 选择支持变化的算法,双线性插值 nullptr, nullptr, nullptr // 过滤器参数 ); if
(!yuv2rgba) { cerr << "sws_getCachedContext failed!" << endl; return -1; }
slice_height = sws_scale( yuv2rgba, yuv, // 输入数据 yuv_linesize, // 输入数据行字节数 0,
yuv_height, // 输入高度 &rgba, // 输出数据 &rgba_linesize ); ofs.write((char*)rgba,
rgba_width * rgba_height * 4); // 将转换后的 RGBA 数据写入到 rgba 文件中 cout <<
slice_height << " " << flush; } ifs.close(); ofs.close(); ifs.open(RGBAFILE,
ios::in | ios::binary); if (!ifs) { cerr << "open " << YUVFILE << " failed" <<
endl; return -1; } /* 将 RGBA 转成 YUV420P */ for (;;) { /* 读取一帧的 RGBA 数据 */
ifs.read((char*)rgba, rgba_width * rgba_height * 4); /* 文件已经读完 */ if
(ifs.gcount() == 0) { break; } /* RGBA 转 YUV 上下文件创建和获取 */ rgba2yuv =
sws_getCachedContext( rgba2yuv, // 转换上下文,NULL新创建,非NULL判断与现有参数是否一致, //
一致直接返回,不一致先清理当前然后再创建 rgba_width, rgba_height, // 输入宽高 AV_PIX_FMT_RGBA, //
输入像素格式 yuv_width, yuv_height, // 输出的宽高 AV_PIX_FMT_YUV420P, // 输出的像素格式
SWS_BILINEAR, // 选择支持变化的算法,双线性插值 nullptr, nullptr, nullptr // 过滤器参数 ); if
(!rgba2yuv) { cerr << "sws_getCachedContext failed!" << endl; return -1; }
slice_height = sws_scale( rgba2yuv, &rgba, // 输入数据 &rgba_linesize, // 输入数据行字节数
0, rgba_height, // 输入高度 yuv, // 输出数据 yuv_linesize ); cout << "(" <<
slice_height << ")" << " " << flush; } ifs.close(); delete[] yuv[0]; delete[]
yuv[1]; delete[] yuv[2]; delete[] rgba; return 0; }
实现了 YUV420P 和 RGBA 图像不同尺寸不同像素格式之间的转换。
测试结果