织梦CMS - 轻松建站从此开始!

罗索

RGB24转成YV12 和 YV12转成RGB

jackyhwei 发布于 2011-12-13 09:17 点击:次 
RGB24(RGB565)与YV12互相转换的最直接的(没有任何优化,直接按公式转换!)算法。
TAG:

// 最直接的(没有任何优化,直接按公式转换!)把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个象素 如下
   
    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->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;


            *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++;
         }
     }                   

      u = yv12 + iBufLen;                                // 记录成品YV12的U的位置    

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

    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;

 }

void yv12_to_rgb565_c2(int32_t * t_ptr, uint8_t * x_ptr,uint8_t * y_ptr)
{
int x, y;

uint8_t * u_ptr = y_ptr + 176672;
uint8_t * v_ptr = u_ptr + 49984;


for (y = 0; y < 288; y+=2)
{
   int r[2], g[2], b[2];
   r[0] = r[1] = g[0] = g[1] = b[0] = b[1] = 0;
for (x = 0; x < 352; x+=2)
{
int rgb_y;
int b_u0 = B_U_tab[ u_ptr[0] ];
int g_uv0 = G_U_tab[ u_ptr[0] ] + G_V_tab[ v_ptr[0] ];
int r_v0 = R_V_tab[ v_ptr[0] ];

rgb_y = RGB_Y_tab[ y_ptr[0] ];
b[0] = (b[0] & 0x7) + ((rgb_y + b_u0) >> SCALEBITS_OUT);
g[0] = (g[0] & 0x7) + ((rgb_y - g_uv0) >> SCALEBITS_OUT);
r[0] = (r[0] & 0x7) + ((rgb_y + r_v0) >> SCALEBITS_OUT);
*(uint16_t *) x_ptr =  MK_RGB565(r[0], g[0], b[0]);
rgb_y = RGB_Y_tab[ y_ptr[1] ];
b[0] = (b[0] & 0x7) + ((rgb_y + b_u0) >> SCALEBITS_OUT);
g[0] = (g[0] & 0x7) + ((rgb_y - g_uv0) >> SCALEBITS_OUT);
r[0] = (r[0] & 0x7) + ((rgb_y + r_v0) >> SCALEBITS_OUT);
*(uint16_t *) (x_ptr+2) = MK_RGB565(r[0], g[0], b[0]);

rgb_y = RGB_Y_tab[ y_ptr[480] ];
b[1] = (b[1] & 0x7) + ((rgb_y + b_u0) >> SCALEBITS_OUT);
g[1] = (g[1] & 0x7) + ((rgb_y - g_uv0) >> SCALEBITS_OUT);
r[1] = (r[1] & 0x7) + ((rgb_y + r_v0) >> SCALEBITS_OUT);
*(uint16_t *) (x_ptr+704) =  MK_RGB565(r[1], g[1], b[1]);
rgb_y = RGB_Y_tab[ y_ptr[481] ];
b[1] = (b[1] & 0x7) + ((rgb_y + b_u0) >> SCALEBITS_OUT);
g[1] = (g[1] & 0x7) + ((rgb_y - g_uv0) >> SCALEBITS_OUT);
r[1] = (r[1] & 0x7) + ((rgb_y + r_v0) >> SCALEBITS_OUT);
*(uint16_t *) (x_ptr+704+2)=  MK_RGB565(r[1], g[1], b[1]);

x_ptr += 4;
y_ptr += 2;
u_ptr += 1;
v_ptr += 1;
}
x_ptr += 352*2;    //704;
// x_ptr += 1600+1600 - 352*2;
y_ptr += 608;      //608; //128 + 480;
u_ptr += 64 ;  //64;
v_ptr += 64; //64;
}
}

(caiweihui)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201112/15465.html]
本文出处:blog.sina.com.cn/caiweihui 作者:caiweihui 原文
顶一下
(1)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容