YUV420-RGB 以点的方式进行转换 原创by: GanYJ
C++代码
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
//YUV420-RGB 以点的方式进行转换 原创by: GanYJ
//可能的问题:在不同的计算机上,显示的色彩有问题,我试了几种算法,还是无法还原
struct
mRGB
{ unsigned
char
R;
unsigned
char
G;
unsigned
char
B;
};
mRGB tempRGB[4];
void
ConvertPointYUV2RGB(unsigned
char
*pFramBeg,
int
x,
int
y,
int
width,
int
height)
{
unsigned
char
YUV_Y;
unsigned
char
YUV_U;
unsigned
char
YUV_V;
unsigned
char
*pTemp[4];
//一次计算4个像素
//4个像素共用一个UV值,只取一次值
pTemp[0]=pFramBeg+height*width+(y/2)*(width)/2+(x/2);
// =INT(y/2)*width+INT(x/2)*2 //计算U地址
YUV_V=*pTemp[0];
//取U
pTemp[0]=pTemp[0]+(height*width)/4;
//加上前半部UV分量的长度,即是后部指针
YUV_U=*(pTemp[0]);
if
(YUV_U>=128)
YUV_U=YUV_U-128;
else
YUV_U=128-YUV_U;
if
(YUV_V>=128)
YUV_V=YUV_V-128;
else
YUV_V=128-YUV_V;
//取4个点的Y值
pTemp[0]=pFramBeg+y*width+x;
//指针计算
pTemp[1]=pFramBeg+y*width+x+1;
//指针计算
pTemp[2]=pFramBeg+(y+1)*width+x;
//指针计算
pTemp[3]=pFramBeg+(y+1)*width+x+1;
//指针计算
//计算4次
for
(
int
i=0;i<4;i++)
{ YUV_Y=*pTemp[i];
//取Y值
if
(YUV_Y>=16)
YUV_Y=YUV_Y-16;
else
YUV_Y=16-YUV_Y;
//计算并保存结果
tempRGB[i].R=((
int
)1000*(YUV_Y)+(
int
)1402*(YUV_V))/(
int
)1000;
tempRGB[i].G=((
int
)1000*(YUV_Y)-(
int
)344*(YUV_U)-(
int
)714*(YUV_V))/(
int
)1000;
tempRGB[i].B=((
int
)1000*(YUV_Y)+(
int
)1772*(YUV_U))/(
int
)1000;
}
}
unsigned
char
* YUV_2_RGB(unsigned
char
*YUV,
int
width,
int
height,
bool
snapbmp)
{
int
i,j;
unsigned
char
*yAddress;
unsigned
char
*pUV_Address_ahead_half;
unsigned
char
*pUV_Address_behend_half;
unsigned
char
* outBuffer=(unsigned
char
*)
malloc
(width*height*3);
unsigned
char
* g_pBits = (unsigned
char
*)
malloc
(width*height*3);
yAddress=YUV;
//指向数据帧的头,即Y分量
pUV_Address_ahead_half=YUV+width*height;
//UV分量的指向前半部。
pUV_Address_behend_half=pUV_Address_ahead_half+width*height/4;
//UV分量的指向后前半部。
//ConvertYUV2RGB( yAddress,pUV_Address_ahead_half,pUV_Address_behend_half,outBuffer,width,height);//转换
unsigned
char
*pTemp=outBuffer;
//X Y均以2的倍数进行处理,以点的方式转RGB
for
(j = 0; j < height; j=j+2)
{ pTemp=outBuffer+3*j*width;
for
(i = 0; i < width; i=i+2)
{
ConvertPointYUV2RGB(yAddress,i,j,width,height);
//i,j即点的X,Y坐标
*(pTemp+3*i)=tempRGB[0].R;
//4个点的结果,存入内存中
*(pTemp+3*i+1)=tempRGB[0].G;
*(pTemp+3*i+2)=tempRGB[0].B;
*(pTemp+3*i+3)=tempRGB[1].R;
*(pTemp+3*i+4)=tempRGB[1].G;
*(pTemp+3*i+5)=tempRGB[1].B;
*(pTemp+3*width+3*i)=tempRGB[2].R;
//4个点的结果,存入内存中
*(pTemp+3*width+3*i+1)=tempRGB[2].G;
*(pTemp+3*width+3*i+2)=tempRGB[2].B;
*(pTemp+3*width+3*i+3)=tempRGB[3].R;
*(pTemp+3*width+3*i+4)=tempRGB[3].G;
*(pTemp+3*width+3*i+5)=tempRGB[3].B;
}
}
pTemp=outBuffer;
for
(i=height-1,j=0; i>=0; i--,j++)
{
memcpy
(g_pBits+j*width*3,pTemp+i*width*3,width*3);
//将图像进行水平镜像 否则图像是颠倒的
}
free
(outBuffer);
return
g_pBits;
}
|