基于最新的ffmpeg5.0库+QT yuv转rgb图片查看器

本文档介绍如何下载最新版FFmpeg库,并在Qt环境中建立工程,配置编译器,链接库,处理头文件。接着详细阐述了关键的YUV到RGB转换函数`yuvToRgb`的实现,以及重绘事件`paintEvent`的处理。通过递归读取YUV文件并双击显示图像,展示了实际运行效果。作者因工作需要,为方便查看YUV格式图片而编写此程序,解决了现有应用的不便。

一、官网下载ffmpeg库

1.点击Windows图标下面的第一个库连接
官网地址:https://ffmpeg.org/download.html
库地址:https://www.gyan.dev/ffmpeg/builds/
请添加图片描述
2.选择发行版本库,这里我选择的是共享库5.0
请添加图片描述
3.解压后如下图所示,bin文件夹带有官方发行版本运行库xx.dll,lib文件夹带有我们所使用的开发库

请添加图片描述
请添加图片描述
请添加图片描述

二、建立QT工程

1.你可以和我一样,亦可以自行选择工程
请添加图片描述
2.pro工程套件配置,编译器选择64位的编译器,当然你也可以选择32位的编译器MinGw
请添加图片描述
3.pro文件链接ffmpeg库,注意,库有64位的,也有32位的,对应自己QT的MinGw的位数
在这里插入图片描述
4.包含头文件,由于ffmpeg库是由c语言编写,所以头文件声明为 extern "c”
在这里插入图片描述

三、编程

1.头文件

class MyTest : public QMainWindow
{
    Q_OBJECT

public:
    MyTest(QWidget *parent = nullptr);
    ~MyTest();

    void readDir(QString _dirname);
    void readFile(QString file_path);
    void readUiArg();
    void setUiArg();
    void yuvToRgb(void* str,AVPixelFormat yuv_fmt,uint32_t str_w, uint32_t str_h);
    void showImag(QString file_path);
protected:
    void paintEvent(QPaintEvent *event);

private slots:
    void slotGetOneFrame(QImage img);
    void slotBtnClicked();

    void on_listWidget_file_itemDoubleClicked(QListWidgetItem *item);


    void on_comboBox_wh_currentIndexChanged(const QString &arg1);

signals:
     void sig_GetOneFrame(QImage img);

private:
    Ui::MyTest *ui;
    QVector <QString>filename;
    QString dirname;//绝对路径
    QImage rgbImage,displayImage;

    QByteArray str_date;

    uint32_t file_size;
    uint32_t yuv_w,yuv_h,yuv_size;
    uint32_t rgb_w,rgb_h,rgb_size;
    AVPixelFormat cur_yuv_fmt;

    uint8_t *yuvBuffer;
    AVFrame *pFrame ;
    AVFrame *pFrameRGB;

    uint8_t * rgbBuffer;
    SwsContext *img_convert_ctx;

    QString cur_img_path;
    int n_count;
    int index;
};

2.重要方法函数 yuv转rgb

void MyTest::yuvToRgb(void *str,AVPixelFormat yuv_fmt, uint32_t str_w, uint32_t str_h)
{
    rgb_w = str_w;
    rgb_h = str_h;

    yuv_size = str_w * str_h * 3 /2;
    yuvBuffer = (uint8_t *)malloc(yuv_size);

    pFrame = av_frame_alloc();
    pFrameRGB = av_frame_alloc();
    rgb_size =av_image_get_buffer_size(AV_PIX_FMT_RGB32, rgb_w, rgb_h, 1);
    rgbBuffer = (uint8_t *) av_malloc(rgb_size * sizeof(uint8_t));

    av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, rgbBuffer, AV_PIX_FMT_RGB32, rgb_w, rgb_h,1);

    img_convert_ctx = sws_getContext(str_w, str_h, yuv_fmt, rgb_w, rgb_h, AV_PIX_FMT_RGB32, SWS_BICUBIC, NULL, NULL, NULL);

    av_image_fill_arrays(pFrame->data,pFrame->linesize,(uint8_t *)str, yuv_fmt, str_w,str_h,1);
    sws_scale(img_convert_ctx,(uint8_t const * const *) pFrame->data,\
            pFrame->linesize, 0, str_h, pFrameRGB->data, pFrameRGB->linesize);
    for(int i=0;i<10000;i++)
        for(int i=0;i<1000;i++);
    QImage tmpImg((uchar *)rgbBuffer,rgb_w,rgb_h,QImage::Format_RGB32);
    rgbImage = tmpImg.copy();
}

3.事件重绘方法函数

void MyTest::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    if (rgbImage.size().width() <= 0) return;
    //将图像按比例缩放成和窗口一样大小
    QImage img = rgbImage.scaled(ui->widget_video->size(),Qt::KeepAspectRatio);

    int x = ui->widget_video->width() - img.width();
    int y = ui->widget_video->height() - img.height();

    x /= 2;
    y /= 2;


    painter.drawImage(QPoint(x,y),img); //画出图像
}

4.递归加载文件

void MyTest::readDir(QString _dirname)
{
    QDir mydir(_dirname);
    QStringList filelist=mydir.entryList();
    for(int i=0;i<filelist.size();i++)
    {
           QString path=QString("%1/%2").arg(_dirname).arg(filelist.at(i));
           if(filelist.at(i)=="."||filelist.at(i)=="..")
                continue;
           QFileInfo myinfo(path);
           if(myinfo.isDir())
           {
               readDir(path);//递归
           }
           if(myinfo.isFile())
           {
               if(filelist.at(i).contains(".yuv"))
               {
                    ui->listWidget_file->addItem(filelist.at(i));
                    filename.push_back(path);
               }
           }
    }
}

四、UI界面设计

1.ui界面
在这里插入图片描述

五、运行效果

1.选择图片格式及分辨率,我这里是YUV420 2592x1944,这些yuv图片是我用V4L2编程代码从硬件里面保存下来的。
2.双击yuv19.yuv在这里插入图片描述

3.双击yuv20.yuv
在这里插入图片描述

六、结束语

1.由于自己从事硬件相关工作,需要查看yuv420格式的图片,从百度拿的app看yuv比较麻烦,所以自己就写了一个,百度的ffmpeg方法都是比较老的且有许多版本造成的问题,我这里是用最新的库编写的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值