若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/79557290
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门)
Qt开发专栏:实用技巧(点击传送门)
需求
服务器拼接,测试图像16个,需要不断切换(图像已在内存中),仅测试超大拼接区域的刷新帧率。
Demo
下载地址:https://download.csdn.net/download/qq21497936/10286699
ReadMe
效果
可以看到,当图片覆盖屏幕(1080p)时,帧率最小,笔者最大帧率为60+fps
但是我们也同时看到,解码jpg文件的时间较长,一张图片200ms左右(1080p)
原理
加载5组,每组16个6*1080p横向凭借的jpg文件(一行80个1080p),不断循环从1组切至5组,测试刷新帧率。
代码
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QPaintEvent> #include "hmfpaintwidget.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); protected slots: void timeout(); void clean(); protected: void paintEvent(QPaintEvent *event); private slots: void on_action_triggered(); void on_action2_triggered(); void on_action3_triggered(); void on_action4_triggered(); void on_action5_triggered(); void on_actionStop_triggered(); void on_action1_triggered(); void on_action2_2_triggered(); private: Ui::MainWindow *ui; HMFPaintWidget * _pHMFPaintWigdet; QList<QList<QPixmap *>> _listListPPixmap; QList<QImage *> _listImage; int _currentIndex; QTimer *_pTimer; int _dirs; bool _start; int _interval; int _factor; int _count; }; #endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QUrl> #include <QTimer> #include <QPainter> #include <QPixmap> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), _dirs(5), _interval(40), _start(false), _factor(1), _count(16) { ui->setupUi(this); _pHMFPaintWigdet = new HMFPaintWidget; setCentralWidget(_pHMFPaintWigdet); _currentIndex = 0; _pTimer = new QTimer(this); connect(_pTimer, SIGNAL(timeout()), this, SLOT(timeout())); } MainWindow::~MainWindow() { delete ui; } void MainWindow::timeout() { static int number = 0; number++; if(_listListPPixmap.size() != 0) { _pHMFPaintWigdet->setListPixmap(_listListPPixmap.at(number%_listListPPixmap.size())); } if(_listImage.size() != 0) { _pHMFPaintWigdet->setImage(_listImage.at(number%_listImage.size())); } } void MainWindow::clean() { _pTimer->stop(); _dirs = 1; _start = false; _pHMFPaintWigdet->clear(); qDebug() << __FILE__ << __LINE__; for(int index = 0; index < _listListPPixmap.size(); index++) { QList<QPixmap *> listPPixmap = _listListPPixmap.at(index); qDebug() << __FILE__ << __LINE__ << index << listPPixmap; for(int index2 = 0; index2 < listPPixmap.size(); index2++) { delete listPPixmap.at(index2); qDebug() << __FILE__ << __LINE__ << index2 << listPPixmap.at(index2); } } qDebug() << __FILE__ << __LINE__; _listListPPixmap.clear(); qDebug() << __FILE__ << __LINE__; } #if 1 #if 1 void MainWindow::paintEvent(QPaintEvent *event) { if(_start) { qint64 total = 0; QPainter painter(this); for(int index = 0; index < _dirs; index++) { QList<QPixmap *> listPPixmap; for(int index2 = 0; index2 < _count; index2++) { QElapsedTimer t; t.start(); QString file = QString("./images/images%1/%2.jpg").arg(index+1).arg(index2+1); QImage image(file); painter.drawText(0,50, QString("正在读取文件:%1").arg(file)); QPixmap * pPixmap = new QPixmap(image.width(), image.height()); *pPixmap = QPixmap::fromImage(image); listPPixmap.push_back(pPixmap); QString str = QString("file: %1 time:%2").arg(file).arg(t.elapsed()); total += t.elapsed(); DEBUG(str); } _listListPPixmap.push_back(listPPixmap); } _pTimer->start(_interval); _start = false; } QMainWindow::paintEvent(event); } #else void MainWindow::paintEvent(QPaintEvent *event) { if(_start) { for(int index = 0; index < _dirs; index++) { QPixmap *pPixmap = new QPixmap(9600/_factor*_count, 1080/_factor); // 若_factor=1,则静态对多2幅图 动态最多1幅图 可存入内存 pPixmap->fill(Qt::white); QPainter painter(pPixmap); for(int index2 = 0; index2 < _count; index2++) { QPixmap pixmap2(QString("./images/images%1/%2.jpg").arg(index+1).arg(index2+1)); painter.drawPixmap(index2*(9600/_factor), 0, 9600/_factor, 1080/_factor, pixmap2); } _listPixmap.push_back(pPixmap); } _pTimer->start(_interval); _start = false; } QMainWindow::paintEvent(event); } #endif #else void MainWindow::paintEvent(QPaintEvent *event) { if(_start) { for(int index = 0; index < _dirs; index++) { QImage *pImage = new QImage(9600/_factor*_count, 1080/_factor, QImage::Format_RGB32); // 若_factor=1,则静态对多2幅图 动态最多1幅图 可存入内存 pImage->fill(Qt::white); QPainter painter(pImage); for(int index2 = 0; index2 < _count; index2++) { QImage image2(QString("./images/images%1/%2.jpg").arg(index+1).arg(index2+1)); painter.drawImage(QRect(index2*(9600/_factor), 0, 9600/_factor, 1080/_factor), image2); } _listImage.push_back(pImage); } _pTimer->start(_interval); _start = false; } QMainWindow::paintEvent(event); } #endif void MainWindow::on_action_triggered() { clean(); _dirs = 1; _start = true; update(); } void MainWindow::on_action2_triggered() { clean(); _dirs = 2; _start = true; update(); } void MainWindow::on_action3_triggered() { clean(); _dirs = 3; _start = true; update(); } void MainWindow::on_action4_triggered() { clean(); _dirs = 4; _start = true; update(); } void MainWindow::on_action5_triggered() { clean(); _dirs = 5; _start = true; update(); } void MainWindow::on_actionStop_triggered() { clean(); } void MainWindow::on_action1_triggered() { _factor = 1; } void MainWindow::on_action2_2_triggered() { _factor = 2; }
hmfpaintwidget.h
#ifndef HMFPAINTWIDGET_H #define HMFPAINTWIDGET_H #define DEBUG(msg) \ (qDebug()<<QString("[%1][%2:%3:%4]%5").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")) \ .arg(__FILE__) \ .arg(__FUNCTION__) \ .arg(__LINE__).arg(msg)); #include <QDateTime> #include <QDebug> #include <QWidget> #include <QElapsedTimer> #include <QList> class QRect; class QPaintEvent; class QResizeEvent; class QPixmap; class HMFPaintWidget : public QWidget { Q_OBJECT public: explicit HMFPaintWidget(QWidget *parent = nullptr); signals: public slots: void setListPixmap(QList<QPixmap *> listPPixmap, bool reload = false); void setPixmap(QPixmap *pixmap, bool reload = false); void setImage(QImage *image, bool reload = false); void setPicture(QPicture *picture, bool reload = false); void flushBackground(); void clear(); void scaleToRect(QRect desRect); void render(); protected: void drawBackground(QPainter &painter); void drawPixmap(QPainter &painter); void drawListPixmap(QPainter &painter); void drawImage(QPainter &painter); void drawPicture(QPainter &painter); void drawFps(QPainter &painter); protected: void paintEvent(QPaintEvent *event) override; void resizeEvent(QResizeEvent *event) override; void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void wheelEvent(QWheelEvent *event) override; void timerEvent(QTimerEvent *event) override; private: QColor _colorBackgound; bool _clearBackgroud; QRectF _rectOrigin; QRectF _rectUse; QRectF _rectVisible; QList<QPixmap *> _listPPixmap; QPixmap _pixmapFull; QPixmap _pixmap; QImage *_imageFull; QImage _image; float _scaleStep; bool _leftButtonPressed; QPoint _pointLast; QElapsedTimer _time; bool _updateFps; float _fps; float _fpsAverage; }; #endif // HMFPAINTWIDGET_H
hmfpaintwidget.cpp
#include "hmfpaintwidget.h" #include <QPainter> #include <QDebug> #include <QPixmap> #include <QWheelEvent> #include <QTimer> #include <QElapsedTimer> HMFPaintWidget::HMFPaintWidget(QWidget *parent) : QWidget(parent), _colorBackgound(QColor(Qt::white)), _clearBackgroud(true), _scaleStep(0.01f), _leftButtonPressed(false), _updateFps(false) { setCursor(Qt::OpenHandCursor); startTimer(1000); _imageFull = 0; render(); } void HMFPaintWidget::setListPixmap(QList<QPixmap *> listPPixmap, bool reload) { if(_listPPixmap.size() == 0 || reload) { _listPPixmap = listPPixmap; _rectOrigin = QRect(0, 0, _listPPixmap.at(0)->rect().width()*_listPPixmap.size(), _listPPixmap.at(0)->rect().height()); scaleToRect(rect()); _fps = 0; _fpsAverage = 0; _time.start(); }else { _listPPixmap = listPPixmap; } } void HMFPaintWidget::setPixmap(QPixmap *pixmap, bool reload) { if(_pixmapFull.isNull() || reload) { _pixmapFull = *pixmap; _rectOrigin = QRect(_pixmapFull.rect()); scaleToRect(rect()); _fps = 0; _fpsAverage = 0; _time.start(); // _pixmapFull.save("./ouput.png"); }else { _pixmapFull = *pixmap; } update(); } void HMFPaintWidget::setImage(QImage *image, bool reload) { if(_pixmapFull.isNull() || reload) { _imageFull = image; _rectOrigin = QRect(_imageFull->rect()); scaleToRect(rect()); _fps = 0; _fpsAverage = 0; _time.start(); // _imageFull.save("./ouput.png"); }else { _imageFull = image; } update(); } void HMFPaintWidget::setPicture(QPicture *picture, bool reload) { } void HMFPaintWidget::flushBackground() { _clearBackgroud = true; } void HMFPaintWidget::clear() { _clearBackgroud = true; _pixmapFull = QPixmap(); _pixmap = QPixmap(); _listPPixmap.clear(); } void HMFPaintWidget::scaleToRect(QRect desRect) { float scaleOrigin = _rectOrigin.width() / (float)_rectOrigin.height(); float scaleWidget = desRect.width() / (float)desRect.height(); if(scaleOrigin > scaleWidget) { float scale; scale = this->rect().width() / (float)_rectOrigin.width(); _rectUse.setWidth(_rectOrigin.width()*scale); _rectUse.setHeight(_rectOrigin.height()*scale); // rect直接使用setx sety 会导致 height width 发生改变,必须使用moveTo _rectUse.moveTo(0, (desRect.height()-_rectUse.height())/2 ); }else{ float scale; scale = this->rect().height() / _rectOrigin.height(); _rectUse.setWidth(_rectOrigin.width()*scale); _rectUse.setHeight(_rectOrigin.height()*scale); _rectUse.moveTo((desRect.width()-_rectUse.width())/2, 0); } } void HMFPaintWidget::drawBackground(QPainter &painter) { painter.save(); painter.setBrush(_colorBackgound); painter.drawRect(0, 0, rect().width(), rect().height()); painter.restore(); } void HMFPaintWidget::drawPixmap(QPainter &painter) { painter.save(); painter.drawPixmap(_rectUse.toRect(), _pixmapFull); painter.restore(); } void HMFPaintWidget::drawListPixmap(QPainter &painter) { if(_listPPixmap.size() == 0) return; painter.save(); float width = _rectUse.width()/(float)_listPPixmap.size(); float lastX = _rectUse.x(); for(int index = 0; index < _listPPixmap.size(); index++) { painter.drawPixmap(lastX, _rectUse.y(), width, _rectUse.height(), *_listPPixmap.at(index)); lastX += width-1; } painter.restore(); } void HMFPaintWidget::drawImage(QPainter &painter) { DEBUG(""); painter.save(); if(_imageFull != NULL) painter.drawImage(_rectUse.toRect(), *_imageFull); painter.restore(); } void HMFPaintWidget::drawPicture(QPainter &painter) { } void HMFPaintWidget::drawFps(QPainter &painter) { painter.save(); painter.drawText(1, rect().height()-1, QString("fps:%1 average fps:%2").arg(_fps).arg(_fpsAverage/(_time.elapsed()/1000))); painter.restore(); } void HMFPaintWidget::paintEvent(QPaintEvent *event) { QPainter painter(this); if(_clearBackgroud) { drawBackground(painter); _clearBackgroud = false; } drawListPixmap(painter); drawFps(painter); static int fps = 0; if(_updateFps) { _fps = fps; fps = 0; _updateFps = false; } fps++; _fpsAverage++; } void HMFPaintWidget::resizeEvent(QResizeEvent *event) { } void HMFPaintWidget::mousePressEvent(QMouseEvent *event) { if(event->button() == Qt::LeftButton) { _leftButtonPressed = true; _pointLast = event->pos(); setCursor(Qt::ClosedHandCursor); } } void HMFPaintWidget::mouseMoveEvent(QMouseEvent *event) { if(_leftButtonPressed) { static QPoint dPoint; dPoint = event->pos() - _pointLast; _pointLast = event->pos(); _rectUse.moveTopLeft(_rectUse.topLeft() + dPoint); } } void HMFPaintWidget::mouseReleaseEvent(QMouseEvent *event) { if(event->button() == Qt::LeftButton) { _leftButtonPressed = false; setCursor(Qt::OpenHandCursor); } } void HMFPaintWidget::wheelEvent(QWheelEvent *event) { if(event->angleDelta().ry() > 0) { float scale = 1.0f + _scaleStep; float dx = (event->pos().x() - _rectUse.x()) * scale - (event->pos().x() - _rectUse.x()); float dy = (event->pos().y() - _rectUse.y()) * scale - (event->pos().y() - _rectUse.y()); _rectUse = QRectF(_rectUse.x()-dx, _rectUse.y()-dy, _rectUse.width()*scale, _rectUse.height()*scale); }else { float scale = 1.0f - _scaleStep; float dx = (event->pos().x() - _rectUse.x()) * scale - (event->pos().x() - _rectUse.x()); float dy = (event->pos().y() - _rectUse.y()) * scale - (event->pos().y() - _rectUse.y()); _rectUse = QRectF(_rectUse.x()-dx, _rectUse.y()-dy, _rectUse.width()*scale, _rectUse.height()*scale); } } void HMFPaintWidget::timerEvent(QTimerEvent *event) { _updateFps = true; } void HMFPaintWidget::render() { static int count = 0; if(count == 0) _time.start(); update(); count++; QTimer::singleShot(0, this, SLOT(render())); }
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/79557290