ffmpeg 对图像数据格式以及图片缩放

8 篇文章 0 订阅

利用ffmpeg进行图像数据格式的转换以及图片的缩放应用中,主要用到了swscale.h文件中的三个函数,分别是:

     struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,
                               int dstW, int dstH, enum AVPixelFormat dstFormat,
                               int flags, SwsFilter *srcFilter,
                               SwsFilter *dstFilter, const double *param);
     int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],
     const int srcStride[], int srcSliceY, int srcSliceH,
                   uint8_t *const dst[], const int dstStride[]); 
 void sws_freeContext(struct SwsContext *swsContext);

sws_getContext函数可以看做是初始化函数,它的参数定义分别为:

  int srcW,int srcH 为原始图像数据的高和宽;

  int dstW,int dstH 为输出图像数据的高和宽;

  enum AVPixelFormat srcFormat 为输入和输出图片数据的类型;eg:AV_PIX_FMT_YUV420、PAV_PIX_FMT_RGB24;

  int flags 为scale算法种类;eg:SWS_FAST_BILINEAR,SWS_BICUBIC、SWS_BICUBLIN、SWS_POINT、SWS_SINC;

  SwsFilter *srcFilter ,SwsFilter *dstFilter,const double *param 可以不用管,全为NULL即可;

sws_scale函数则为执行函数,它的参数定义分别为:

  struct SwsContext *c 为sws_getContext函数返回的值;

  const uint8_t *const srcSlice[],uint8_t *const dst[] 为输入输出图像数据各颜色通道的buffer指针数组;

  const int srcStride[],const int dstStride[] 为输入输出图像数据各颜色通道每行存储的字节数数组;     

  int srcSliceY 为从输入图像数据的第多少列开始逐行扫描,通常设为0;

  int srcSliceH 为需要扫描多少行,通常为输入图像数据的高度;

sws_freeContext函数为结束函数,它的参数即为sws_getContext函数返回的值;

做一个实际缩放YUV420函数打包实例如下:

int ScaleImg(AVCodecContext *pCodecCtx,AVFrame *src_picture,AVFrame *dst_picture,int nDstH ,int nDstW )
{
int i ;
int nSrcStride[3];
int nDstStride[3];
int nSrcH = pCodecCtx->height;
int nSrcW = pCodecCtx->width;
struct SwsContext* m_pSwsContext;


uint8_t *pSrcBuff[3] = {src_picture->data[0],src_picture->data[1], src_picture->data[2]};


nSrcStride[0] = nSrcW ;
nSrcStride[1] = nSrcW/2 ;
nSrcStride[2] = nSrcW/2 ;




dst_picture->linesize[0] = nDstW;
dst_picture->linesize[1] = nDstW / 2;
dst_picture->linesize[2] = nDstW / 2;


printf("nSrcW%d\n",nSrcW);


m_pSwsContext = sws_getContext(nSrcW, nSrcH, PIX_FMT_YUV420P,
nDstW, nDstH, PIX_FMT_YUV420P,
SWS_BICUBIC,
NULL, NULL, NULL);


if (NULL == m_pSwsContext)
{
printf("ffmpeg get context error!\n");
exit (-1);
}


sws_scale(m_pSwsContext, src_picture->data,src_picture->linesize, 0, pCodecCtx->height,dst_picture->data,dst_picture->linesize);


printf("line0:%d line1:%d line2:%d\n",dst_picture->linesize[0] ,dst_picture->linesize[1] ,dst_picture->linesize[2]);
sws_freeContext(m_pSwsContext);


return 1 ;
}

函数很简单,申请环境初始指针,后缩放即可。读到此文的朋友,这个函数可以直接拷贝使用哟。

RGB的缩放可以参考下面:

int ScaleYUVImgToRGB(int nSrcW,int nSrcH ,uint8_t* src_data,int *linesize,int nDstW ,int nDstH )  
{  
    int i ; int ret ;  FILE *nRGB_file ;

    AVFrame *nDst_picture ;
    struct SwsContext* m_pSwsContext;  

    nDst_picture = avcodec_alloc_frame();
    if (!nDst_picture){
        printf("nDst_picture avcodec_alloc_frame failed\n");
        exit(1);
    }
    if(avpicture_alloc((AVPicture *)nDst_picture,PIX_FMT_RGB24,nDstW, nDstH)<0){
        printf("dst_picture avpicture_alloc failed\n");
        exit(1);
    }
    m_pSwsContext = sws_getContext(nSrcW, nSrcH, PIX_FMT_YUV420P,  
        nDstW, nDstH, PIX_FMT_RGB24,  
        SWS_BICUBIC,  
        NULL, NULL, NULL);  

    if (NULL == m_pSwsContext)  
    {  
        printf("ffmpeg get context error!\n");  
        exit (-1);  
    }   

    ret = sws_scale(m_pSwsContext, src_data,linesize, 0,nSrcH,nDst_picture->data,nDst_picture->linesize);  

    nRGB_file = fopen("..\\YUV_STREAM\\RGBFile.rgb","ab+");
    fwrite(nDst_picture->data[0],nDstW*nDstH*3,1,nRGB_file);
    fclose(nRGB_file);

    sws_freeContext(m_pSwsContext);  
    avpicture_free((AVPicture *)nDst_picture);

    return 0;  
}

参数data 和 linesize 参考yuv平面指针即可。

同时如果不想使用AVPicture结构的话,可以参考下面的:(注意不同图像类型,linesize一定要写对)

char* H264Decoder_c::ScaleYUVImgToRGB(int nSrcW,int nSrcH ,uint8_t** src_data,int *linesize,int nDstW ,int nDstH )
{
    int i ; int ret ;  FILE *nRGB_file ;

    struct SwsContext* m_pSwsContext;
    char*  out_Img[3];
    int out_linesize[3];
    out_linesize[0] = 2*nDstW ; //out_linesize[1] = nDstW ;out_linesize[2] = nDstW ;
    out_Img[0] = g_RGBImg ;

    m_pSwsContext = sws_getContext(nSrcW, nSrcH, PIX_FMT_YUV420P,
        nDstW, nDstH, PIX_FMT_RGB565,
        SWS_BICUBIC,
        NULL, NULL, NULL);

    if (NULL == m_pSwsContext)
    {
        printf("ffmpeg get context error!\n");
        exit (-1);
    }

    ret = sws_scale(m_pSwsContext, src_data,linesize, 0,nSrcH,(uint8_t**)out_Img,out_linesize);
#if 0
    nRGB_file = fopen("./RGBFile.rgb","ab+");
    fwrite(out_Img[0],nDstW*nDstH*2,1,nRGB_file);
    fclose(nRGB_file);

#endif

    sws_freeContext(m_pSwsContext);

    return out_Img[0];

转载自

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值