YUV格式学习:YUYV、YVYU、UYVY、VYUY格式转换成RGB24

前面文章讲过题目中的YUYV、YVYU、UYVY、VYUY格式,它们都是YUV422的打包格式——即在内存中,Y、U、V都是挨着排序的。它们的名称就表示了Y、U、V的顺序。像YUYV,就是Y、U、Y、V、Y、U、Y、V。在做转换时,就显得很容易、简单了。

因为极其相近,故在将这几种格式全部封装到一个函数里做。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
void yuv422packed_to_rgb24(YUV_TYPE type, unsigned char* yuv422p, unsigned char* rgb, int width, int height)
{
int y, cb, cr;
int r, g, b;
int i = 0;
unsigned char* p;
unsigned char* p_rgb;

p = yuv422p;

p_rgb = rgb;

init_yuv422p_table();

for (i = 0; i < width * height / 2; i++)
{
switch(type)
{
case FMT_YUYV:
y = p[0];
cb = p[1];
cr = p[3];
break;
case FMT_YVYU:
y = p[0];
cr = p[1];
cb = p[3];
break;
case FMT_UYVY:
cb = p[0];
y = p[1];
cr = p[2];
break;
case FMT_VYUY:
cr = p[0];
y = p[1];
cb = p[2];
break;
default:
break;
}

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

// 此处可调整RGB排序,BMP图片排序为BGR
// 默认排序为:RGB
p_rgb[0] = r;
p_rgb[1] = g;
p_rgb[2] = b;

switch(type)
{
case FMT_YUYV:
case FMT_YVYU:
y = p[2];
break;
case FMT_UYVY:
case FMT_VYUY:
y = p[3];
break;
default:
break;
}

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[3] = r;
p_rgb[4] = g;
p_rgb[5] = b;

p += 4;
p_rgb += 6;
}
}

在做转换时,要注意YUV422采样格式,2个Y共用1个U和1个V,因此每一次循环就是读取1个Y、1个U和V转换成R、G、B,再读取下一个Y、U、V。由于UV共用,所以第2次转换时不用再给U、V赋值了。
综上,代码依然十分简单。

2015.8.5 晚上 李迟