若该文为原创文章,未经允许不得转载
原博主博客地址: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、单片机、软硬结合等等)持续更新中…(点击传送门)
服务器拼接,测试图像16个,需要不断切换(图像已在内存中),仅测试超大拼接区域的刷新帧率。
下载地址:https://download.csdn.net/download/qq21497936/10286699
可以看到,当图片覆盖屏幕(1080p)时,帧率最小,笔者最大帧率为60+fps
但是我们也同时看到,解码jpg文件的时间较长,一张图片200ms左右(1080p)
加载5组,每组16个6*1080p横向凭借的jpg文件(一行80个1080p),不断循环从1组切至5组,测试刷新帧率。
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#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> _listListPPixmap;
QList _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
#include
#include
#include
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 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 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()<
#include
#include
#include
#include
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 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 _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
#include
#include
#include
#include
#include
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 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