NV12等常用YUV数据格式

Reference:

  1. YUV数据格式
  2. 图解YU12、I420、YV12、NV12、NV21、YUV420P、YUV420SP、YUV422P、YUV444P的区别

与 RGB 编码方法类似,YUV 也是一种颜色编码方法。其中“Y”表示明亮度(Luminance 或 Luma),也就是灰阶值,UV 表示的则是色度(Chrominance 或 Chroma),分别用 C r C_r Cr C b C_b Cb 来表示,作用是描述影像色彩及饱和度,用于指定像素的颜色。

这样分开的好处;

  1. 可以避免相互干扰(没有 UV 信息一样可以显示完整的图像,因而解决了彩色电视与黑白电视的兼容问题);
  2. 降低色度的采样率而不会对图像质量影响太大,降低了视屏是`信号传输时对频宽(带宽)的要求。

YUV 是一个比较笼统地说法,针对它的具体排列方式,可以分为很多种具体的格式。

1. YUV 采样表示法

YUV 采用 A:B:C 表示法来描述 Y Y Y, U U U, V V V 采样频率比例,下图中黑点表示采样像素点 Y Y Y 分量,空心圆表示采样像素点的 U V UV UV 分量。
在这里插入图片描述

  • 4:4:4 表示色度频道没有下采样,即一个 Y Y Y 分量对应着一个 U U U 分量和一个 V V V 分量。一个 YUV 占 8+8+8=24bits 3个字节;
  • 4:2:2 表示 2:1 的水平取样,垂直完全采样。一个 YUV 占 8+4+4=16bits 2个字节;
  • 4:2:0 表示 2:1 的水平取样,垂直 2:1 采样。一个 YUV 占 8+2+2=12bits 1.5个字节;
  • 4:1:1 表示 4:1 的水平取样,垂直完全采样。 与其他格式相比,4:1:1 采样不太常用。

2. YUV 格式

  1. 打包格式(packed formats): 打包格式中的 YUV 时混合在一起的。
  2. 平面格式(planar formats): 每 Y Y Y 分量、 U U U 分量和 V V V 分量都是以独立的平面组织的,也就是有三个平面。

3. 数据格式

3.1 4:4:4 格式

  1. AYUV:这是一个打包格式,其中每个像素都被编码为四个连续字节,其组织顺序如下所示,其中 A A A 标示了alpha通道。
    在这里插入图片描述

3.2 4:2:2 格式

  1. YUY2:在 YUY2 格式中,数据可被视为一个不带正负号的 char 值组成的数组,其中第一个字节存储第一个 Y Y Y 样例,第二个字节存储第一个 U ( C b ) U(C_b) U(Cb) 样例,第三个字节存储第二个 Y Y Y 样例,第四个字节存储第一个 V ( C r ) V(C_r) V(Cr) 样例,如下图:
    在这里插入图片描述
  2. UYVY:此格式与 YUY2 相同,只是字节顺序是与之相反的。
    在这里插入图片描述

3.3 4:2:0 格式

  1. IMC1:所有 Y Y Y 样例都会作为不带正负号的 char 值组成的数组首先存储在内存中。后面跟着存储所有 V ( C r ) V(C_r) V(Cr) 样例,然后是所有 U ( C b ) U(C_b) U(Cb) 样例。 V V V U U U 平面与 Y Y Y 平面具有相同的跨距(即存储数组的宽度),从而遗留了如下图所示的未使用的内存区域。
    在这里插入图片描述

  2. IMC3:此格式与 IMC1 相同,只是 U U U V V V 平面进行了交换:
    在这里插入图片描述

  3. IMC2:此格式与 IMC1 相同,只是 V ( C r ) V(C_r) V(Cr) U ( C b ) U(C_b) U(Cb) 行在半跨距边界处进行了交错。换句话说,就是色度区域中的每个完整跨距行都以一行 V V V 样例开始,然后是一行在下一个半跨距边界处开始的 U U U 样例:
    在这里插入图片描述
    此布局与 IMC1 相比,IMC2 能够更加高效地利用存储空间。它的色度存储空间缩小了一半,因此整体存储空间缩小了 25%。在各个 4:2:0 格式中,IMC2 是第二首选格式,排在 NV12 之后。

  4. IMC4:此格式与 IMC2 相同,只是 U ( C b ) U(C_b) U(Cb) V ( C r ) V(C_r) V(Cr) 行进行了交换:
    在这里插入图片描述

  5. NV12: 所有 Y Y Y 样例都会作为由不带正负号的 char 值组成的数组首先存储在内存中,并且行数为偶数。 Y Y Y 平面后面紧接着一个由不带正负号的 char 值组成的数组,其中包含了打包的 U ( C b ) U(C_b) U(Cb) V ( C r ) V(C_r) V(Cr) 样例。
    在这里插入图片描述

  6. NV21: NV21 格式和 NV12 存储格式基本相同,只是 U V UV UV 存储位置互换。

  7. YU12: 也叫做 I420 格式,首先是所有 Y Y Y,然后是所有 U U U,最后是所有 V V V
    在这里插入图片描述也就是为什么 U U U V V V 看到的是四幅图像(如图中U1、U2、U3 和 U4、U5、U6相比在Y上是上下两行,而不是同一行,所以可以看到两张):
    在这里插入图片描述

  8. YV12: YV12 格式与 YU12 基本相同,首先是所有 Y Y Y 值,然后是所有 V V V 值,最后是所有 U U U 值。

4. YUV数据转换

  1. 4:2:2 -> 4:2:0 的有损压缩转换: Y Y Y 存储数据不变,对 U U U V V V 分量在行垂直下采样进行隔行抽样。
  2. 4:2:0 -> 4:2:2的补足转换: Y Y Y 存储数据不变,对 U U U V V V 分量在行垂直下采样进行隔行拷贝补足下一行色度数据。

5. NV12转RGB

r = y + (140 * (v-128))/100;  //r
g = y - (34 * (u-128))/100 - (71 * (v-128))/100; //g
b = y + (177 * (u-128))/100; //b
  • 17
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是将NV12格式的图像数据保存为YUV格式文件的C语言算法: ```c #include <stdio.h> // 定义NV12格式图像的宽和高 #define WIDTH 640 #define HEIGHT 480 // 将NV12格式的图像数据保存为YUV格式文件 void nv12_to_yuv(unsigned char* nv12_data, int nv12_size, const char* yuv_filename) { // 打开YUV格式文件 FILE* yuv_file = fopen(yuv_filename, "wb"); if (yuv_file == NULL) { printf("Error: Failed to open YUV file\n"); return; } // 计算Y分量和UV分量的大小 int y_size = WIDTH * HEIGHT; int uv_size = y_size / 2; // 写入Y分量到YUV文件 fwrite(nv12_data, 1, y_size, yuv_file); // 将UV分量写入到YUV文件 unsigned char* uv_data = nv12_data + y_size; for (int i = 0; i < uv_size; i += 2) { fwrite(&uv_data[i + 1], 1, 1, yuv_file); fwrite(&uv_data[i], 1, 1, yuv_file); } // 关闭YUV文件 fclose(yuv_file); } int main() { // 读取NV12格式的图像数据 FILE* nv12_file = fopen("input.nv12", "rb"); if (nv12_file == NULL) { printf("Error: Failed to open NV12 file\n"); return 1; } fseek(nv12_file, 0, SEEK_END); int nv12_size = ftell(nv12_file); fseek(nv12_file, 0, SEEK_SET); unsigned char* nv12_data = (unsigned char*)malloc(nv12_size); fread(nv12_data, 1, nv12_size, nv12_file); fclose(nv12_file); // 将NV12格式的图像数据保存为YUV格式文件 nv12_to_yuv(nv12_data, nv12_size, "output.yuv"); // 释放内存 free(nv12_data); return 0; } ``` 上述代码中,`nv12_data` 表示NV12格式的图像数据,`nv12_size` 表示数据大小,`yuv_filename` 表示保存的YUV格式文件名。函数 `nv12_to_yuv` 将NV12格式的图像数据转换为YUV格式并保存到文件中。在主函数中,先读取NV12格式的图像数据,然后调用 `nv12_to_yuv` 函数将NV12格式的数据转换为YUV格式并保存到文件中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泠山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值