使用c++处理YUV文件

目录

  • YUV文件的存储结构
    • 取样结构
      • 4:4:4
      • 4:2:2
      • 4:1:1
      • 4:2:0格式1
      • 4:2:0格式2
    • 存储结构
      • YUVY(4:2:2)
      • UYVY(4:2:2)
      • YUV422P(4:2:2)
      • YV12,YU12(4:2:0)
      • NV12,NV21(4:2:0)
  • 所占空间计算
  • 使用c++进行处理

YUV文件的存储结构

取样结构

这组图图每一行即为一行像素点,以Y为基准,蓝色和红色表示 C b / U C_b/U Cb/U C r / V C_r/V Cr/V

4:4:4

使用c++处理YUV文件_第1张图片

4:2:2

使用c++处理YUV文件_第2张图片

4:1:1

使用c++处理YUV文件_第3张图片

4:2:0格式1

使用c++处理YUV文件_第4张图片

4:2:0格式2

使用c++处理YUV文件_第5张图片

存储结构

一下均指一帧的情况,实际上是一帧内容按照相应格式存储完成后,再存储下一帧。

YUVY(4:2:2)

Y 0 C b 0 Y 1 C r 0 Y 2 C b 1 Y 3 C r 2 ⋯ Y_0C_{b_0}Y_1C_{r_0}Y_2C_{b_1}Y_3C_{r_2}\cdots Y0Cb0Y1Cr0Y2Cb1Y3Cr2
Y Y Y后跟 C b C_b Cb Y Y Y后跟 C r C_r Cr交替出现。

UYVY(4:2:2)

C b 0 Y 0 C r 0 Y 1 C b 1 Y 2 C r 2 Y 3 ⋯ C_{b_0}Y_0C_{r_0}Y_1C_{b_1}Y_2C_{r_2}Y_3\cdots Cb0Y0Cr0Y1Cb1Y2Cr2Y3
C b C_b Cb后跟 Y Y Y C r C_r Cr后跟 Y Y Y交替出现。

YUV422P(4:2:2)

先存储完所有Y,再存储完所有 C b C_b Cb,最后再存储所有 C r C_r Cr

YV12,YU12(4:2:0)

先存储完所有Y,再存储完所有 C b C_b Cb,最后再存储所有 C r C_r Cr

NV12,NV21(4:2:0)

先存储完所有Y,之后 C b x C_{b_x} Cbx C b x + 1 C_{b_{x+1}} Cbx+1 C r x C_{r_x} Crx C r x + 1 C_{r_{x+1}} Crx+1的结构交替出现,即两字节 C b C_b Cb之后再存储两字节 C r C_r Cr

所占空间计算

每一个像素点用1字节存储信息。知道分辨率,即高 h h h和宽度 w w w之后, h × w h\times w h×w即是Y所占空间大小,再根据取样结构算出U和V所占比例,相加即为一帧所占大小。
如4:2:0格式,Y占用 h × w h\times w h×w,U和V占用 h × w × 2 4 h\times{w}\times\frac{2}{4} h×w×42,加起来一帧所占的空间就是 3 h w 2 \frac{3hw}{2} 23hw

使用c++进行处理

知道文件怎么存储之后,就可以进行处理了。以288乘352的YV12格式为例。
如果我想把它变成黑白的,那么我只需要保留Y的信息,其余都抹掉即可。那么去掉U,V是否是把他们变成0呢?并不是,因为U,V有负值,而处理数据的时候却不按照负值处理,于是U,V的0的位置,被128代替;也就是说128才是实际意义上的0。

#include 
#include 
using namespace std;
const char* inPath = "miss.cif";
const char* outPath = "miss_out.cif";
int main()
{
	ifstream in(inPath, ios::binary);
	in.seekg(0, ios::end);
	int size = in.tellg();
	in.seekg(0, ios::beg);

	char* inBuffer = new char[size];
	in.read(inBuffer, size);
	in.close();

	char* outBuffer = new char[size];
	int width = 352, height = 288, inFrameSize = width * height * 3 / 2;
	int frameNum = size / inFrameSize;

	for (int i = 0; i < frameNum; ++i)
		for (int j = 0; j < inFrameSize; ++ j)
			outBuffer[i * inFrameSize + j] = j < width * height ? inBuffer[i * inFrameSize + j] : 128;

	ofstream out(outPath,ios::binary);
	out.write(outBuffer, size);
	out.close();
}

处理完成后使用YUV播放器查看效果:
处理前:
使用c++处理YUV文件_第6张图片使用c++处理YUV文件_第7张图片
处理后:
使用c++处理YUV文件_第8张图片
使用c++处理YUV文件_第9张图片

你可能感兴趣的:(数字视频处理,视频处理,yuv,c++)