YUV格式学习:YUV444转换RGB24
YUV格式有很多种,按其采样方式,有444、422、420,还有411(但不常见)。针对数据的排序,又有平面格式和打包格式,还有“踢啊”特有的半平面格式——这些排列组合,就显得YUV格式多种多样,初看起来杂乱无章,但只要用心,就能理出头绪。像我,也是花了很多时间去慢慢搜索才真正理解。有时间会系统整理几篇文章出来,也会实践一下。
YUV444格式没有进行压缩,占用空间为with*height*3,与RGB占用空间相同。因此在转换上也很方便,但很多编码器似乎不太支持该格式。或许和其占用空间有莫大的关联吧。
首先给出生成查询表格的函数,代码是在网上找来的,如下:
#ifndef MAX #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif #ifndef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif static long U[256], V[256], Y1[256], Y2[256]; void init_yuv422p_table(void) { int i; static int init = 0; if (init == 1) return; // Initialize table for (i = 0; i < 256; i++) { V[i] = 15938 * i - 2221300; U[i] = 20238 * i - 2771300; Y1[i] = 11644 * i; Y2[i] = 19837 * i - 311710; } init = 1; }
在转换成RGB之前,要调用上述函数。下面是YUV444转换成RGB24的函数实现:
void yuv4444_to_rgb24(unsigned char *yuv, unsigned char *rgb, int width, int height) { int y, cb, cr; int r, g, b; int i = 0; unsigned char* p_y; unsigned char* p_u; unsigned char* p_v; unsigned char* p_rgb; p_y = yuv; p_u = yuv+width*height; p_v = yuv+2*width*height; p_rgb = rgb; init_yuv422p_table(); for (i = 0; i < width * height; i++) { y = p_y[0]; cb = p_u[0]; cr = p_v[0]; //yuv2rgb(y, cb, cr, &r, &g, &b); //yuv2rgb_1(y, cb, cr, &r, &g, &b); r = MAX (0, MIN (255, (V[cr] + Y1[y])/10000)); //R value b = MAX (0, MIN (255, (U[cb] + Y1[y])/10000)); //B value g = MAX (0, MIN (255, (Y2[y] - 5094*(r) - 1942*(b))/10000)); //G value p_rgb[0] = r; p_rgb[1] = g; p_rgb[2] = b;; p_rgb += 3; p_y++; p_u++; p_v++; } }
从代码看到,实际上就是扫描YUV444的内存,得到Y、U、V的分量,然后查表得到对应用R、G、B值,再赋值给RGB内存指针。如前所述,YUV444与RGB占用空间相同,故在代码并无太多的技巧。
李迟 2015.8.5 晚上
近来经济拮据,如本文对阁下有帮助,可慷慨解囊赞助笔者以输出更多好文章。
[email protected] 或 微信fly_camel_fly 均可。感谢!
本文固定链接: /my-study/yuv-learning-yuv444-to-rgb24.html