欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

将标题重写为:“将YUV数据格式从NV12转换为I420并进行90度旋转”

最编程 2024-08-15 15:27:18
...

1、几种常见格式的YUV数据

I420(YU12):先存Y,然后U,最后V。YYYYYYYYUUVV

YV12:先存Y,然后V,最后U。YYYYYYYYVVUU

NV12:先存Y,然后UV交错存储,iOS下这种模式。YYYYYYYYUVUV

NV21:先存Y,然后VU交错存储,Android下这种格式。YYYYYYYYVUVU

2、NV12转I420

因为NV12的YUV数据UV是交错存储的,I420的UV是单独存储的,所有NV12转I420的时候,只需要将UV数据分开

void NV12ToI420(uint8_t* src_y, uint8_t* src_uv, 
	uint8_t* dst_y, uint8_t* dst_u, uint8_t* dst_v,
    uint32_t width,uint32_t height) {
	// src_y --> dst_y memcpy
	for (int i = 0; i < (width* height); ++i) {
		dst_y[i] = src_y[i];
	}

	// src_uv --> dst_u,dst_v
	int index = 0;
	for (int i = 0; i < (width* height/2); ++i) {
		dst_u[index] = src_uv[i++];
		dst_v[index] = src_uv[i];
		index++;
	}
}

3、旋转I420数据,旋转90度

YUV数据格式的转换(NV12ToI420)和旋转(旋转90度)_像素点

首先我们先看这样一张图,代表的是4*8的YUV420数据,每一个Y代表一个像素点,长度为1个字节,每四个Y对应一个U,一个V(相同颜色),也就是每一个2*2的小正方形对应一个U和V。下来我们将图片旋转90度,可以得到下面这张图片

YUV数据格式的转换(NV12ToI420)和旋转(旋转90度)_音视频_02

首先我们旋转的是Y,然后旋转U,最后旋转V,因为每一个2*2的小正方形对应一个U和V,所以就是每两个宽和每两个高取一个U和V,所以只要写出Y的旋转,然后U和V的旋转就是将Y旋转的宽和高都变为原来的一半就可以了,具体代码如下

enum Degree { kRotate90, kRotate180, kRotate270 };
// 旋转
void RotateI420(uint8_t* src_y, uint8_t* src_u, uint8_t* src_v,
	uint8_t* dst_y, uint8_t* dst_u, uint8_t* dst_v,
    uint32_t width,uint32_t height,int degree) {
	if (degree != kRotate90) {
		return;
	}
	// 第一步我们只转Y
	// 旋转90度
	int index = 0;
	for (int i = 0; i < width; ++i) {
		for (int j = height- 1; j >= 0; --j) {
			dst_y[index++] = src_y[j*width+ i];
		}
	}

	int uv_index = 0;
	for (int i = 0; i<width/ 2; i++) {
		for (int j = height/2-1; j>=0; j--)
		{
			dst_u[uv_index] = src_u[width/ 2 * j + i];
			dst_v[uv_index] = src_v[width/ 2 * j + i];
			uv_index++;
		}
	}
}

3、当然上面的格式转换和旋转都可以使用libyuv取完成,写好的库,很方便