YUV格式学习:NV16和YUV422P格式互换

其实以前也实现过SP转P的格式,现在再完善一些,写成此文。由于是相同采样空间的转换,只是个别分量位置的调整,只要明白了Y、U、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
79
80
81
82
/**
yyyy yyyy
uv uv
->
yyyy yyyy
uu
vv
*/
void yuv422sp_to_yuv422p(unsigned char* yuv422sp, unsigned char* yuv422p, int width, int height)
{
int i, j;
int y_size;
int uv_size;
unsigned char* p_y1;
unsigned char* p_uv;

unsigned char* p_y2;
unsigned char* p_u;
unsigned char* p_v;

y_size = uv_size = width * height;

p_y1 = yuv422sp;
p_uv = yuv422sp + y_size;

p_y2 = yuv422p;
p_u = yuv422p + y_size;
p_v = p_u + width * height / 2;

memcpy(p_y2, p_y1, y_size);

for (j = 0, i = 0; j < uv_size; j+=2, i++)
{
p_u[i] = p_uv[j];
p_v[i] = p_uv[j+1];
}
}

/**
yyyy yyyy
uu
vv
->
yyyy yyyy
uv uv
*/
void yuv422p_to_yuv422sp(unsigned char* yuv422p, unsigned char* yuv422sp, int width, int height)
{
int i, j;
int y_size;
int uv_size;
unsigned char* p_y1;
unsigned char* p_uv;

unsigned char* p_y2;
unsigned char* p_u;
unsigned char* p_v;

y_size = uv_size = width * height;

p_y1 = yuv422p;

p_y2 = yuv422sp;
p_u = p_y1 + y_size;
p_v = p_u + width * height / 2;

p_uv = p_y2 + y_size;

memcpy(p_y2, p_y1, y_size);

for (j = 0, i = 0; j < uv_size; j+=2, i++)
{
// 此处可调整U、V的位置,变成NV16或NV61
#if 01
p_uv[j] = p_u[i];
p_uv[j+1] = p_v[i];
#else
p_uv[j] = p_v[i];
p_uv[j+1] = p_u[i];
#endif
}
}

李迟 2015.8.5 晚上