学习记录:YUV420P数据格式加边框

项目场景:

接上文:[学习记录:RGBA格式数据加边框](https://blog.csdn.net/weixin_38978427/article/details/121064425) 参考文章:[视音频数据处理入门:RGB、YUV像素数据处理](https://blog.csdn.net/leixiaohua1020/article/details/50534150)

问题描述:

实现yuv420p数据添加边框。


实现:

  • m_width == m_SwsWidth && m_height == m_SwsHeight:
    这个是最简单的,不需要任何处理。
  • m_width == m_SwsWidth && m_height > m_SwsHeight:
    宽度相同,但是高度不匹配,需要对上下分别填充 m_width * (m_height - m_SwsHeight)/2 边框。
//copy data[start~( start + len)] from src
bool CopyUnsignedChar(unsigned char *dest, int &pos, unsigned char *src, int start, int len)
{
    if(start < 0 || len < 0)
    {
        printf("invalue.\n");
        return false;
    }
    for(int i = start; i < start + len; i ++)
    {
        dest[pos ++] = src[i];
    }
    return true;
}
/**
 * -------------
 * |    top    |
 * -------------
 * -------------
 * |    pic    |
 * -------------
 * -------------
 * |   buttom  |
 * -------------
 */ 
 int diff_h     = m_height - m_SwsHeight;
 int diff_t     = diff_h/2;
 int diff_b     = diff_h - diff_t;

 //create top
 int top_s    = m_width * diff_t;
 int top_size = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, m_width, diff_t, 1);
 uint8_t *top = (uint8_t*)av_malloc(top_size);
 memset(top, 0, m_width * diff_t);//Y:black
 memset(top + m_width * diff_t, 128, m_width * diff_t / 2); //UV:设置128 透明

 //buttom
 int buttom_s    = m_width * diff_b;
 int buttom_size = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, m_width, diff_b, 1);
 uint8_t *buttom = (uint8_t*)av_malloc(buttom_size);
 memset(buttom, 0, m_width * diff_b);
 memset(buttom + m_width * diff_b, 128, m_width * diff_b / 2);

 //pic
 int pic_s = m_width * m_SwsHeight;
 int pos = 0;//标记图片数据的当前位置
 //Y
 //top
 CopyUnsignedChar(m_picture_buf2, pos, top, 0, top_s);
 //pic
 CopyUnsignedChar(m_picture_buf2, pos, picture_buf, 0, pic_s);
 //buttom
 CopyUnsignedChar(m_picture_buf2, pos, buttom, 0, buttom_s);

 //U
 pos = m_width * m_height;
 //top
 CopyUnsignedChar(m_picture_buf2, pos, top, top_s, top_s/4);
 //pic
 CopyUnsignedChar(m_picture_buf2, pos, picture_buf, pic_s, pic_s/4);
 //buttom
 CopyUnsignedChar(m_picture_buf2, pos, buttom, buttom_s, buttom_s/4);

 //V
 pos = m_width * m_height * 5/4;
 //top
 CopyUnsignedChar(m_picture_buf2, pos, top, top_s * 5 / 4, top_s/4);
 //pic
 CopyUnsignedChar(m_picture_buf2, pos, picture_buf, pic_s * 5 / 4, pic_s/4);
 //buttom
 CopyUnsignedChar(m_picture_buf2, pos, buttom, buttom_s * 5 / 4, buttom_s/4);

 av_free(top);
 av_free(buttom);
  • m_width > m_SwsWidth && m_height == m_SwsHeight:
    高度相同,但是宽度不匹配,需要对左右分别填充 (m_width - m_SwsWidth )/2 * m_height 边框。
/**
 * |--left--||--pic--||--right--|
 */ 
 int diff_w    = m_width - m_SwsWidth;
 int diff_l    = diff_w/2;
 int diff_r    = diff_w - diff_l;
 int pos	   = 0;//记录图片当前位置

 //left
 int left_uv_w = diff_l/2;
 int left_size = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, diff_l, m_height, 1);
 uint8_t *left = (uint8_t*)av_malloc(left_size);
 memset(left, 0, diff_l * m_height);
 memset(left + diff_l * m_height, 128, diff_l * m_height / 2);

 //right
 int right_uv_w = diff_r/2;
 int right_size = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, diff_r, m_height, 1);
 uint8_t *right = (uint8_t*)av_malloc(right_size);
 memset(right, 0, diff_r * m_height);
 memset(right + diff_r * m_height, 128, diff_r * m_height / 2);

 //combination:left==>>m_picture==>>right
 //Y
 for(int i = 0; i < m_height; i ++)
 {
     //left
     CopyUnsignedChar(m_picture_buf2, pos, left, i * diff_l, diff_l);
     //picture_buf
     CopyUnsignedChar(m_picture_buf2, pos, picture_buf, i * m_SwsWidth, m_SwsWidth);
     //right
     CopyUnsignedChar(m_picture_buf2, pos, right, i * diff_r, diff_r);
 }

 printf("pos = %d, total:%d.\n", pos, m_width * m_height);

 //U
 for(int i = 0; i < m_height / 2; i ++)
 {
     //left
     CopyUnsignedChar(m_picture_buf2, pos, left, i * left_uv_w + diff_l * m_height, left_uv_w);
     //picture_buf
     CopyUnsignedChar(m_picture_buf2, pos, picture_buf, i * m_SwsWidth/2 + m_SwsWidth * m_height, m_SwsWidth/2);
     //right
     CopyUnsignedChar(m_picture_buf2, pos, right, i * right_uv_w + diff_r * m_height, right_uv_w);
 }

 //V
 for(int i = 0; i < m_height / 2; i ++)
 {
     //left
     CopyUnsignedChar(m_picture_buf2, pos, left, i * left_uv_w + diff_l * m_height * 5 / 4, left_uv_w);
     //m_picture_buf
     CopyUnsignedChar(m_picture_buf2, pos, picture_buf, i * m_SwsWidth/2 + m_SwsWidth * m_height * 5 / 4, m_SwsWidth/2);
     //right
     CopyUnsignedChar(m_picture_buf2, pos, right, i * right_uv_w + diff_r * m_height * 5 / 4, right_uv_w);
 }

 av_free(left);
 av_free(right);
  • m_width > m_SwsWidth && m_height > m_SwsHeight:
    宽度和高度不匹配,需要对上下m_width * (m_height - m_SwsHeight)/2 边框,左右 (m_width - m_SwsWidth )/2 * m_SwsHeight。
/**
 * |----------------------top-----------------------|
 * |--left--||------------pic------------||--right--|
 * |-------------------buttom-----------------------|
 */ 
 //top & buttom 's height
 int diff_h      = m_height - m_SwsHeight;
 int diff_top    = diff_h/2;
 int diff_buttom = diff_h - diff_top;
 //left & right 's width
 int diff_w        = m_width - m_SwsWidth;
 int diff_left_w   = diff_w/2;
 int diff_right_w  = diff_w - diff_left_w;
 //left & right 's height
 int diff_left_h = m_SwsHeight;
 int diff_right_h = m_SwsHeight;

 int row = 0;//pic_buf flag

 //for Y
 uint8_t* data_y = (uint8_t*)av_malloc(m_width * m_height);
 row = 0;
 for(int i = 0; i < m_height; i ++)
 {
     for(int j = 0; j < m_width; j++)
     {
         if( j < diff_left_w || j >= (diff_left_w + m_SwsWidth) || i < diff_top || i >= (diff_top + m_SwsHeight))
         {
             data_y[i * m_width + j] = 0;//black
         }else
         {
             data_y[i * m_width + j] = picture_buf[row ++];
         }
     }
 }

 //for U
 row = m_SwsWidth * m_SwsHeight;
 uint8_t *data_u = (uint8_t*)av_malloc(m_width * m_height/4);
 for(int i = 0; i < m_height/2; i ++)
 {
     for(int j = 0 ; j < m_width/2; j ++)
     {
         if(j < diff_left_w/2 || j >= (diff_left_w/2 + m_SwsWidth/2) || i < diff_top/2 || i >= (diff_top/2 + m_SwsHeight/2))
         {
             data_u[i * m_width/2 + j] = 128;//透明
         }else
         {
             data_u[i * m_width/2 + j] = picture_buf[row ++];
         }
     }
 }

 //for V
 row = m_SwsWidth * m_SwsHeight * 5 / 4;
 uint8_t *data_v = (uint8_t*)av_malloc(m_width * m_height/4);
 for(int i = 0; i < m_height/2; i ++)
 {
     for(int j = 0 ; j < m_width/2; j ++)
     {
         if(j < diff_left_w/2 || j >= (diff_left_w/2 + m_SwsWidth/2) || i < diff_top/2 || i >= (diff_top/2 + m_SwsHeight/2))
         {
             data_v[i * m_width/2 + j] = 128;
         }else
         {
             data_v[i * m_width/2 + j] = picture_buf[row ++];
         }
     }
 }

 //copy to m_picture_buf2
 memcpy(m_picture_buf2, data_y, m_width * m_height);
 memcpy(m_picture_buf2 + m_width * m_height, data_u, m_width * m_height / 4);
 memcpy(m_picture_buf2 + m_width * m_height * 5 / 4, data_v, m_width * m_height / 4);
 //free
 av_free(data_y);
 av_free(data_u);
 av_free(data_v);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值