首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 媒体动画 > 多媒体 >

RGB24转成YV12,然后进行x264编码,图像失真解决思路

2013-01-25 
RGB24转成YV12,然后进行x264编码,图像失真将采集到的RGB24转成YV12,然后进行x264编码,图像失真,图像为相册

RGB24转成YV12,然后进行x264编码,图像失真
将采集到的RGB24转成YV12,然后进行x264编码,图像失真,图像为相册内的"失真"。
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个象素 如下
    
    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

 

            //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 =  int(0.256788 * pRGB->r + 0.504129 * pRGB->g + 0.097906 * pRGB->b) +  16;
            vau = int(-0.148223 * pRGB->r - 0.290993 * pRGB->g + 0.439216 * pRGB->b) + 128;


            vav =  int(0.439216 * pRGB->r - 0.367788 * pRGB->g - 0.071427 * pRGB->b) + 128;

            *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

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

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

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

            v++;    // 移动到下一位!
            u++;
         }
     }
    delete [] vv;
    delete [] uu;
}
这段代码是从网上找的,是不是有什么问题?
[解决办法]
转换本来就是有损的

热点排行