//
最直接的(没有任何优化,直接按公式转换!)把RGB24转成YV12的算法
//
参数: 宽(w) 和高(h) 必须是 4对齐的!不然会有错误!
//
输出结果 YV12 格式:
//
y01 y02 y03 y04 - - - - - - - -
//
- - - - - - - - - - - -
//
- - - - - - - - - - - -
//
- - - - - - - - - - - -
//
- - - - - - - - - - - -
//
- - - - - - - - - - - -
//
- - - - - - - - - - - -
//
- - - - - - - - - - - -
//
v01 v02 - - - - - - - - - -
//
- - - - - - - - - - - -
//
u01 u02 - - - - - - - - - -
//
- - - - - - - - - - - -
![](http://blog.vckbase.com/Images/OutliningIndicators/None.gif)
![](http://blog.vckbase.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
typedef
struct
tagRGB24
{
unsigned char b;
unsigned char g;
unsigned char r;
}
RGB24;
![](http://blog.vckbase.com/Images/OutliningIndicators/None.gif)
![](http://blog.vckbase.com/Images/OutliningIndicators/None.gif)
void
HotRGB24_2_YV12(unsigned
char
*
yv12,unsigned
char
*
rgb24,
int
w,
int
h)
![](http://blog.vckbase.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
int iBufLen = w * h;
int i,j,vay,vau,vav;
unsigned char* cv; // 当前坐标的v(current v);
unsigned char* nv; // 在cv下一行的对应位置的 v;
unsigned char* cu; // 当前坐标的u(current u);
unsigned char* nu; // 在cu下一行的对应位置的 u;
unsigned char v01,v02,v11,v12,u01,u02,u11,u12; // 需要整合的相邻的4个象素 如下
![](http://blog.vckbase.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*
v01 v02 - - - -
v11 v12 - - - -
- - - - - -
u01 u02
u11 u12
*/
unsigned char* vv = new unsigned char[iBufLen]; // 每个RGB单位对应的V!
unsigned char* uu = new unsigned char[iBufLen]; // 每个RGB单位对应的U!
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
// 按标准算法从RGB24计算出所有YUV
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
RGB24 * pRGB = (RGB24*)rgb24;
unsigned char* y = yv12; // 这里直接用 yuv 缓冲。。省了copy了。
unsigned char* v = vv;
unsigned char* u = uu;
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
for(i = 0; i < h; i++)
![](http://blog.vckbase.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
for(j = 0; j < w; j++)
![](http://blog.vckbase.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
//Y = 0.299R + 0.587G + 0.114B
//U = -0.147R - 0.289G + 0.436B
//V = 0.615R - 0.515G - 0.100B
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
// 这个算法颜色不正啊。。
//vay = pRGB->r * 0.299 + pRGB->g * 0.587 + pRGB->b * 0.114; // 根据公式计算出Y
//vav = pRGB->r * 0.615 + pRGB->g * -0.515 + pRGB->b * -0.100; // 根据公式计算出V
//vau = pRGB->r * -0.147 + pRGB->g * -0.289 + pRGB->b * 0.436; // 根据公式计算出U
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
//Y = round( 0.256788 * R + 0.504129 * G + 0.097906 * B) + 16
//U = round(-0.148223 * R - 0.290993 * G + 0.439216 * B) + 128
//V = round( 0.439216 * R - 0.367788 * G - 0.071427 * B) + 128
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
// 好象这个算法颜色正,而且是MSDN中列出的算法
vay = 0.256788 * pRGB->r + 0.504129 * pRGB->g + 0.097906 * pRGB->b + 16;
vau = -0.148223 * pRGB->r - 0.290993 * pRGB->g + 0.439216 * pRGB->b + 128;
vav = 0.439216 * pRGB->r - 0.367788 * pRGB->g - 0.071427 * pRGB->b + 128;
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
*y = vay < 0 ? 0 : (vay > 255 ? 255: vay); // 如果Y小于0置换成0,如果Y大于255就置换成255
*v = vav < 0 ? 0 : (vav > 255 ? 255: vav); // 如果V小于0置换成0,如果V大于255就置换成255
*u = vau < 0 ? 0 : (vau > 255 ? 255: vau); // 如果U小于0置换成0,如果U大于255就置换成255
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
y++; // 移动到下一位!
v++;
u++;
pRGB++;
}
}
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
v = yv12 + iBufLen; // 记录成品YV12的V的位置
u = v + (iBufLen >> 2); // 记录成品YV12的U的位置
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
for(i = 0; i < h; i+=2) // 由于 V 和 U 只记录隔行的,所以 += 2;
![](http://blog.vckbase.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
cv = vv + i * w; // 取得第i 行的v;
nv = vv + (i + 1) * w; // 取得第i + 1 行的v
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
cu = uu + i * w; // 取得第i 行的u;
nu = uu + (i + 1) * w; // 取得第i + 1 行的u
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
for(j = 0; j < w; j+=2) // 由于 一躺循环 我们访问 两个 uu 或 vv 所以 += 2;
![](http://blog.vckbase.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
v01 = *(cv + j); // 取得第i 行的第j 个v的具体的值
v02 = *(cv + j + 1); // 取得第i 行的第j + 1 个v的具体的值
v11 = *(nv + j); // 取得第i + 1 行的第j 个v的具体的值
v12 = *(nv + j + 1); // 取得第i + 1 行的第j + 1 个v的具体的值
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
*v = (v01 + v02 + v11 + v12) / 4; // 取v01,v02,v11,v12的平均值给v
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
u01 = *(cu + j); // 取得第i 行的第j 个u的具体的值
u02 = *(cu + j + 1); // 取得第i 行的第j + 1 个u的具体的值
u11 = *(nu + j); // 取得第i + 1 行的第j 个u的具体的值
u12 = *(nu + j + 1); // 取得第i + 1 行的第j + 1 个u的具体的值
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
*u = (u01 + u02 + u11 + u12) / 4; // 取u01,u02,u11,u12的平均值给u
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
v++; // 移动到下一位!
u++;
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
}
}
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
delete [] vv;
delete [] uu;
![](http://blog.vckbase.com/Images/OutliningIndicators/InBlock.gif)
}
转载于:https://www.cnblogs.com/carekee/articles/2346807.html