Krita Source Code Documentation
Loading...
Searching...
No Matches
KisDlgAnimationRenderer Class Reference

#include <KisDlgAnimationRenderer.h>

+ Inheritance diagram for KisDlgAnimationRenderer:

Public Member Functions

KisAnimationRenderingOptions getEncoderOptions () const
 
 KisDlgAnimationRenderer (KisDocument *doc, QWidget *parent=0)
 
 ~KisDlgAnimationRenderer () override
 
- Public Member Functions inherited from KoDialog
QPushButton * button (ButtonCode id) const
 
QIcon buttonIcon (ButtonCode id) const
 
QString buttonText (ButtonCode id) const
 
QString buttonToolTip (ButtonCode id) const
 
QString buttonWhatsThis (ButtonCode id) const
 
ButtonCode defaultButton () const
 
QString helpLinkText () const
 
void incrementInitialSize (const QSize &size)
 
bool isButtonEnabled (ButtonCode id) const
 
 KoDialog (QWidget *parent=0, Qt::WindowFlags f=Qt::WindowFlags())
 
QWidget * mainWidget ()
 
QSize minimumSizeHint () const override
 
void setButtonFocus (ButtonCode id)
 
void setButtonGuiItem (ButtonCode id, const KGuiItem &item)
 
void setButtonIcon (ButtonCode id, const QIcon &icon)
 
void setButtons (ButtonCodes buttonMask)
 
void setButtonsOrientation (Qt::Orientation orientation)
 
void setButtonText (ButtonCode id, const QString &text)
 
void setButtonToolTip (ButtonCode id, const QString &text)
 
void setButtonWhatsThis (ButtonCode id, const QString &text)
 
void setDefaultButton (ButtonCode id)
 
void setEscapeButton (ButtonCode id)
 
void setInitialSize (const QSize &size)
 
void setMainWidget (QWidget *widget)
 
void showButton (ButtonCode id, bool state)
 
void showButtonSeparator (bool state)
 
QSize sizeHint () const override
 
 ~KoDialog () override
 

Protected Slots

void slotButtonClicked (int button) override
 
void slotDialogAccepted ()
 
- Protected Slots inherited from KoDialog
virtual void slotButtonClicked (int button)
 

Private Types

enum  FFmpegValidationResult { VALID = 1 , INVALID = 0 , NOT_A_BINARY = -1 , COMPRESSED_FORMAT = -2 }
 

Private Slots

void frameRateChanged (int framerate)
 
void selectRenderOptions ()
 
void selectRenderType (int i)
 
void sequenceMimeTypeOptionsClicked ()
 sequenceMimeTypeSelected calls the dialog for the export widget.
 
void setFFmpegPath (const QString &path)
 
void slotExportTypeChanged ()
 
void slotLockAspectRatioDimensionsHeight (int height)
 
void slotLockAspectRatioDimensionsWidth (int width)
 

Private Member Functions

void ffmpegWarningCheck ()
 
QStringList filterMimeTypeListByAvailableEncoders (const QStringList &mimeTypes)
 
void initializeRenderSettings (const KisDocument &doc, const KisAnimationRenderingOptions &lastUsedOptions)
 
FFmpegValidationResult validateFFmpeg (const QString &ffmpegPath)
 

Static Private Member Functions

static QString defaultVideoFileName (KisDocument *doc, const QString &mimeType)
 
static void filterSequenceMimeTypes (QStringList &mimeTypes)
 
static void getDefaultVideoEncoderOptions (const QString &mimeType, KisPropertiesConfigurationSP cfg, const QStringList &availableEncoders, QString *customFFMpegOptionsString, bool *forceHDRVideo)
 
static bool imageMimeSupportsHDR (QString &hdr)
 
static KisPropertiesConfigurationSP loadLastConfiguration (QString configurationID)
 
static QStringList makeVideoMimeTypesList ()
 
static void saveLastUsedConfiguration (QString configurationID, KisPropertiesConfigurationSP config)
 

Private Attributes

QStringList ffmpegCodecs = QStringList()
 
QMap< QString, QStringListffmpegEncoderTypes
 
QString ffmpegVersion = "None"
 
QString m_customFFMpegOptionsString
 
KisDocumentm_doc
 
KisImageSP m_image
 
WdgAnimationRendererm_page {0}
 
bool m_wantsRenderWithHDR = false
 

Additional Inherited Members

- Public Types inherited from KoDialog
enum  ButtonCode {
  None = 0x00000000 , Help = 0x00000001 , Default = 0x00000002 , Ok = 0x00000004 ,
  Apply = 0x00000008 , Try = 0x00000010 , Cancel = 0x00000020 , Close = 0x00000040 ,
  No = 0x00000080 , Yes = 0x00000100 , Reset = 0x00000200 , Details = 0x00000400 ,
  User1 = 0x00001000 , User2 = 0x00002000 , User3 = 0x00004000 , NoDefault = 0x00008000
}
 
enum  ButtonPopupMode { InstantPopup = 0 , DelayedPopup = 1 }
 
enum  CaptionFlag { NoCaptionFlags = 0 , AppNameCaption = 1 , ModifiedCaption = 2 , HIGCompliantCaption = AppNameCaption }
 
- Public Slots inherited from KoDialog
void delayedDestruct ()
 
void enableButton (ButtonCode id, bool state)
 
void enableButtonApply (bool state)
 
void enableButtonCancel (bool state)
 
void enableButtonOk (bool state)
 
void enableLinkedHelp (bool state)
 
bool isDetailsWidgetVisible () const
 
virtual void setCaption (const QString &caption)
 
virtual void setCaption (const QString &caption, bool modified)
 
void setDetailsWidget (QWidget *detailsWidget)
 
void setDetailsWidgetVisible (bool visible)
 
void setHelp (const QString &anchor, const QString &appname=QString())
 
void setHelpLinkText (const QString &text)
 
virtual void setPlainCaption (const QString &caption)
 
- Signals inherited from KoDialog
void aboutToShowDetails ()
 
void applyClicked ()
 
void buttonClicked (KoDialog::ButtonCode button)
 
void cancelClicked ()
 
void closeClicked ()
 
void defaultClicked ()
 
void finished ()
 
void helpClicked ()
 
void hidden ()
 
void layoutHintChanged ()
 
void noClicked ()
 
void okClicked ()
 
void resetClicked ()
 
void tryClicked ()
 
void user1Clicked ()
 
void user2Clicked ()
 
void user3Clicked ()
 
void yesClicked ()
 
- Static Public Member Functions inherited from KoDialog
static int groupSpacingHint ()
 
static QString makeStandardCaption (const QString &userCaption, QWidget *window=0, CaptionFlags flags=HIGCompliantCaption)
 
static int marginHint ()
 
static void resizeLayout (QLayout *lay, int margin, int spacing)
 
static void resizeLayout (QWidget *widget, int margin, int spacing)
 
static int spacingHint ()
 
- Protected Member Functions inherited from KoDialog
void closeEvent (QCloseEvent *e) override
 
void hideEvent (QHideEvent *) override
 
void keyPressEvent (QKeyEvent *) override
 
void showEvent (QShowEvent *e) override
 

Detailed Description

Definition at line 38 of file KisDlgAnimationRenderer.h.

Member Enumeration Documentation

◆ FFmpegValidationResult

Enumerator
VALID 
INVALID 
NOT_A_BINARY 
COMPRESSED_FORMAT 

Definition at line 74 of file KisDlgAnimationRenderer.h.

Constructor & Destructor Documentation

◆ KisDlgAnimationRenderer()

KisDlgAnimationRenderer::KisDlgAnimationRenderer ( KisDocument * doc,
QWidget * parent = 0 )

Definition at line 47 of file KisDlgAnimationRenderer.cpp.

48 : KoDialog(parent)
49 , m_image(doc->image())
50 , m_doc(doc)
51{
52 KisConfig cfg(true);
53
54 setCaption(i18n("Render Animation"));
57
58 m_page = new WdgAnimationRenderer(this);
59 m_page->layout()->setContentsMargins(0, 0, 0, 0);
60
61 m_page->dirRequester->setMode(KoFileDialog::OpenDirectory);
62
63 m_page->intStart->setMinimum(0);
64 m_page->intStart->setMaximum(doc->image()->animationInterface()->documentPlaybackRange().end());
65 m_page->intEnd->setMinimum(doc->image()->animationInterface()->documentPlaybackRange().start());
66
67 m_page->intHeight->setMinimum(1);
68 m_page->intHeight->setMaximum(100000);
69
70 m_page->intWidth->setMinimum(1);
71 m_page->intWidth->setMaximum(100000);
72
73 // Setup audio...
74 QVector<QFileInfo> audioFiles = doc->getAudioTracks();
75 const bool hasAudio = audioFiles.count() > 0;
76 m_page->chkIncludeAudio->setEnabled(hasAudio);
77
78 // Setup image mimeTypes...
80 mimes.sort();
82 Q_FOREACH(const QString &mime, mimes) {
83 QString description = KisMimeDatabase::descriptionForMimeType(mime);
84 if (description.isEmpty()) {
85 description = mime;
86 }
87
88 m_page->cmbMimetype->addItem(description, mime);
89
90 if (mime == "image/png") {
91 m_page->cmbMimetype->setCurrentIndex(m_page->cmbMimetype->count() - 1);
92 }
93 }
94
95 m_page->cmbScaleFilter->addItem(i18nc("bicubic filtering", "bicubic"), "bicubic");
96 m_page->cmbScaleFilter->addItem(i18nc("bilinear filtering", "bilinear"), "bilinear");
97 m_page->cmbScaleFilter->addItem(i18nc("lanczos3 filtering", "lanczos3"), "lanczos");
98 m_page->cmbScaleFilter->addItem(i18nc("nearest neighbor filtering", "neighbor"), "neighbor");
99 m_page->cmbScaleFilter->addItem(i18nc("spline filtering", "spline"), "spline");
100
101 m_page->videoFilename->setMode(KoFileDialog::SaveFile);
102
103 m_page->ffmpegLocation->setMode(KoFileDialog::OpenFile);
104
105 m_page->cmbRenderType->setPlaceholderText(i18nc("Not applicable. No render types without valid ffmpeg path.", "N/A"));
106
107 { // Establish connections...
108 connect(m_page->bnExportOptions, SIGNAL(clicked()), this, SLOT(sequenceMimeTypeOptionsClicked()));
109 connect(m_page->bnRenderOptions, SIGNAL(clicked()), this, SLOT(selectRenderOptions()));
110
111 connect(m_page->shouldExportOnlyImageSequence, SIGNAL(toggled(bool)), this, SLOT(slotExportTypeChanged()));
112 connect(m_page->shouldExportOnlyVideo, SIGNAL(toggled(bool)), this, SLOT(slotExportTypeChanged()));
113
114 connect(m_page->intFramesPerSecond, SIGNAL(valueChanged(int)), SLOT(frameRateChanged(int)));
115
116 connect(m_page->ffmpegLocation, SIGNAL(fileSelected(QString)), SLOT(setFFmpegPath(QString)));
117
118 connect(this, SIGNAL(accepted()), SLOT(slotDialogAccepted()));
119 }
120
121
122 // try to lock the width and height being updated
123 KisAcyclicSignalConnector *constrainsConnector = new KisAcyclicSignalConnector(this);
124 constrainsConnector->createCoordinatedConnector()->connectBackwardInt(m_page->intWidth, SIGNAL(valueChanged(int)), this, SLOT(slotLockAspectRatioDimensionsWidth(int)));
125 constrainsConnector->createCoordinatedConnector()->connectForwardInt(m_page->intHeight, SIGNAL(valueChanged(int)), this, SLOT(slotLockAspectRatioDimensionsHeight(int)));
126
127 { // Initialize settings from last configuration...
128 KisPropertiesConfigurationSP animProperties = loadLastConfiguration("ANIMATION_EXPORT");
130 options.fromProperties(animProperties);
131
132 initializeRenderSettings(*doc, options);
133 }
134
136}
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
KisAcyclicSignalConnector * createCoordinatedConnector()
create a coordinated connector that can be used for extending the number of self-locking connection.
void connectBackwardInt(QObject *sender, const char *signal, QObject *receiver, const char *method)
void connectForwardInt(QObject *sender, const char *signal, QObject *receiver, const char *method)
void fromProperties(KisPropertiesConfigurationSP config)
void initializeRenderSettings(const KisDocument &doc, const KisAnimationRenderingOptions &lastUsedOptions)
void sequenceMimeTypeOptionsClicked()
sequenceMimeTypeSelected calls the dialog for the export widget.
void setFFmpegPath(const QString &path)
void slotLockAspectRatioDimensionsHeight(int height)
void slotLockAspectRatioDimensionsWidth(int width)
static KisPropertiesConfigurationSP loadLastConfiguration(QString configurationID)
WdgAnimationRenderer * m_page
static void filterSequenceMimeTypes(QStringList &mimeTypes)
KisImageSP image
QVector< QFileInfo > getAudioTracks() const
const KisTimeSpan & documentPlaybackRange() const
documentPlaybackRange
KisImageAnimationInterface * animationInterface() const
static QStringList supportedMimeTypes(Direction direction)
static QString descriptionForMimeType(const QString &mimeType)
Find the user-readable description for the given mimetype.
int start() const
int end() const
void setMainWidget(QWidget *widget)
Definition KoDialog.cpp:354
virtual void setCaption(const QString &caption)
Definition KoDialog.cpp:498
void setButtons(ButtonCodes buttonMask)
Definition KoDialog.cpp:195
void setDefaultButton(ButtonCode id)
Definition KoDialog.cpp:302
@ Ok
Show Ok button. (this button accept()s the dialog; result set to QDialog::Accepted)
Definition KoDialog.h:127
@ Cancel
Show Cancel-button. (this button reject()s the dialog; result set to QDialog::Rejected)
Definition KoDialog.h:130
KoDialog(QWidget *parent=0, Qt::WindowFlags f=Qt::WindowFlags())
Definition KoDialog.cpp:176

References KisImage::animationInterface(), KoDialog::Cancel, connect(), KisAcyclicSignalConnector::connectBackwardInt(), KisAcyclicSignalConnector::connectForwardInt(), KisAcyclicSignalConnector::createCoordinatedConnector(), KisMimeDatabase::descriptionForMimeType(), KisImageAnimationInterface::documentPlaybackRange(), KisTimeSpan::end(), KisImportExportManager::Export, filterSequenceMimeTypes(), frameRateChanged(), KisAnimationRenderingOptions::fromProperties(), KisDocument::getAudioTracks(), KisDocument::image, initializeRenderSettings(), loadLastConfiguration(), m_page, KoDialog::Ok, KoFileDialog::OpenDirectory, KoFileDialog::OpenFile, KoFileDialog::SaveFile, selectRenderOptions(), sequenceMimeTypeOptionsClicked(), KoDialog::setButtons(), KoDialog::setCaption(), KoDialog::setDefaultButton(), setFFmpegPath(), KoDialog::setMainWidget(), slotDialogAccepted(), slotExportTypeChanged(), slotLockAspectRatioDimensionsHeight(), slotLockAspectRatioDimensionsWidth(), KisTimeSpan::start(), and KisImportExportManager::supportedMimeTypes().

◆ ~KisDlgAnimationRenderer()

KisDlgAnimationRenderer::~KisDlgAnimationRenderer ( )
override

Definition at line 138 of file KisDlgAnimationRenderer.cpp.

139{
140 delete m_page;
141}

References m_page.

Member Function Documentation

◆ defaultVideoFileName()

QString KisDlgAnimationRenderer::defaultVideoFileName ( KisDocument * doc,
const QString & mimeType )
staticprivate

Definition at line 531 of file KisDlgAnimationRenderer.cpp.

532{
533 const QString docFileName = !doc->localFilePath().isEmpty() ? doc->localFilePath() : i18n("Untitled");
534
535 if (!mimeType.isEmpty()) {
536 return QString("%1.%2").arg(QFileInfo(docFileName).completeBaseName(),
537 KisMimeDatabase::suffixesForMimeType(mimeType).first());
538 } else {
539 return docFileName;
540 }
541}
QString localFilePath() const
static QStringList suffixesForMimeType(const QString &mimeType)

References KisDocument::localFilePath(), and KisMimeDatabase::suffixesForMimeType().

◆ ffmpegWarningCheck()

void KisDlgAnimationRenderer::ffmpegWarningCheck ( )
private

Definition at line 491 of file KisDlgAnimationRenderer.cpp.

491 {
492 const QString mimeType = m_page->cmbRenderType->itemData(m_page->cmbRenderType->currentIndex()).toString();
493
494 const QRegularExpression minVerFFMpegRX(R"(^n{0,1}(?:[0-3]|4\.[01])[\.\-])");
495 const QRegularExpressionMatch minVerFFMpegMatch = minVerFFMpegRX.match(ffmpegVersion);
496
497 QStringList warnings;
498
499 if (mimeType == "image/gif" && minVerFFMpegMatch.hasMatch()) {
500 warnings << i18nc("ffmpeg warning checks", "FFmpeg must be at least version 4.2+ for GIF transparency to work");
501 }
502
503 // m_page->bnRenderOptions->setEnabled(mimeType != "image/gif" && mimeType != "image/webp" && mimeType !=
504 // "image/png" );
505 if (mimeType == "image/gif" && m_page->intFramesPerSecond->value() > 50) {
506 warnings << i18nc("ffmpeg warning checks",
507 "Animated GIF images cannot have a framerate higher than 50. The framerate will be reduced "
508 "to 50 frames per second");
509 }
510
511 m_page->lblWarnings->setVisible(!warnings.isEmpty());
512
513 if (!warnings.isEmpty()) {
514 QString text = QString("<p><b>%1</b>").arg(i18n("Warning(s):"));
515 text.append("<ul>");
516 Q_FOREACH (const QString &warning, warnings) {
517 text.append("<li>");
518 text.append(warning.toHtmlEscaped());
519 text.append("</li>");
520 }
521 text.append("</ul></p>");
522 m_page->lblWarnings->setText(text);
523
524 m_page->lblWarnings->setPixmap(
525 m_page->lblWarnings->style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(QSize(32, 32)));
526 }
527
528 m_page->adjustSize();
529}

References ffmpegVersion, and m_page.

◆ filterMimeTypeListByAvailableEncoders()

QStringList KisDlgAnimationRenderer::filterMimeTypeListByAvailableEncoders ( const QStringList & mimeTypes)
private

Definition at line 341 of file KisDlgAnimationRenderer.cpp.

342{
343 QStringList retValue;
344
345 Q_FOREACH(const QString& mime, input) {
346 if ( mime == "video/x-matroska" ) {
347 if ( ffmpegCodecs.contains("h264") || ffmpegCodecs.contains("vp9") ) {
348 QList<QString> encodersPresent;
349 encodersPresent << ffmpegEncoderTypes["h264"] << ffmpegEncoderTypes["vp9"];
351 retValue << mime;
352 }
353 } else if (mime == "video/mp4") {
354 if ( ffmpegCodecs.contains("h264") || ffmpegCodecs.contains("vp9") ) {
355 QList<QString> encodersPresent;
356 encodersPresent << ffmpegEncoderTypes["h264"] << ffmpegEncoderTypes["vp9"];
358 retValue << mime;
359 }
360 } else if (mime == "video/webm") {
361 if ( ffmpegCodecs.contains("vp9") ) {
362 QList<QString> encodersPresent;
363 encodersPresent << ffmpegEncoderTypes["vp9"];
365 retValue << mime;
366 }
367 } else if (mime == "image/gif") {
368 if ( ffmpegCodecs.contains("gif") ) {
369 retValue << mime;
370 }
371 } else if (mime == "image/apng") {
372 if ( ffmpegCodecs.contains("apng") ) {
373 retValue << mime;
374 }
375 } else if (mime == "image/webp") {
376 if ( ffmpegCodecs.contains("webp") ) {
377 retValue << mime;
378 }
379 } else if (mime == "video/ogg") {
380 if ( ffmpegCodecs.contains("theora") ) {
381 retValue << mime;
382 }
383 }
384 }
385
386 return retValue;
387}
bool meetsEncoderRequirementsForContainer(KisVideoExportOptionsDialog::ContainerType encoderType, const QStringList &encodersPresent)
QMap< QString, QStringList > ffmpegEncoderTypes

References ffmpegCodecs, ffmpegEncoderTypes, meetsEncoderRequirementsForContainer(), KisVideoExportOptionsDialog::MKV, KisVideoExportOptionsDialog::MP4, and KisVideoExportOptionsDialog::WEBM.

◆ filterSequenceMimeTypes()

void KisDlgAnimationRenderer::filterSequenceMimeTypes ( QStringList & mimeTypes)
staticprivate

Definition at line 306 of file KisDlgAnimationRenderer.cpp.

307{
308 KritaUtils::filterContainer(mimeTypes, [](QString type) {
309 return (type.startsWith("image/")
310 || (type.startsWith("application/") &&
311 !type.startsWith("application/x-spriter")));
312 });
313}
auto filterContainer(C &container, KeepIfFunction keepIf) -> decltype(bool(keepIf(container[0])), void())

References KritaUtils::filterContainer().

◆ frameRateChanged

void KisDlgAnimationRenderer::frameRateChanged ( int framerate)
privateslot

Definition at line 801 of file KisDlgAnimationRenderer.cpp.

802{
803 Q_UNUSED(framerate);
805}

References ffmpegWarningCheck().

◆ getDefaultVideoEncoderOptions()

void KisDlgAnimationRenderer::getDefaultVideoEncoderOptions ( const QString & mimeType,
KisPropertiesConfigurationSP cfg,
const QStringList & availableEncoders,
QString * customFFMpegOptionsString,
bool * forceHDRVideo )
staticprivate

Definition at line 287 of file KisDlgAnimationRenderer.cpp.

292{
295
296 QScopedPointer<KisVideoExportOptionsDialog> encoderConfigWidget(
297 new KisVideoExportOptionsDialog(containerType, availableEncoders, 0));
298
299 // we always enable HDR, letting the user to force it
300 encoderConfigWidget->setSupportsHDR(true);
301 encoderConfigWidget->setConfiguration(cfg);
302 *customFFMpegOptionsString = encoderConfigWidget->customUserOptionsString();
303 *renderHDR = encoderConfigWidget->videoConfiguredForHDR();
304}
static ContainerType mimeToContainer(const QString &mimeType)

References KisVideoExportOptionsDialog::mimeToContainer().

◆ getEncoderOptions()

KisAnimationRenderingOptions KisDlgAnimationRenderer::getEncoderOptions ( ) const

Definition at line 670 of file KisDlgAnimationRenderer.cpp.

671{
673
675 options.videoMimeType = m_page->cmbRenderType->currentData().toString();
676 options.frameMimeType = m_page->cmbMimetype->currentData().toString();
677 options.scaleFilter = m_page->cmbScaleFilter->currentData().toString();
678
679 options.basename = m_page->txtBasename->text();
680 options.directory = m_page->dirRequester->fileName();
681 options.firstFrame = m_page->intStart->value();
682 options.lastFrame = m_page->intEnd->value();
683 options.sequenceStart = m_page->sequenceStart->value();
684
685 options.shouldEncodeVideo = m_page->shouldExportOnlyVideo->isChecked();
686 options.shouldDeleteSequence = !m_page->shouldExportOnlyImageSequence->isChecked();
687 options.includeAudio = m_page->chkIncludeAudio->isChecked();
688 options.wantsOnlyUniqueFrameSequence = m_page->chkOnlyUniqueFrames->isChecked();
689
690 options.ffmpegPath = m_page->ffmpegLocation->fileName();
691 options.frameRate = m_page->intFramesPerSecond->value();
692
693 if (options.frameRate > 50 && options.videoMimeType == "image/gif") {
694 options.frameRate = 50;
695 }
696
697 options.width = m_page->intWidth->value();
698 options.height = m_page->intHeight->value();
699 options.videoFileName = m_page->videoFilename->fileName();
700
702
703 {
705 if (cfg) {
707 }
708
709 const bool forceNecessaryHDRSettings = m_wantsRenderWithHDR && imageMimeSupportsHDR(options.frameMimeType);
710 if (forceNecessaryHDRSettings) {
711 KIS_SAFE_ASSERT_RECOVER_NOOP(options.frameMimeType == "image/png");
712 cfg->setProperty("forceSRGB", false);
713 cfg->setProperty("saveAsHDR", true);
714 }
715
716 options.frameExportConfig = cfg;
717 }
718
719 return options;
720}
KisPropertiesConfigurationSP frameExportConfig
static bool imageMimeSupportsHDR(QString &hdr)
static void fillStaticExportConfigurationProperties(KisPropertiesConfigurationSP exportConfiguration, KisImageSP image)
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130

References KisAnimationRenderingOptions::basename, KisAnimationRenderingOptions::customFFMpegOptions, KisAnimationRenderingOptions::directory, KisAnimationRenderingOptions::ffmpegPath, KisImportExportManager::fillStaticExportConfigurationProperties(), KisAnimationRenderingOptions::firstFrame, KisAnimationRenderingOptions::frameExportConfig, KisAnimationRenderingOptions::frameMimeType, KisAnimationRenderingOptions::frameRate, KisAnimationRenderingOptions::height, imageMimeSupportsHDR(), KisAnimationRenderingOptions::includeAudio, KIS_SAFE_ASSERT_RECOVER_NOOP, KisAnimationRenderingOptions::lastDocumentPath, KisAnimationRenderingOptions::lastFrame, loadLastConfiguration(), KisDocument::localFilePath(), m_customFFMpegOptionsString, m_doc, m_image, m_page, m_wantsRenderWithHDR, KisAnimationRenderingOptions::scaleFilter, KisAnimationRenderingOptions::sequenceStart, KisAnimationRenderingOptions::shouldDeleteSequence, KisAnimationRenderingOptions::shouldEncodeVideo, KisAnimationRenderingOptions::videoFileName, KisAnimationRenderingOptions::videoMimeType, KisAnimationRenderingOptions::wantsOnlyUniqueFrameSequence, and KisAnimationRenderingOptions::width.

◆ imageMimeSupportsHDR()

bool KisDlgAnimationRenderer::imageMimeSupportsHDR ( QString & hdr)
staticprivate

Definition at line 389 of file KisDlgAnimationRenderer.cpp.

390{
391 return (mime == "image/png");
392}

◆ initializeRenderSettings()

void KisDlgAnimationRenderer::initializeRenderSettings ( const KisDocument & doc,
const KisAnimationRenderingOptions & lastUsedOptions )
private

Definition at line 143 of file KisDlgAnimationRenderer.cpp.

144{
145 // Initialize FFmpeg location... (!)
146 KisConfig cfg(false);
147 QString cfgFFmpegPath = cfg.ffmpegLocation();
148#ifdef Q_OS_MACOS
149 if (cfgFFmpegPath.isEmpty()) {
150 QJsonObject ffmpegInfo = KisFFMpegWrapper::findFFMpeg(cfgFFmpegPath);
151 cfgFFmpegPath = (ffmpegInfo["enabled"].toBool()) ? ffmpegInfo["path"].toString() : "";
152 }
153#endif
154
155 // Check known ffmpeg locations..
156 QString likelyFFmpegPath = [&]() {
157 // Check last used
158 if (!lastUsedOptions.ffmpegPath.isEmpty() && QFileInfo(lastUsedOptions.ffmpegPath).isExecutable()) {
159 return lastUsedOptions.ffmpegPath;
160 }
161
162 // Check krita config
163 if (!cfgFFmpegPath.isEmpty() && QFileInfo(cfgFFmpegPath).isExecutable()) {
164 return cfgFFmpegPath;
165 }
166
167 // Check standard paths
168 QString systemFFmpeg = QStandardPaths::findExecutable("ffmpeg");
169 if (!systemFFmpeg.isEmpty() && QFileInfo(systemFFmpeg).isExecutable()) {
170 return systemFFmpeg;
171 }
172
173 // Find ffmpeg elsewhere...
174 QJsonObject ffmpegJsonObj = KisFFMpegWrapper::findFFMpeg("");
175 return (ffmpegJsonObj["enabled"].toBool()) ? ffmpegJsonObj["path"].toString() : "";
176 }();
177
178 if (!likelyFFmpegPath.isEmpty() && QFileInfo(likelyFFmpegPath).isExecutable()) {
179 setFFmpegPath(likelyFFmpegPath);
180 }
181
182 const QString documentPath = m_doc->localFilePath();
183
184 // Initialize these settings based on last used configuration when possible..
185 if (!lastUsedOptions.lastDocumentPath.isEmpty() &&
186 lastUsedOptions.lastDocumentPath == documentPath) {
187
188 // If the file is the same as last time, we use the last used basename.
189 m_page->txtBasename->setText(lastUsedOptions.basename);
190
191 m_page->sequenceStart->setValue(lastUsedOptions.sequenceStart);
192 m_page->intWidth->setValue(lastUsedOptions.width);
193 m_page->intHeight->setValue(lastUsedOptions.height);
194
195 m_page->videoFilename->setStartDir(lastUsedOptions.resolveAbsoluteDocumentFilePath(documentPath));
196 m_page->videoFilename->setFileName(lastUsedOptions.videoFileName);
197
198 m_page->dirRequester->setStartDir(lastUsedOptions.resolveAbsoluteDocumentFilePath(documentPath));
199 m_page->dirRequester->setFileName(lastUsedOptions.directory);
200 } else {
201 m_page->sequenceStart->setValue(m_image->animationInterface()->activePlaybackRange().start());
202 m_page->intWidth->setValue(m_image->width());
203 m_page->intHeight->setValue(m_image->height());
204
205 m_page->videoFilename->setStartDir(lastUsedOptions.resolveAbsoluteDocumentFilePath(documentPath));
206 m_page->videoFilename->setFileName(defaultVideoFileName(m_doc, lastUsedOptions.videoMimeType));
207
208 m_page->dirRequester->setStartDir(lastUsedOptions.resolveAbsoluteDocumentFilePath(documentPath));
209 m_page->dirRequester->setFileName(lastUsedOptions.directory);
210 }
211
212 // Initialize FRAME render format...
213 for (int i = 0; i < m_page->cmbMimetype->count(); ++i) {
214 if (m_page->cmbMimetype->itemData(i).toString() == lastUsedOptions.frameMimeType) {
215 m_page->cmbMimetype->setCurrentIndex(i);
216 break;
217 }
218 }
219
220 for (int i = 0; i < m_page->cmbScaleFilter->count(); ++i) {
221 if (m_page->cmbScaleFilter->itemData(i).toString() == lastUsedOptions.scaleFilter) {
222 m_page->cmbScaleFilter->setCurrentIndex(i);
223 break;
224 }
225 }
226
227 // Initialize VIDEO render format...
228 for (int i = 0; i < m_page->cmbRenderType->count(); ++i) {
229 if (m_page->cmbRenderType->itemData(i).toString() == lastUsedOptions.videoMimeType) {
230 m_page->cmbRenderType->setCurrentIndex(i);
231 break;
232 }
233 }
234
235 m_page->chkOnlyUniqueFrames->setChecked(lastUsedOptions.wantsOnlyUniqueFrameSequence);
236
237 m_page->shouldExportOnlyVideo->setChecked(lastUsedOptions.shouldEncodeVideo);
238 m_page->shouldExportOnlyImageSequence->setChecked(!lastUsedOptions.shouldDeleteSequence);
240
241 {
242 KisPropertiesConfigurationSP settings = loadLastConfiguration("VIDEO_ENCODER");
243
244 QStringList encodersPresent;
245 Q_FOREACH(const QString& key, ffmpegEncoderTypes.keys()) {
246 encodersPresent << ffmpegEncoderTypes[key];
247 }
248
249 getDefaultVideoEncoderOptions(lastUsedOptions.videoMimeType, settings,
250 encodersPresent,
253 }
254
255 {
256 KisPropertiesConfigurationSP settings = loadLastConfiguration("img_sequence/" + lastUsedOptions.frameMimeType);
257 m_wantsRenderWithHDR = settings->getPropertyLazy("saveAsHDR", m_wantsRenderWithHDR);
258 }
259
260 m_page->ffmpegLocation->setFileName(likelyFFmpegPath);
261 m_page->ffmpegLocation->setStartDir(QFileInfo(m_doc->localFilePath()).path());
262 m_page->ffmpegLocation->setReadOnlyText(true);
263
264 // Initialize these settings based on the current document context..
265 m_page->intStart->setValue(doc.image()->animationInterface()->activePlaybackRange().start());
266 m_page->intEnd->setValue(doc.image()->animationInterface()->activePlaybackRange().end());
267 m_page->intFramesPerSecond->setValue(doc.image()->animationInterface()->framerate());
268
269 if (!doc.image()->animationInterface()->exportSequenceFilePath().isEmpty()
270 && QDir(doc.image()->animationInterface()->exportSequenceFilePath()).exists() ) {
271 m_page->dirRequester->setStartDir(doc.image()->animationInterface()->exportSequenceFilePath());
272 m_page->dirRequester->setFileName(doc.image()->animationInterface()->exportSequenceFilePath());
273 }
274
275 if (!doc.image()->animationInterface()->exportSequenceBaseName().isEmpty()) {
276 m_page->txtBasename->setText(doc.image()->animationInterface()->exportSequenceBaseName());
277 }
278
279 if (doc.image()->animationInterface()->exportInitialFrameNumber() != -1) {
280 m_page->sequenceStart->setValue(doc.image()->animationInterface()->exportInitialFrameNumber());
281 }
282
283 bool hasAudioLoaded = doc.getAudioTracks().count() > 0;
284 m_page->chkIncludeAudio->setChecked(hasAudioLoaded);
285}
QString resolveAbsoluteDocumentFilePath(const QString &documentPath) const
static void getDefaultVideoEncoderOptions(const QString &mimeType, KisPropertiesConfigurationSP cfg, const QStringList &availableEncoders, QString *customFFMpegOptionsString, bool *forceHDRVideo)
static QString defaultVideoFileName(KisDocument *doc, const QString &mimeType)
static QJsonObject findFFMpeg(const QString &customLocation)
const KisTimeSpan & activePlaybackRange() const
activePlaybackRange
qint32 width() const
qint32 height() const
QString toString(const QString &value)

References KisImageAnimationInterface::activePlaybackRange(), KisImage::animationInterface(), KisAnimationRenderingOptions::basename, defaultVideoFileName(), KisAnimationRenderingOptions::directory, KisTimeSpan::end(), KisImageAnimationInterface::exportInitialFrameNumber(), KisImageAnimationInterface::exportSequenceBaseName(), KisImageAnimationInterface::exportSequenceFilePath(), ffmpegEncoderTypes, KisConfig::ffmpegLocation(), KisAnimationRenderingOptions::ffmpegPath, KisFFMpegWrapper::findFFMpeg(), KisAnimationRenderingOptions::frameMimeType, KisImageAnimationInterface::framerate(), KisDocument::getAudioTracks(), getDefaultVideoEncoderOptions(), KisImage::height(), KisAnimationRenderingOptions::height, KisDocument::image, KisAnimationRenderingOptions::lastDocumentPath, loadLastConfiguration(), KisDocument::localFilePath(), m_customFFMpegOptionsString, m_doc, m_image, m_page, m_wantsRenderWithHDR, KisAnimationRenderingOptions::resolveAbsoluteDocumentFilePath(), KisAnimationRenderingOptions::scaleFilter, KisAnimationRenderingOptions::sequenceStart, setFFmpegPath(), KisAnimationRenderingOptions::shouldDeleteSequence, KisAnimationRenderingOptions::shouldEncodeVideo, slotExportTypeChanged(), KisTimeSpan::start(), KisAnimationRenderingOptions::videoFileName, KisAnimationRenderingOptions::videoMimeType, KisAnimationRenderingOptions::wantsOnlyUniqueFrameSequence, KisImage::width(), and KisAnimationRenderingOptions::width.

◆ loadLastConfiguration()

KisPropertiesConfigurationSP KisDlgAnimationRenderer::loadLastConfiguration ( QString configurationID)
staticprivate

Definition at line 394 of file KisDlgAnimationRenderer.cpp.

394 {
395 KisConfig globalConfig(true);
396 return globalConfig.exportConfiguration(configurationID);
397}

References KisConfig::exportConfiguration().

◆ makeVideoMimeTypesList()

QStringList KisDlgAnimationRenderer::makeVideoMimeTypesList ( )
staticprivate

Definition at line 315 of file KisDlgAnimationRenderer.cpp.

316{
317 QStringList supportedMimeTypes = QStringList();
318 supportedMimeTypes << "video/x-matroska";
319 supportedMimeTypes << "video/mp4";
320 supportedMimeTypes << "video/webm";
321 supportedMimeTypes << "image/gif";
322 supportedMimeTypes << "image/apng";
323 supportedMimeTypes << "image/webp";
324 supportedMimeTypes << "video/ogg";
325
326 return supportedMimeTypes;
327}
QList< QString > QStringList

◆ saveLastUsedConfiguration()

void KisDlgAnimationRenderer::saveLastUsedConfiguration ( QString configurationID,
KisPropertiesConfigurationSP config )
staticprivate

Definition at line 399 of file KisDlgAnimationRenderer.cpp.

400{
401 KisConfig globalConfig(false);
402 globalConfig.setExportConfiguration(configurationID, config);
403}

References KisConfig::setExportConfiguration().

◆ selectRenderOptions

void KisDlgAnimationRenderer::selectRenderOptions ( )
privateslot

Definition at line 587 of file KisDlgAnimationRenderer.cpp.

588{
589 const int index = m_page->cmbRenderType->currentIndex();
590 const QString mimetype = m_page->cmbRenderType->itemData(index).toString();
591
594
595 QStringList encodersPresent;
596 Q_FOREACH(const QString& key, ffmpegEncoderTypes.keys()) {
597 encodersPresent << ffmpegEncoderTypes[key];
598 }
599
600 KisVideoExportOptionsDialog *encoderConfigWidget =
601 new KisVideoExportOptionsDialog(containerType, encodersPresent, this);
602
603 // we always enable HDR, letting the user to force it
604 encoderConfigWidget->setSupportsHDR(true);
605
606 {
607 KisPropertiesConfigurationSP settings = loadLastConfiguration("VIDEO_ENCODER");
608 encoderConfigWidget->setConfiguration(settings);
609 encoderConfigWidget->setHDRConfiguration(m_wantsRenderWithHDR);
610 }
611
612 KoDialog dlg(this);
613 dlg.setMainWidget(encoderConfigWidget);
614 dlg.setButtons(KoDialog::Ok | KoDialog::Cancel);
615 if (dlg.exec() == QDialog::Accepted) {
616 saveLastUsedConfiguration("VIDEO_ENCODER", encoderConfigWidget->configuration());
618 m_wantsRenderWithHDR = encoderConfigWidget->videoConfiguredForHDR();
619 }
620
621 dlg.setMainWidget(0);
622 encoderConfigWidget->deleteLater();
623}
static void saveLastUsedConfiguration(QString configurationID, KisPropertiesConfigurationSP config)
KisPropertiesConfigurationSP configuration() const override
void setConfiguration(const KisPropertiesConfigurationSP config) override
A dialog base class with standard buttons and predefined layouts.
Definition KoDialog.h:116

References KoDialog::Cancel, KisVideoExportOptionsDialog::configuration(), KisVideoExportOptionsDialog::customUserOptionsString(), ffmpegEncoderTypes, loadLastConfiguration(), m_customFFMpegOptionsString, m_page, m_wantsRenderWithHDR, KisVideoExportOptionsDialog::mimeToContainer(), KoDialog::Ok, saveLastUsedConfiguration(), KoDialog::setButtons(), KisVideoExportOptionsDialog::setConfiguration(), KisVideoExportOptionsDialog::setHDRConfiguration(), KoDialog::setMainWidget(), KisVideoExportOptionsDialog::setSupportsHDR(), and KisVideoExportOptionsDialog::videoConfiguredForHDR().

◆ selectRenderType

void KisDlgAnimationRenderer::selectRenderType ( int i)
privateslot

Definition at line 543 of file KisDlgAnimationRenderer.cpp.

544{
545 if (m_page->cmbRenderType->count() == 0) return;
546
547 const QString mimeType = m_page->cmbRenderType->itemData(index).toString();
548
549 /*
550 m_page->bnRenderOptions->setEnabled(mimeType != "image/gif" && mimeType != "image/webp" && mimeType != "image/png");
551 */
552
554
555 QString videoFileName = defaultVideoFileName(m_doc, mimeType);
556
557 if (!m_page->videoFilename->fileName().isEmpty()) {
558 const QFileInfo info = QFileInfo(m_page->videoFilename->fileName());
559 const QString baseName = info.completeBaseName();
560 const QString path = info.path();
561
562 videoFileName = QString("%1%2%3.%4")
563 .arg(path, "/", baseName, KisMimeDatabase::suffixesForMimeType(mimeType).first());
564 }
565 m_page->videoFilename->setMimeTypeFilters(QStringList() << mimeType, mimeType);
566 m_page->videoFilename->setFileName(videoFileName);
567
568 m_wantsRenderWithHDR = (mimeType == "video/mp4") ? m_wantsRenderWithHDR : false;
569
570 { // We've got to reload the render settings to account for the user changing render type without configuration.
571 // If this is removed from the configuration, ogg vorbis can fail to render on first attempt. BUG:421658
572 // This should be revisited at some point, too much configuration juggling in this class makes it error-prone...
573
574 QStringList encodersPresent;
575 Q_FOREACH(const QString& key, ffmpegEncoderTypes.keys()) {
576 encodersPresent << ffmpegEncoderTypes[key];
577 }
578
579 KisPropertiesConfigurationSP settings = loadLastConfiguration("VIDEO_ENCODER");
580 getDefaultVideoEncoderOptions(mimeType, settings,
581 encodersPresent,
584 }
585}

References defaultVideoFileName(), ffmpegEncoderTypes, ffmpegWarningCheck(), getDefaultVideoEncoderOptions(), loadLastConfiguration(), m_customFFMpegOptionsString, m_doc, m_page, m_wantsRenderWithHDR, and KisMimeDatabase::suffixesForMimeType().

◆ sequenceMimeTypeOptionsClicked

void KisDlgAnimationRenderer::sequenceMimeTypeOptionsClicked ( )
privateslot

sequenceMimeTypeSelected calls the dialog for the export widget.

Definition at line 625 of file KisDlgAnimationRenderer.cpp.

626{
627 int index = m_page->cmbMimetype->currentIndex();
628
629 KisConfigWidget *frameExportConfigWidget = 0;
630
631 QString mimetype = m_page->cmbMimetype->itemData(index).toString();
633 if (filter) {
634 frameExportConfigWidget = filter->createConfigurationWidget(0, KisDocument::nativeFormatMimeType(), mimetype.toLatin1());
635
636 if (frameExportConfigWidget) {
637
638 KisPropertiesConfigurationSP exportConfig = loadLastConfiguration("img_sequence/" + mimetype);
639 if (exportConfig) {
641 }
642
643 //Important -- m_useHDR allows the synchronization of both the video and image render settings.
644 if(imageMimeSupportsHDR(mimetype)) {
645 exportConfig->setProperty("saveAsHDR", m_wantsRenderWithHDR);
647 exportConfig->setProperty("forceSRGB", false);
648 }
649 }
650
651 frameExportConfigWidget->setConfiguration(exportConfig);
652 KoDialog dlg(this);
653 dlg.setMainWidget(frameExportConfigWidget);
654 dlg.setButtons(KoDialog::Ok | KoDialog::Cancel);
655 if (dlg.exec() == QDialog::Accepted) {
656 m_wantsRenderWithHDR = frameExportConfigWidget->configuration()->getPropertyLazy("saveAsHDR", false);
657 saveLastUsedConfiguration("img_sequence/" + mimetype, frameExportConfigWidget->configuration());
658 }
659
660 frameExportConfigWidget->hide();
661 dlg.setMainWidget(0);
662 frameExportConfigWidget->setParent(0);
663 frameExportConfigWidget->deleteLater();
664
665 }
666 }
667}
virtual KisPropertiesConfigurationSP configuration() const =0
virtual void setConfiguration(const KisPropertiesConfigurationSP config)=0
static QByteArray nativeFormatMimeType()
static KisImportExportFilter * filterForMimeType(const QString &mimetype, Direction direction)
filterForMimeType loads the relevant import/export plugin and returns it. The caller is responsible f...

References KoDialog::Cancel, KisConfigWidget::configuration(), KisImportExportManager::Export, KisImportExportManager::fillStaticExportConfigurationProperties(), KisImportExportManager::filterForMimeType(), imageMimeSupportsHDR(), loadLastConfiguration(), m_image, m_page, m_wantsRenderWithHDR, KisDocument::nativeFormatMimeType(), KoDialog::Ok, saveLastUsedConfiguration(), KoDialog::setButtons(), KisConfigWidget::setConfiguration(), and KoDialog::setMainWidget().

◆ setFFmpegPath

void KisDlgAnimationRenderer::setFFmpegPath ( const QString & path)
privateslot

Definition at line 405 of file KisDlgAnimationRenderer.cpp.

405 {
406 // Let's START with the assumption that user-specified ffmpeg path is invalid
407 // and clear out all of the ffmpeg-specific fields to fill post-validation...
408 m_page->cmbRenderType->setDisabled(true);
409 m_page->bnRenderOptions->setDisabled(true);
410
411 QString previousMimeType = m_page->cmbRenderType->currentData().toString();
412
413 m_page->cmbRenderType->clear();
414 ffmpegEncoderTypes.clear();
415
416 // Validate FFmpeg binary and setup FFMpeg...
417 if (validateFFmpeg(path)) {
418 QJsonObject ffmpegJsonObj = KisFFMpegWrapper::findFFMpeg(path);
419 ffmpegVersion = ffmpegJsonObj["enabled"].toBool() ? ffmpegJsonObj["version"].toString() : i18n("No valid FFmpeg binary supplied...");
421
422 // Build map of encoding types to their specific encoder support (e.g. h264 => libopenh264, h264, h264_vaapi or whatever)
423 Q_FOREACH(const QString& codec, ffmpegCodecs) {
424 QJsonObject codecjson = ffmpegJsonObj["codecs"].toObject()[codec].toObject();
425 if ( codecjson["encoding"].toBool() ) {
426 QJsonArray codecEncoders = codecjson["encoders"].toArray();
427
428 // In the case where no specific codec "library" is specified but we do support
429 // encoding, we simply push the type onto the list regardless. This basically
430 // means that there's no "specific" requirements that we need to meet and
431 // encoding should be possible.
432 if (codecEncoders.size() == 0) {
433 codecEncoders.push_back(QJsonValue(codec));
434 }
435
436 Q_FOREACH(const QJsonValue& value, codecEncoders) {
437 if (ffmpegEncoderTypes.contains(codec)) {
438 ffmpegEncoderTypes[codec].push_back(value.toString());
439 } else {
440 ffmpegEncoderTypes.insert(codec, {value.toString()} );
441 }
442 }
443 }
444 }
445
446 KisConfig cfg(false);
447
448 { // Build list of supported container types and repopulate cmbRenderType.
449 KisSignalsBlocker(m_page->cmbRenderType);
450
451 QStringList supportedMimeTypes = makeVideoMimeTypesList();
452 supportedMimeTypes = filterMimeTypeListByAvailableEncoders(supportedMimeTypes);
453
454 int previousMimeTypeIndex = -1;
455 Q_FOREACH (const QString &mime, supportedMimeTypes) {
456 QString description = KisMimeDatabase::descriptionForMimeType(mime);
457 if (description.isEmpty()) {
458 description = mime;
459 }
460
461 m_page->cmbRenderType->addItem(description, mime);
462 if (mime == previousMimeType) {
463 previousMimeTypeIndex = m_page->cmbRenderType->count() - 1;
464 }
465 }
466
467 const int indexCount = m_page->cmbRenderType->count();
468 if (indexCount > 0) {
469 if (previousMimeTypeIndex >= 0) {
470 m_page->cmbRenderType->setCurrentIndex(previousMimeTypeIndex % indexCount);
471 } else {
472 m_page->cmbRenderType->setCurrentIndex(0);
473 }
474
475 selectRenderType(m_page->cmbRenderType->currentIndex());
476 m_page->cmbRenderType->setDisabled(false);
477 m_page->bnRenderOptions->setDisabled(false);
478 connect(m_page->cmbRenderType, SIGNAL(currentIndexChanged(int)), this, SLOT(selectRenderType(int)));
479 }
480 }
481
482 m_page->lblFFMpegVersion->setText(ffmpegVersion);
483
484 // Store configuration..
485 cfg.setFFMpegLocation(ffmpegJsonObj["path"].toString());
486
488 }
489}
float value(const T *src, size_t ch)
QStringList filterMimeTypeListByAvailableEncoders(const QStringList &mimeTypes)
FFmpegValidationResult validateFFmpeg(const QString &ffmpegPath)
static QStringList makeVideoMimeTypesList()
static QStringList getSupportedCodecs(const QJsonObject &ffmpegJsonProcessInput)

References connect(), KisMimeDatabase::descriptionForMimeType(), ffmpegCodecs, ffmpegEncoderTypes, ffmpegVersion, ffmpegWarningCheck(), filterMimeTypeListByAvailableEncoders(), KisFFMpegWrapper::findFFMpeg(), KisFFMpegWrapper::getSupportedCodecs(), m_page, makeVideoMimeTypesList(), selectRenderType(), KisConfig::setFFMpegLocation(), validateFFmpeg(), and value().

◆ slotButtonClicked

void KisDlgAnimationRenderer::slotButtonClicked ( int button)
overrideprotectedslot

Definition at line 741 of file KisDlgAnimationRenderer.cpp.

742{
743 if (button == KoDialog::Ok && !m_page->shouldExportOnlyImageSequence->isChecked()) {
744 QString fileName = m_page->videoFilename->fileName();
745
746 if (fileName.isEmpty()) {
747 QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("Please enter a file name to render to."));
748 return;
749 }
750 else {
751 switch (validateFFmpeg(m_page->ffmpegLocation->fileName())) {
753 QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("The FFmpeg that you've given us appears to be compressed. Please try to extract FFmpeg from the archive first."));
754 return;
756 QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("The FFmpeg that you've given us appears to be invalid. Please select the correct location of an FFmpeg executable on your system."));
757 return;
758 default:
759 break;
760 }
761 }
762 }
764}
virtual void slotButtonClicked(int button)
Definition KoDialog.cpp:820
QPushButton * button(ButtonCode id) const
Definition KoDialog.cpp:591

References KoDialog::button(), COMPRESSED_FORMAT, m_page, NOT_A_BINARY, KoDialog::Ok, KoDialog::slotButtonClicked(), and validateFFmpeg().

◆ slotDialogAccepted

void KisDlgAnimationRenderer::slotDialogAccepted ( )
protectedslot

Definition at line 766 of file KisDlgAnimationRenderer.cpp.

767{
768 KisConfig cfg(false);
770 saveLastUsedConfiguration("ANIMATION_EXPORT", options.toProperties());
771
775}
KisPropertiesConfigurationSP toProperties() const
KisAnimationRenderingOptions getEncoderOptions() const
void setExportSequenceBaseName(const QString &baseName)
void setExportInitialFrameNumber(const int frameNum)
void setExportSequenceFilePath(const QString &filePath)

References KisImage::animationInterface(), KisAnimationRenderingOptions::basename, KisAnimationRenderingOptions::directory, getEncoderOptions(), m_image, saveLastUsedConfiguration(), KisAnimationRenderingOptions::sequenceStart, KisImageAnimationInterface::setExportInitialFrameNumber(), KisImageAnimationInterface::setExportSequenceBaseName(), KisImageAnimationInterface::setExportSequenceFilePath(), and KisAnimationRenderingOptions::toProperties().

◆ slotExportTypeChanged

void KisDlgAnimationRenderer::slotExportTypeChanged ( )
privateslot

A fallback fix for a case when both checkboxes are unchecked

Definition at line 777 of file KisDlgAnimationRenderer.cpp.

778{
779 KisConfig cfg(false);
780
781 const bool willEncodeVideo = m_page->shouldExportOnlyVideo->isChecked();
782
783 // if a video format needs to be outputted
784 if (willEncodeVideo) {
785 // videos always uses PNG for creating video, so disable the ability to change the format
786 m_page->cmbMimetype->setEnabled(false);
787 m_page->cmbMimetype->setCurrentIndex(m_page->cmbMimetype->findData("image/png"));
788 }
789
793 if (!m_page->shouldExportOnlyVideo->isChecked() &&
794 !m_page->shouldExportOnlyImageSequence->isChecked()) {
795
796 KisSignalsBlocker b(m_page->shouldExportOnlyImageSequence);
797 m_page->shouldExportOnlyImageSequence->setChecked(true);
798 }
799}

References m_page.

◆ slotLockAspectRatioDimensionsHeight

void KisDlgAnimationRenderer::slotLockAspectRatioDimensionsHeight ( int height)
privateslot

Definition at line 820 of file KisDlgAnimationRenderer.cpp.

821{
822 Q_UNUSED(height);
823
824 float aspectRatio = (float)m_image->width() / (float)m_image->height();
825
826 // update width here
827 float newWidth = aspectRatio * m_page->intHeight->value();
828
829 m_page->intWidth->setValue(newWidth);
830}

References KisImage::height(), m_image, m_page, and KisImage::width().

◆ slotLockAspectRatioDimensionsWidth

void KisDlgAnimationRenderer::slotLockAspectRatioDimensionsWidth ( int width)
privateslot

Definition at line 807 of file KisDlgAnimationRenderer.cpp.

808{
809 Q_UNUSED(width);
810
811 float aspectRatio = (float)m_image->width() / (float)m_image->height();
812
813 // update height here
814 float newHeight = m_page->intWidth->value() / aspectRatio ;
815
816 m_page->intHeight->setValue(newHeight);
817
818}

References KisImage::height(), m_image, m_page, and KisImage::width().

◆ validateFFmpeg()

KisDlgAnimationRenderer::FFmpegValidationResult KisDlgAnimationRenderer::validateFFmpeg ( const QString & ffmpegPath)
private

Definition at line 722 of file KisDlgAnimationRenderer.cpp.

723{
724 if (!ffmpegPath.isEmpty()) {
725 QFileInfo ffmpegBinary(ffmpegPath);
726 if (ffmpegBinary.exists() && ffmpegBinary.isExecutable()) {
727 QStringList commpressedFormats{"zip", "7z", "tar.bz2"};
728 Q_FOREACH(const QString& compressedFormat, commpressedFormats) {
729 if (ffmpegBinary.fileName().endsWith(compressedFormat)) {
731 }
732 }
734 } else if (ffmpegBinary.exists()) {
736 }
737 }
739}

References COMPRESSED_FORMAT, INVALID, NOT_A_BINARY, and VALID.

Member Data Documentation

◆ ffmpegCodecs

QStringList KisDlgAnimationRenderer::ffmpegCodecs = QStringList()
private

Definition at line 108 of file KisDlgAnimationRenderer.h.

◆ ffmpegEncoderTypes

QMap<QString, QStringList> KisDlgAnimationRenderer::ffmpegEncoderTypes
private

Definition at line 109 of file KisDlgAnimationRenderer.h.

◆ ffmpegVersion

QString KisDlgAnimationRenderer::ffmpegVersion = "None"
private

Definition at line 106 of file KisDlgAnimationRenderer.h.

◆ m_customFFMpegOptionsString

QString KisDlgAnimationRenderer::m_customFFMpegOptionsString
private

Definition at line 105 of file KisDlgAnimationRenderer.h.

◆ m_doc

KisDocument* KisDlgAnimationRenderer::m_doc
private

Definition at line 103 of file KisDlgAnimationRenderer.h.

◆ m_image

KisImageSP KisDlgAnimationRenderer::m_image
private

Definition at line 102 of file KisDlgAnimationRenderer.h.

◆ m_page

WdgAnimationRenderer* KisDlgAnimationRenderer::m_page {0}
private

Definition at line 113 of file KisDlgAnimationRenderer.h.

113{0};

◆ m_wantsRenderWithHDR

bool KisDlgAnimationRenderer::m_wantsRenderWithHDR = false
private

Definition at line 111 of file KisDlgAnimationRenderer.h.


The documentation for this class was generated from the following files: