add support to export slide show animation to movie file via ffmpeg
This commit is contained in:
@ -225,11 +225,13 @@ displays the images created by LAMMPS as they are written.
|
|||||||
:align: center
|
:align: center
|
||||||
:scale: 50%
|
:scale: 50%
|
||||||
|
|
||||||
The various buttons at the bottom right of the window allow either
|
The various buttons at the bottom right of the window allow single
|
||||||
single stepping through the sequence of images or playing an animation
|
stepping through the sequence of images or playing an animation (as a
|
||||||
(as a continuous loop or once from first to last). It is also possible
|
continuous loop or once from first to last). It is also possible to
|
||||||
to zoom in or zoom out of the displayed images. The slide show window
|
zoom in or zoom out of the displayed images, and to export the slide
|
||||||
will be closed when a new file is loaded.
|
show animation to a movie file, if `ffmpeg <https://ffmpeg.org/>`_ is
|
||||||
|
installed. The slide show window will be closed when a new file is
|
||||||
|
loaded.
|
||||||
|
|
||||||
Variable Info
|
Variable Info
|
||||||
-------------
|
-------------
|
||||||
|
|||||||
BIN
tools/lammps-gui/export-movie.png
Normal file
BIN
tools/lammps-gui/export-movie.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.0 KiB |
@ -858,6 +858,7 @@ void LammpsGui::logupdate()
|
|||||||
slideshow->hide();
|
slideshow->hide();
|
||||||
} else {
|
} else {
|
||||||
slideshow->setWindowTitle(QString("LAMMPS-GUI - Slide Show: ") + current_file);
|
slideshow->setWindowTitle(QString("LAMMPS-GUI - Slide Show: ") + current_file);
|
||||||
|
if (QSettings().value("viewslide", true).toBool()) slideshow->show();
|
||||||
}
|
}
|
||||||
slideshow->add_image(imagefile);
|
slideshow->add_image(imagefile);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
<file>edit-undo.png</file>
|
<file>edit-undo.png</file>
|
||||||
<file>emblem-photos.png</file>
|
<file>emblem-photos.png</file>
|
||||||
<file>expand-text.png</file>
|
<file>expand-text.png</file>
|
||||||
|
<file>export-movie.png</file>
|
||||||
<file>format-indent-less-3.png</file>
|
<file>format-indent-less-3.png</file>
|
||||||
<file>go-first.png</file>
|
<file>go-first.png</file>
|
||||||
<file>go-last.png</file>
|
<file>go-last.png</file>
|
||||||
|
|||||||
@ -13,7 +13,11 @@
|
|||||||
|
|
||||||
#include "slideshow.h"
|
#include "slideshow.h"
|
||||||
|
|
||||||
|
#include "helpers.h"
|
||||||
|
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFileDialog>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
@ -21,11 +25,13 @@
|
|||||||
#include <QImageReader>
|
#include <QImageReader>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QPalette>
|
#include <QPalette>
|
||||||
|
#include <QProcess>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QShortcut>
|
#include <QShortcut>
|
||||||
#include <QSpacerItem>
|
#include <QSpacerItem>
|
||||||
|
#include <QTemporaryFile>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
@ -58,6 +64,10 @@ SlideShow::SlideShow(const QString &fileName, QWidget *parent) :
|
|||||||
auto *dummy = new QPushButton(QIcon(), "");
|
auto *dummy = new QPushButton(QIcon(), "");
|
||||||
dummy->hide();
|
dummy->hide();
|
||||||
|
|
||||||
|
auto *tomovie = new QPushButton(QIcon(":/export-movie.png"), "");
|
||||||
|
tomovie->setToolTip("Export to movie file");
|
||||||
|
tomovie->setEnabled(has_exe("ffmpeg"));
|
||||||
|
|
||||||
auto *gofirst = new QPushButton(QIcon(":/go-first.png"), "");
|
auto *gofirst = new QPushButton(QIcon(":/go-first.png"), "");
|
||||||
gofirst->setToolTip("Go to first Image");
|
gofirst->setToolTip("Go to first Image");
|
||||||
auto *goprev = new QPushButton(QIcon(":/go-previous-2.png"), "");
|
auto *goprev = new QPushButton(QIcon(":/go-previous-2.png"), "");
|
||||||
@ -83,6 +93,7 @@ SlideShow::SlideShow(const QString &fileName, QWidget *parent) :
|
|||||||
auto *normal = new QPushButton(QIcon(":/gtk-zoom-fit.png"), "");
|
auto *normal = new QPushButton(QIcon(":/gtk-zoom-fit.png"), "");
|
||||||
normal->setToolTip("Reset zoom to normal");
|
normal->setToolTip("Reset zoom to normal");
|
||||||
|
|
||||||
|
connect(tomovie, &QPushButton::released, this, &SlideShow::movie);
|
||||||
connect(gofirst, &QPushButton::released, this, &SlideShow::first);
|
connect(gofirst, &QPushButton::released, this, &SlideShow::first);
|
||||||
connect(goprev, &QPushButton::released, this, &SlideShow::prev);
|
connect(goprev, &QPushButton::released, this, &SlideShow::prev);
|
||||||
connect(goplay, &QPushButton::released, this, &SlideShow::play);
|
connect(goplay, &QPushButton::released, this, &SlideShow::play);
|
||||||
@ -96,6 +107,7 @@ SlideShow::SlideShow(const QString &fileName, QWidget *parent) :
|
|||||||
|
|
||||||
navLayout->addSpacerItem(new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum));
|
navLayout->addSpacerItem(new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum));
|
||||||
navLayout->addWidget(dummy);
|
navLayout->addWidget(dummy);
|
||||||
|
navLayout->addWidget(tomovie);
|
||||||
navLayout->addWidget(gofirst);
|
navLayout->addWidget(gofirst);
|
||||||
navLayout->addWidget(goprev);
|
navLayout->addWidget(goprev);
|
||||||
navLayout->addWidget(goplay);
|
navLayout->addWidget(goplay);
|
||||||
@ -178,6 +190,46 @@ void SlideShow::loadImage(int idx)
|
|||||||
} while (idx >= 0);
|
} while (idx >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SlideShow::movie()
|
||||||
|
{
|
||||||
|
QString fileName = QFileDialog::getSaveFileName(this, "Export to Movie File", ".",
|
||||||
|
"Movie Files (*.mpg *.mp4 *.mkv *.avi *.mpeg)");
|
||||||
|
if (fileName.isEmpty()) return;
|
||||||
|
|
||||||
|
QDir curdir(".");
|
||||||
|
QTemporaryFile concatfile;
|
||||||
|
concatfile.open();
|
||||||
|
for (auto image : imagefiles) {
|
||||||
|
concatfile.write("file '");
|
||||||
|
concatfile.write(curdir.absoluteFilePath(image).toLocal8Bit());
|
||||||
|
concatfile.write("'\n");
|
||||||
|
}
|
||||||
|
concatfile.close();
|
||||||
|
|
||||||
|
QStringList args;
|
||||||
|
args << "-y";
|
||||||
|
args << "-safe"
|
||||||
|
<< "0";
|
||||||
|
args << "-r"
|
||||||
|
<< "10";
|
||||||
|
args << "-f"
|
||||||
|
<< "concat";
|
||||||
|
args << "-i" << concatfile.fileName();
|
||||||
|
if (scaleFactor != 1.0) {
|
||||||
|
args << "-vf" << QString("scale=iw*%1:-1").arg(scaleFactor);
|
||||||
|
}
|
||||||
|
args << "-b:v"
|
||||||
|
<< "2000k";
|
||||||
|
args << "-r"
|
||||||
|
<< "24";
|
||||||
|
args << fileName;
|
||||||
|
|
||||||
|
auto *ffmpeg = new QProcess(this);
|
||||||
|
ffmpeg->start("ffmpeg", args);
|
||||||
|
ffmpeg->waitForFinished(-1);
|
||||||
|
delete ffmpeg;
|
||||||
|
}
|
||||||
|
|
||||||
void SlideShow::first()
|
void SlideShow::first()
|
||||||
{
|
{
|
||||||
current = 0;
|
current = 0;
|
||||||
|
|||||||
@ -32,6 +32,7 @@ public:
|
|||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void movie();
|
||||||
void first();
|
void first();
|
||||||
void last();
|
void last();
|
||||||
void next();
|
void next();
|
||||||
|
|||||||
Reference in New Issue
Block a user