• yuyv转yuv420p代码及验证代码


    另一篇博客《YUV格式介绍》有yuyv和yuv420p的理论介绍,本篇博客为具体转换的实际代码以及验证用的代码,代码均来源于其他博客,经实际验证有效,在此记录防止遗忘。

    yuyv转yuv420p:

    unsigned char *yuyv_buf = (unsigned char *)malloc(2 * width * height * sizeof(unsigned char));
    unsigned char *yuv420_buf = (unsigned char *)malloc(3 * width * height / 2 * sizeof(unsigned char));
    
    int yuyv_to_yuv420p(const unsigned char *in, unsigned char *out, unsigned int width, unsigned int height)
    {
        unsigned char *y = out;
        unsigned char *u = out + width*height;
        unsigned char *v = out + width*height + width*height/4;
     
        unsigned int i,j;
        unsigned int base_h;
        unsigned int is_y = 1, is_u = 1;
        unsigned int y_index = 0, u_index = 0, v_index = 0;
     
        unsigned long yuv422_length = 2 * width * height;
     
        //序列为YU YV YU YV,一个yuv422帧的长度 width * height * 2 个字节
        //丢弃偶数行 u v
        for(i=0; i<yuv422_length; i+=2){
            *(y+y_index) = *(in+i);
            y_index++;
        }
        for(i=0; i<height; i+=2){
            base_h = i*width*2;
            for(j=base_h+1; j<base_h+width*2; j+=2) {
                if(is_u){
                    *(u+u_index) = *(in+j);
                    u_index++;
                    is_u = 0;
                }else{
                    *(v+v_index) = *(in+j);
                    v_index++;
                    is_u = 1;
                }
            }
        }
        return 1;
    }

    验证的话只需要将数据转换成rgb看是否正长即可知道转换是否有问题:

    yuyv转rgb:

    void yuyv_to_rgb(unsigned char* yuv,unsigned char* rgb)
    {
        unsigned int i;
        unsigned char* y0 = yuv + 0;   
        unsigned char* u0 = yuv + 1;
        unsigned char* y1 = yuv + 2;
        unsigned char* v0 = yuv + 3;
     
        unsigned  char* r0 = rgb + 0;
        unsigned  char* g0 = rgb + 1;
        unsigned  char* b0 = rgb + 2;
        unsigned  char* r1 = rgb + 3;
        unsigned  char* g1 = rgb + 4;
        unsigned  char* b1 = rgb + 5;
       
        float rt0 = 0, gt0 = 0, bt0 = 0, rt1 = 0, gt1 = 0, bt1 = 0;
     
        for(i = 0; i <= (WIDTH * HEIGHT) / 2 ;i++)
        {
            bt0 = 1.164 * (*y0 - 16) + 2.018 * (*u0 - 128); 
            gt0 = 1.164 * (*y0 - 16) - 0.813 * (*v0 - 128) - 0.394 * (*u0 - 128); 
            rt0 = 1.164 * (*y0 - 16) + 1.596 * (*v0 - 128); 
       
            bt1 = 1.164 * (*y1 - 16) + 2.018 * (*u0 - 128); 
            gt1 = 1.164 * (*y1 - 16) - 0.813 * (*v0 - 128) - 0.394 * (*u0 - 128); 
            rt1 = 1.164 * (*y1 - 16) + 1.596 * (*v0 - 128); 
        
          
                       if(rt0 > 250)      rt0 = 255;
            if(rt0< 0)        rt0 = 0;    
     
            if(gt0 > 250)     gt0 = 255;
            if(gt0 < 0)    gt0 = 0;    
     
            if(bt0 > 250)    bt0 = 255;
            if(bt0 < 0)    bt0 = 0;    
     
            if(rt1 > 250)    rt1 = 255;
            if(rt1 < 0)    rt1 = 0;    
     
            if(gt1 > 250)    gt1 = 255;
            if(gt1 < 0)    gt1 = 0;    
     
            if(bt1 > 250)    bt1 = 255;
            if(bt1 < 0)    bt1 = 0;    
                        
            *r0 = (unsigned char)rt0;
            *g0 = (unsigned char)gt0;
            *b0 = (unsigned char)bt0;
        
            *r1 = (unsigned char)rt1;
            *g1 = (unsigned char)gt1;
            *b1 = (unsigned char)bt1;
     
            yuv = yuv + 4;
            rgb = rgb + 6;
            if(yuv == NULL)
              break;
     
            y0 = yuv;
            u0 = yuv + 1;
            y1 = yuv + 2;
            v0 = yuv + 3;
      
            r0 = rgb + 0;
            g0 = rgb + 1;
            b0 = rgb + 2;
            r1 = rgb + 3;
            g1 = rgb + 4;
            b1 = rgb + 5;
        }   
    }

    yuv420p转rgb:

    bool YV12ToBGR24_FFmpeg(unsigned char* pYUV,unsigned char* pBGR24,int width,int height)
    {
        if (width < 1 || height < 1 || pYUV == NULL || pBGR24 == NULL)
            return false;
        //int srcNumBytes,dstNumBytes;
        //uint8_t *pSrc,*pDst;
        AVPicture pFrameYUV,pFrameBGR;
        
        //pFrameYUV = avpicture_alloc();
        //srcNumBytes = avpicture_get_size(PIX_FMT_YUV420P,width,height);
        //pSrc = (uint8_t *)malloc(sizeof(uint8_t) * srcNumBytes);
        avpicture_fill(&pFrameYUV,pYUV,PIX_FMT_YUV420P,width,height);
    
        //U,V互换
        uint8_t * ptmp=pFrameYUV.data[1];
        pFrameYUV.data[1]=pFrameYUV.data[2];
        pFrameYUV.data [2]=ptmp;
    
        //pFrameBGR = avcodec_alloc_frame();
        //dstNumBytes = avpicture_get_size(PIX_FMT_BGR24,width,height);
        //pDst = (uint8_t *)malloc(sizeof(uint8_t) * dstNumBytes);
        avpicture_fill(&pFrameBGR,pBGR24,PIX_FMT_BGR24,width,height);
    
        struct SwsContext* imgCtx = NULL;
        imgCtx = sws_getContext(width,height,PIX_FMT_YUV420P,width,height,PIX_FMT_BGR24,SWS_BILINEAR,0,0,0);
    
        if (imgCtx != NULL){
            sws_scale(imgCtx,pFrameYUV.data,pFrameYUV.linesize,0,height,pFrameBGR.data,pFrameBGR.linesize);
            if(imgCtx){
                sws_freeContext(imgCtx);
                imgCtx = NULL;
            }
            return true;
        }
        else{
            sws_freeContext(imgCtx);
            imgCtx = NULL;
            return false;
        }
    }

    拿到RGB数据后可以用Qt的QImage类保存成本地图片文件以查验转换是否成功。

  • 相关阅读:
    为什么在SqlServer流水模式下,事务无法启动?
    默认web站点被删除,如何设置新的默认站点?
    用C#实现基于TCP协议的网络通讯
    如何通过DataRelation关联两个DataGrid,实现主从表。
    如何设置网站的会话时间?
    性能测试基本概念释疑
    C#中如何获取服务器IP,名称,操作系统,客户端IP,名称!
    DataGridComboBoxColumn控件
    端口基础知识
    P2P之UDP穿透NAT的原理与实现
  • 原文地址:https://www.cnblogs.com/gisvito/p/12881502.html
Copyright © 2020-2023  润新知