RGB24转YV12(按公式转,没有任何优化)

//  最直接的(没有任何优化,直接按公式转换!)把RGB24转成YV12的算法
//  参数: 宽(w) 和高(h) 必须是 4对齐的!不然会有错误!
//  输出结果 YV12 格式:
//  y01 y02 y03 y04 -   -   -   -   -   -   -   -
//  -   -   -   -   -   -   -   -   -   -   -   -
//  -   -   -   -   -   -   -   -   -   -   -   -
//  -   -   -   -   -   -   -   -   -   -   -   -
//  -   -   -   -   -   -   -   -   -   -   -   -
//  -   -   -   -   -   -   -   -   -   -   -   -
//  -   -   -   -   -   -   -   -   -   -   -   -
//  -   -   -   -   -   -   -   -   -   -   -   -
//  v01 v02 -   -   -   -   -   -   -   -   -   -
//  -   -   -   -   -   -   -   -   -   -   -   -
//  u01 u02 -   -   -   -   -   -   -   -   -   -
//  -   -   -   -   -   -   -   -   -   -   -   -


typedef 
struct  tagRGB24 {
        unsigned 
char    b;
        unsigned 
char    g;
        unsigned 
char    r;
}
 RGB24;


void  HotRGB24_2_YV12(unsigned  char *  yv12,unsigned  char *  rgb24, int  w, int  h)
{
    
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个象素 如下
    /**//*
    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!

    
// 按标准算法从RGB24计算出所有YUV

    RGB24 
* pRGB = (RGB24*)rgb24;
    unsigned 
char* y = yv12;                                // 这里直接用 yuv 缓冲。。省了copy了。
    unsigned char* v = vv;
    unsigned 
char* u = uu;

    
for(i = 0; i < h; i++)
    
{
        
for(j = 0; j < w; j++)
        
{

            
//Y =   0.299R + 0.587G + 0.114B
            
//U =  -0.147R - 0.289G + 0.436B
            
//V =   0.615R - 0.515G - 0.100B

            
// 这个算法颜色不正啊。。
            
//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


            
//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


            
// 好象这个算法颜色正,而且是MSDN中列出的算法
            vay =  0.256788 * pRGB->+ 0.504129 * pRGB->+ 0.097906 * pRGB->+  16;
            vau 
= -0.148223 * pRGB->- 0.290993 * pRGB->+ 0.439216 * pRGB->+ 128;
            vav 
=  0.439216 * pRGB->- 0.367788 * pRGB->- 0.071427 * pRGB->+ 128;


            
*=  vay < 0 ? 0 : (vay > 255 ? 255: vay);                        // 如果Y小于0置换成0,如果Y大于255就置换成255
            *=  vav < 0 ? 0 : (vav > 255 ? 255: vav);                        // 如果V小于0置换成0,如果V大于255就置换成255
            *=  vau < 0 ? 0 : (vau > 255 ? 255: vau);                        // 如果U小于0置换成0,如果U大于255就置换成255

            y
++;    // 移动到下一位!
            v++;
            u
++;
            pRGB
++;
        }

    }


    v 
= yv12 + iBufLen;                                // 记录成品YV12的V的位置
    u = v    + (iBufLen >> 2);                        // 记录成品YV12的U的位置

    
for(i = 0; i < h; i+=2)                            // 由于 V 和 U 只记录隔行的,所以 += 2;
    {
        cv 
= vv + i * w;                            // 取得第i     行的v;
        nv = vv + (i + 1* w;                        // 取得第i + 1 行的v

        cu 
= uu + i * w;                            // 取得第i     行的u;
        nu = uu + (i + 1* w;                        // 取得第i + 1 行的u


        
for(j = 0; j < w; j+=2)                        // 由于 一躺循环 我们访问 两个 uu 或 vv 所以 += 2;
        {
            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的具体的值

            
*= (v01 + v02 + v11 + v12) / 4;        // 取v01,v02,v11,v12的平均值给v


            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的具体的值

            
*= (u01 + u02 + u11 + u12) / 4;        // 取u01,u02,u11,u12的平均值给u

            v
++;    // 移动到下一位!
            u++;

        }

    }


    delete [] vv;
    delete [] uu;

}

转载于:https://www.cnblogs.com/carekee/articles/2346807.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值