YUV422的旋转

YUV422的旋转,其实就是将之当做YUV420一样进行旋转,即4个Y值,共享一组UV,这样旋转后,会损失一般的色度值。

不管你的decoder给你的什么鬼,或许是平面格式,或许是打包格式,反正就是两个Y值共享一组UV,那么旋转后,还得是两个Y值共享一组UV。


那么问题来了,你做的旋转使得以前垂直相邻的像素变成了水平相邻,而水平相邻的像素点需要共享UV数据,而旋转前这两个像素点没有任何关系,这个UV值从哪里来?

个最简单的例子,有4个像素点:

p1,p2

p3,p4

那么p1,p2共享一组U12,V12,p3,p4共享一组U34,V34,旋转以后呢?

这里以p2点为原点,逆时针90°:

p2,p4

p1,p3

Y值是一一对应的,其旋转不说了。可是UV呢?

这时p2,p4需要共享一组UV,p1,p3需要共享一组UV(你的screen或者encoder决定,你输出的视频数据必须要p2,p4共享一组UV,p1,p3共享一组UV),

但是旋转前,p2和p4,p1和p3一毛钱关系都木有啊!

那怎么办?那算了,没关系就没关系吧,就这样赋值吧(假设UV输出需要UVUVUVUV这样的序列):

U12,V12,U34,V34,

那么赋值出来的结果是什么?

video_width = video_width *2;

video_hight = video_hight/2;

那么好吧,我随便赋值得了,反正没人管我,但是UV值都是相互配合才能表示一个像素点的,那咋整呢!?

好吧,算了,我妥协了,索性:

Y1和Y2,Y3和Y4都对应U12,V12。

画面不清晰就算了,至少色彩正了。

但是效率问题来了,对于一个720*480视频中的一块464 * 380的区域,进行左右90°旋转,耗时是内存拷贝该区域的4倍。

我试用了查找表的方式,徒劳,依然是4倍......





以下是将 YUV422 平面格式数据旋转 270 度的 C 代码实现: ```c void rotate_yuv422p270(unsigned char *src, unsigned char *dst, int width, int height) { int i, j, k, l; int src_y_index, src_uv_index, dst_y_index, dst_uv_index; unsigned char *src_y, *src_u, *src_v, *dst_y, *dst_u, *dst_v; unsigned char y1, y2, u, v; // 计算旋转后图像的宽高 int dst_width = height; int dst_height = width; // 计算 Y、U、V 平面的大小 int src_y_size = width * height; int src_uv_size = width * height / 2; int dst_y_size = dst_width * dst_height; int dst_uv_size = dst_width * dst_height / 2; // 分配内存 src_y = src; src_u = src + src_y_size; src_v = src_u + src_uv_size; dst_y = dst; dst_u = dst + dst_y_size; dst_v = dst_u + dst_uv_size; // 旋转 Y 平面 for (i = 0; i < height; i++) { for (j = 0; j < width; j += 2) { src_y_index = i * width + j; dst_y_index = (dst_width - j / 2 - 1) * dst_width + i; y1 = src_y[src_y_index]; y2 = src_y[src_y_index + 1]; dst_y[dst_y_index] = y1; dst_y[dst_y_index - dst_width] = y2; } } // 旋转 U、V 平面 for (i = 0; i < height / 2; i++) { for (j = 0; j < width; j += 2) { src_uv_index = i * width + j; dst_uv_index = (dst_width - j / 2 - 1) * dst_width / 2 + i / 2; u = src_u[src_uv_index]; v = src_v[src_uv_index]; dst_u[dst_uv_index] = u; dst_v[dst_uv_index] = v; } } } ``` 这段代码中,首先计算旋转后图像的宽高和 YUV422 平面格式的大小,然后将 Y、U、V 平面的指针分别指向输入和输出数据中对应的位置。 接下来,通过双重循环逐个像素地将输入数据中的像素复制到输出数据中,并且根据旋转方向调整像素的位置和顺序。具体来说,对于 Y 平面,每次处理两个像素,将第一个像素复制到输出数据的最后一列、第一行中,将第二个像素复制到输出数据的倒数第二列、第二行中。对于 U、V 平面,每次处理一个像素,将其复制到输出数据中对应的位置上。 最后,输出数据中的 YUV422 平面格式数据就是旋转后的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值